Runtime logs - Blueye SDK

Skip to content

# Log statements from the blueye.sdk

The `blueye.sdk` package uses the standard Python logging module to log information about the SDK's operation. The log statements are useful for debugging and troubleshooting, and can be used to get a better understanding of what is happening inside the SDK.

Note: These logs must not be confused with the divelogs that are generated and stored on the drone. See Listing and downloading logfiles for instructions on how to get the divelogs.

Events with severity `WARNING` or greater are printed to `sys.stderr` by default, but can be configured to be written to a file or sent to a remote server. See the Python logging documentation for more information about how to configure the logging module.

## Enabling logging with lower severity

By default, the events with severity lower than `WARNING` are muted. To enable them, you need to configure the logger to capture the logs. Here's an example of how to enable debug logs:

    import logging
    import blueye.sdk

    def enable_debug_logs():
        # Set the logger configuration
        logger = logging.getLogger(blueye.sdk.__name__)
        logger.setLevel(logging.DEBUG)

        # Define the log handler
        handler = logging.StreamHandler()
        handler.setLevel(logging.DEBUG)

        # Define the log format
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)

        # Add the log handler to the logger
        logger.addHandler(handler)

In the example above, we import the necessary modules and create a function `enable_runtime_logs()` to enable the runtime logs. We configure the logger to capture logs with the `logging.getLogger(blueye.sdk.__name__)` statement and set the log level to `DEBUG` to capture all logs.

We also define a log handler to determine where the logs should be outputted. In this example, we use a `logging.StreamHandler()` to print the logs to the console. You can customize the log handler based on your requirements, such as writing logs to a file or sending them to a remote server.

Finally, we set the log format using `logging.Formatter()` and add the log handler to the logger using `logger.addHandler(handler)`.

## Disabling Logging

If you want to completely disable logging and prevent any logs from being captured, you can use a `NullHandler`. Here's an example:

    import logging
    import blueye.sdk

    def disable_logging():
        # Disable all logging
        logger = logging.getLogger(blueye.sdk.__name__)
        logger.addHandler(logging.NullHandler())

In the example above, we define a function `disable_logging()` that sets a `NullHandler` to the logger. The `NullHandler` is a special handler that essentially discards all log records, effectively disabling logging.

## Receiving logs in another terminal

Sometimes the program output can become quite cluttered if the logs are being printed inbetween the program output. In such cases, it can be useful to run the program in one terminal and then run a separate terminal to read the logs. This can be accomblished by configuring a simple TCP server to listen for log messages. Here's an example of how to do this:

    import logging
    import logging.handlers
    import socketserver
    import struct

    class LogRecordStreamHandler(socketserver.StreamRequestHandler):
        def handle(self):
            while True:
                chunk = self.connection.recv(4)
                if len(chunk) < 4:
                    break
                slen = struct.unpack(">L", chunk)[0]
                chunk = self.connection.recv(slen)
                while len(chunk) < slen:
                    chunk = chunk + self.connection.recv(slen - len(chunk))
                obj = self.unPickle(chunk)
                record = logging.makeLogRecord(obj)
                self.handleLogRecord(record)

        def unPickle(self, data):
            import pickle

            return pickle.loads(data)

        def handleLogRecord(self, record):
            logger = logging.getLogger(record.name)
            logger.handle(record)

    class LogRecordSocketReceiver(socketserver.ThreadingTCPServer):
        allow_reuse_address = True

        def __init__(
            self,
            host="localhost",
            port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
            handler=LogRecordStreamHandler,
        ):
            socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)

    logging.basicConfig(
        level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s:\n    %(message)s\n"
    )
    tcpserver = LogRecordSocketReceiver()
    print("Starting logging server...")
    tcpserver.serve_forever()

And then we need to configure the SDKs logger to send the logs to this server.

    from blueye.sdk import Drone

    # Set up logging
    logger = logging.getLogger("blueye.sdk")
    logger.setLevel(logging.INFO)
    socket_handler = logging.handlers.SocketHandler(
        "localhost", logging.handlers.DEFAULT_TCP_LOGGING_PORT
    )
    logger.addHandler(socket_handler)

    d = Drone()

    # Logs from the SDK will now be sent to the logging server