Hi there,
@Emil published a very cool and new release of dash-extensions
yesterday. It brings a lot of useful special components. Today I’m going to try EventSource
, which is a component for listening to Server-Sent Events (SSE).
I’m going to use it to display logs on a web page. This is the result.
First, we should have a log file, let me use logging
to simulate a log output.
import logging
import time
logging.basicConfig(
level=logging.DEBUG,
filename="/tmp/test.log",
format="%(levelname)-8s : %(message)s",
)
s = 1
while True:
logging.warning(f"I'm warning {s}.")
time.sleep(3)
s += 1
Then read the log and stream it out.
import asyncio
import uvicorn
import tailer
from sse_starlette import EventSourceResponse
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
middleware = Middleware(CORSMiddleware, allow_origins=["*"], allow_headers=["*"])
server = Starlette(middleware=[middleware])
async def logCheck(request):
for line in tailer.follow(open("/tmp/test.log")):
if await request.is_disconnected():
print("Disconnected.")
break
await asyncio.sleep(1)
yield line
@server.route("/log")
async def sse(request):
generator = logCheck(request)
return EventSourceResponse(generator)
if __name__ == "__main__":
uvicorn.run(server, port=5000)
Next, the Dash application.
from dash_extensions import EventSource, Purify
from dash_extensions.enrich import (
html,
Output,
Input,
State,
DashProxy,
ClientsideFunction,
)
# Create small example app.
app = DashProxy(__name__)
app.layout = html.Div(
[
EventSource(id="sse", url="http://127.0.0.1:5000/log"),
Purify(id="log-output", className="log-box"),
]
)
app.clientside_callback(
ClientsideFunction(namespace="clientside", function_name="update_log"),
Output("log-output", "html"),
Input("sse", "message"),
State("log-output", "html"),
)
if __name__ == "__main__":
app.run_server(debug=True)
window.dash_clientside = Object.assign({}, window.dash_clientside, {
clientside: {
update_log: (msg, html) => {
if (!msg) { return };
if (!html) {
return '<pre>' +
msg.replace('WARNING', "<span class='log-color--purple'>WARNING</span>") + '</pre>';
} else {
return html + '<pre>' +
msg.replace('WARNING', "<span class='log-color--purple'>WARNING</span>") + '</pre>';
};
}
}
});
It looks like I might have to find a component dedicated to displaying logs to have a good outcome.
Does anyone have a good recommendation?
Hope you like this. XD
Keywords: SSE, Server-Sent Event, dash-extensions, EventSource, logging, WebSocket
Other Daily Tips series:
Daily Tips - If I have a Bunch of Triggers
Daily Tips - Share the Function
Daily Tips - How many Ways to share Dash in a company?
Daily Tips - Give your Component a Name
Daily Tips - Share Dash to Social Media
Daily Tips - Double-click to open Dash
Daily Tips - What rows of data have I modified?
Daily Tips - Write the Simplest Client-side Callback
Daily Tips - Some simple Expressions
Daily Tips - IoT? Real Real-time Data and Live Update
Daily Tips - Which formatter is your favorite?
Daily Tips - Convert a React Component to Dash