1

I want to write a record created by a logging handler to a webpage by passing that record through a Flask SocketIO socket (i.e. print the same log message I get at the console to a webpage).

I see many handlers are available, but none of them appear to readily suit this case. Maybe I need a custom handler?

class MessagePaneHandler:
    # some log data is received 
    socketio.emit("event_name", log_message_from_handler, namespace="/some_namespace", broadcast=True)

Update:

As far as I can tell, the logging.handlers.SocketHandler writes to a raw TCP socket. Can I use a logging.handlers.SocketHandler to write to a Flask SocketIO socket instead? If so, how?

If it helps, this is how I set up my socket on the front end:

var socket = io.connect("http://" + document.domain + ":" + location.port + "/some_namespace");
3
  • SocketHandler is not what you want, that writes to a standard networking socket, which is much more lower lever than Socket.IO. I think you'll need to write your own logging handler, I'm not aware of any that sends logs via Socket.IO. Commented Aug 22, 2020 at 18:30
  • @MiguelGrinberg is writing an own socket handler if someone wants to write to Flask SocketIO still the way to go? Commented May 31, 2023 at 15:25
  • 1
    @j0da to my knowledge there is no other option, so yes. Commented May 31, 2023 at 23:00

1 Answer 1

2

As far as I could find, none of the built in handlers do this. This custom handler did the trick for me:


from flask_socketio import SocketIO
socketio = SocketIO()

class SocketIOHandler(logging.Handler):
    """A logging handler that emits records with SocketIO."""

    def __init__(self):
        super().__init__()

    def emit(self, record):
        asctime = record.__dict__["asctime"]
        msecs = record.__dict__["msecs"]
        levelname = record.__dict__["levelname"]
        module = record.__dict__["module"]
        message = record.__dict__["message"]
        msg = f"{asctime}.{round(msecs):03} [{levelname:<5.5s}]  {module:<18s}  {message}"
        socketio.emit("update_message_box", msg, namespace="/printing", broadcast=True)
Sign up to request clarification or add additional context in comments.

2 Comments

This is fantastic! I'm not sure whether this ties into some version of Python or whatever, but I could just access record.asctime, record.levelname etc., from the LogRecord instance attributes. Also: it probably makes sense to return early if socketio.server is None. Other than that I have only gratitude for your implementation.
Note: this only works if socketio.emit is synchronous

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.