Source code for fastcs.tracer

from collections import defaultdict
from typing import Any

from fastcs.logging import logger


[docs] class Tracer: """A mixin or standalone class for conditionally logging trace events. This can be used for verbose logging that is disabled by default and enabled on a per-instance basis, with filtering based on specific key-value pairs on the event. Any instance of this class can enable tracing independently. Some key classes inherit this class, such as ``Attributes``, and some modules have their own ``Tracer``, such as ``fastcs.launch``. When enabled, any event logged from the object, or from another ``Tracer`` that uses the object as the ``topic``, will be logged. Note: The global logger level must be set to ``TRACE`` for the messages to be logged Example usage: .. code-block:: python controller.ramp_rate.enable_tracing() controller.ramp_rate.disable_tracing() controller.connection.enable_tracing() controller.connection.add_tracing_filter("query", "V?") controller.connection.remove_tracing_filter("query", "V?") controller.connection.disable_tracing() :param name: The name of the logger. Attached to log messages as ``logger_name``. """ def __init__(self, name: str | None = None): self.__tracing_enabled: bool = False self.__tracing_filters: dict[str, list[Any]] = defaultdict(list) self.__logger_name = name if name is not None else self.__class__.__name__
[docs] def log_event(self, event: str, topic: "Tracer | None" = None, *args, **kwargs): """Log an event only if tracing is enabled and the filter matches :param event: A message describing the event :param topic: Another `Tracer` related to this event to enable it to be logged :param args: Positional arguments for underlying logger :param kwargs: Keyword arguments for underlying logger """ if self.__tracing_enabled or (topic is not None and topic.__tracing_enabled): # noqa: SLF001 if self.__tracing_filters: for kwarg, values in self.__tracing_filters.items(): if kwarg in kwargs and any(kwargs[kwarg] == v for v in values): break else: return logger.trace(event, *args, logger_name=self.__logger_name, **kwargs)
[docs] def enable_tracing(self): """Enable trace logging for this object""" self.__tracing_enabled = True
[docs] def disable_tracing(self): """Disable trace logging for this object""" self.__tracing_enabled = False
[docs] def add_tracing_filter(self, key: str, value: Any): """Add a filter for trace log messages from this object To reduce trace messages further, a filter can be applied such that events must have a key with a specific value for it to be logged. :param key: A new or existing key to filter on :param value: An allowed value for the event to be logged """ self.__tracing_filters[key].append(value)
[docs] def remove_tracing_filter(self, key: str, value: Any): """Remove a specific key-value pair from the filter :param key: An existing filter key :param value: The allowed value to remove """ if ( key not in self.__tracing_filters or value not in self.__tracing_filters[key] ): return self.__tracing_filters[key].remove(value) if not self.__tracing_filters[key]: self.__tracing_filters.pop(key)
[docs] def clear_tracing_filters(self): """Clear all filters and allow all messages to be logged (if enabled)""" self.__tracing_filters.clear()