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.get_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.NOTSET) 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 handler. Usually a log level of `logging.NOTSET` is appropriate. This does not do any extra filtering, and so will use the log level of the logger to which it is attached. .. 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:: get_thing_logger(thing_name: str | None = None) -> logging.Logger Return the Thing Logger, or a child logger. This function returns either the Thing logger, or a child of it. Any messages logged to this logger will be picked up by invocation logs, if they are logged from an invocation thread/context. ``thing.logger`` is equivalent to ``get_thing_logger(thing.name)`` for any `~lt.Thing` instance. :param thing_name: the name of a `lt.Thing`\ . If supplied, we will get a child logger (i.e. ``labthings_fastapi.things.{thing_name}``). By default, the root Thing logger (``labthings_fastapi.things``) is returned. :return: the Thing logger or a child of it. .. 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.