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