labthings_fastapi.logs ====================== .. py:module:: labthings_fastapi.logs .. autoapi-nested-parse:: Log-related functions and classes. This module currently contains code that allows us to filter out logs by invocaton ID, so that they may be returned when invocations are queried. Attributes ---------- .. autoapisummary:: labthings_fastapi.logs.THING_LOGGER Classes ------- .. autoapisummary:: labthings_fastapi.logs.DequeByInvocationIDHandler Functions --------- .. autoapisummary:: labthings_fastapi.logs.inject_invocation_id labthings_fastapi.logs.configure_thing_logger labthings_fastapi.logs.add_thing_log_destination Module Contents --------------- .. py:data:: THING_LOGGER .. py:function:: inject_invocation_id(record: logging.LogRecord) -> bool Add the invocation ID to records. This function adds the current invocation ID to log records. If it is not available, we set the record's ``invocation_id`` property to `None`\ . :param record: the `logging.LogRecord` object to modify. :return: `True` (which signals we should keep every record if this is used as a filter). .. py:class:: DequeByInvocationIDHandler(level: int = logging.INFO) Bases: :py:obj:`logging.Handler` A log handler that stores entries in memory. Set up a log handler that appends messages to a deque. .. warning:: This log handler does not currently rotate or truncate the list. It's best to use a `deque` with a finite capacity to avoid memory leaks. :param level: sets the level of the logger. For most invocations, a log level of `logging.INFO` is appropriate. .. py:attribute:: destinations .. py:method:: add_destination_for_id(id: uuid.UUID, destination: collections.abc.MutableSequence) -> None Append logs matching ``id`` to a specified sequence. :param id: the ``invocation_id`` to match. :param destination: should specify a deque, to which we will append each log entry as it comes in. This is assumed to be thread safe. .. py:method:: emit(record: logging.LogRecord) -> None Save a log record to the destination deque. :param record: the `logging.LogRecord` object to add. .. py:function:: configure_thing_logger(level: int | None = None) -> None Set up the logger for thing instances. We always set the logger for thing instances to level INFO by default, as this is currently used to relay progress to the client. This function will collect logs on a per-invocation basis by adding a `.DequeByInvocationIDHandler` to the log. Only one such handler will be added - subsequent calls are ignored. Unfortunately, filters must be added to every sub-logger, so globally adding a filter to add invocation ID is not possible. Instead, we attach a filter to the handler, which filters all the records that propagate to it (i.e. anything that starts with ``labthings_fastapi.things``). :param level: the logging level to use. If not specified, we use INFO. .. py:function:: add_thing_log_destination(invocation_id: uuid.UUID, destination: collections.abc.MutableSequence) -> None Append logs matching ``invocation_id`` to a specified sequence. This instructs a handler on the logger used for `~lt.Thing` instances to append a copy of the logs generated by that invocation to the specified sequence. This is primarily used by invocation threads to collect their logs, so they may be returned when the invocation is queried. :param invocation_id: the ``invocation_id`` to match. :param destination: should specify a deque, to which we will append each log entry as it comes in. This is assumed to be thread safe. :raises LogConfigurationError: if there is not exactly one suitable handler.