ds_common_logger_py_lib.core

File: core.py Region: ds_common_logger_py_lib

Description

Defines the core logging API for this package, including a Logger helper for configuring Python logging, retrieving named loggers, and updating the active log format across already-created loggers.

Example

>>> from ds_common_logger_py_lib import Logger
>>> import logging
>>>
>>> Logger.configure()
>>> logger = Logger.get_logger(__name__)
>>> logger.info("Hello, world!")
[2024-01-15T10:30:45][__main__][INFO][core.py:18]: Hello, world!
>>>
>>> Logger.set_log_format("%(levelname)s: %(message)s")
>>> logger.info("Custom format message")
INFO: Custom format message

Classes

Logger

Logger class for the application with static methods only.

Module Contents

class ds_common_logger_py_lib.core.Logger[source]

Logger class for the application with static methods only.

Configure the logger using Logger.configure() before using Logger.get_logger(). The default format can be customized by calling set_log_format() or by passing a format_string to configure().

Example

>>> Logger.configure(level=logging.DEBUG)
>>> logger = Logger.get_logger(__name__)
>>> logger.info("Test message")
[2024-01-15T10:30:45][__main__][INFO][core.py:59]: Test message
>>>
>>> Logger.set_log_format("%(levelname)s: %(message)s")
>>> logger.info("Formatted message")
INFO: Formatted message
>>>
>>> Logger.configure(level=logging.INFO, handlers=[logging.FileHandler("app.log")])
>>> Logger.configure(level=logging.DEBUG, force=True)
DEFAULT_FORMAT = '[%(asctime)s][%(levelname)s][%(name)s][%(filename)s:%(lineno)d]: %(message)s'
DEFAULT_FORMAT_WITH_PREFIX = '[%(asctime)s][%(levelname)s][{prefix}][%(name)s][%(filename)s:%(lineno)d]: %(message)s'
DEFAULT_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S'
_configured: bool = False
_prefix: str = ''
_format_string: str | None = '[%(asctime)s][%(levelname)s][{prefix}][%(name)s][%(filename)s:%(lineno)d]: %(message)s'
_date_format: str | None = '%Y-%m-%dT%H:%M:%S'
_level: int = 20
_handlers: ClassVar[list[logging.Handler]] = []
_default_handler: logging.Handler | None = None
_managed_loggers: ClassVar[set[str]]
_logger_levels: ClassVar[dict[str, int]]
_filter: ds_common_logger_py_lib.formatter.LoggerFilter
static configure(prefix: str = '', format_string: str = DEFAULT_FORMAT_WITH_PREFIX, date_format: str = DEFAULT_DATE_FORMAT, level: int = logging.INFO, handlers: list[logging.Handler] | None = None, default_handler: logging.Handler | None = None, allowed_prefixes: set[str] | None = None, logger_levels: dict[str, int] | None = None, force: bool = False) None[source]

Configure application-level logging settings.

This should be called once at application startup, before any packages start using the logger. The configuration will be applied to all loggers created via Logger.get_logger().

Parameters:
  • prefix – Prefix to inject into log messages (via {prefix} in format). Can be updated later with set_prefix().

  • format_string – Format string for log messages. Uses {prefix} to include the prefix. Uses DEFAULT_FORMAT_WITH_PREFIX by default.

  • date_format – Date format string. Uses DEFAULT_DATE_FORMAT by default.

  • level – Default logging level.

  • handlers – List of handlers to add to all loggers. If None, uses default StreamHandler.

  • default_handler – Single default handler to use for all loggers. If provided, this replaces the default StreamHandler.

  • allowed_prefixes – Set of logger name prefixes to allow in addition to library-created loggers. Default is None, which means only loggers created via Logger.get_logger() are allowed. To include third-party library logs, add their prefixes: {“sqlalchemy”, “boto3”} to see SQLAlchemy and boto3 logs.

  • logger_levels – Optional mapping of logger names to logging levels. If provided, levels are applied to the parent loggers for those names (e.g., setting “myapp” sets the parent logger for “myapp.*”). Pass an empty dict to clear existing rules.

  • force – If True, force reconfiguration even if already configured.

Example

>>> from ds_common_logger_py_lib import Logger
>>> import logging
>>> Logger.configure(
...     prefix="MyService",
...     format_string="[%(asctime)s][{prefix}][%(name)s]: %(message)s",
...     level=logging.DEBUG
...     logger_levels={
...         "ds": logging.WARNING,
...     },
... )
>>> logger = Logger.get_logger(__name__)
>>> logger.info("Service started")
[2024-01-15T10:30:45][MyService][__main__]: Service started
static get_logger(name: str, package: bool = False) logging.Logger[source]

Get a configured logger instance.

If Logger.configure() is called, the logger will use application-level settings (prefix, format, handlers). Otherwise, uses default settings.

Parameters:
  • name – The logger name (usually __name__).

  • package – If True, normalize internal package names into a shared namespace (e.g., ds_common_* -> ds.common.*).

Returns:

Configured logger instance.

Example

>>> Logger.configure()
>>> logger = Logger.get_logger(__name__)
>>> logger.info("Test message")
[2024-01-15T10:30:45][__main__][INFO][core.py:232]: Test message
static set_prefix(prefix: str) None[source]

Update the prefix at runtime.

This allows you to change the prefix dynamically, for example when a session starts or when context changes. The new prefix will be applied to all existing and future loggers.

If Logger.configure() hasn’t been called yet, this will automatically configure it with default settings that include {prefix} in the format (using the provided prefix).

Parameters:

prefix – New prefix value to use in log messages.

Example

>>> from ds_common_logger_py_lib import Logger
>>> import logging
>>> Logger.set_prefix("MyApp")
>>> logger = Logger.get_logger(__name__)
>>> logger.info("Log with MyApp prefix")
[2024-01-15T10:30:45][MyApp][__main__][INFO][core.py:158]: Log with MyApp prefix
>>>
>>> session_id = "session_12345"
>>> Logger.set_prefix(f"[{session_id}]")
>>> logger.info("Log with session prefix")
[2024-01-15T10:30:46][session_12345][__main__][INFO][core.py:162]: Log with session prefix
static set_log_format(format_string: str | None = None, date_format: str | None = None) None[source]

Set or update the default log format for all loggers.

Parameters:
  • format_string – Format string to set. If None, resets to DEFAULT_FORMAT.

  • date_format – Date format string to set. If None, resets to DEFAULT_DATE_FORMAT.

Example

>>> Logger.configure()
>>> Logger.set_log_format("%(levelname)s: %(message)s")
>>> logger = Logger.get_logger(__name__)
>>> logger.info("This will use the custom format")
INFO: This will use the custom format
static add_handler(handler: logging.Handler) None[source]

Add a handler to the root logger.

When Logger.configure() is called, handlers are on the root logger only. Package loggers propagate to root, so they will use this handler automatically.

Parameters:

handler – Handler to add.

Example

>>> from ds_common_logger_py_lib import Logger
>>> import logging
>>> Logger.configure()
>>> file_handler = logging.FileHandler("app.log")
>>> Logger.add_handler(file_handler)
>>> logger = Logger.get_logger(__name__)
>>> logger.info("Message goes to file via root logger")
static remove_handler(handler: logging.Handler) None[source]

Remove a handler from the root logger.

Parameters:

handler – Handler to remove.

Example

>>> from ds_common_logger_py_lib import Logger
>>> import logging
>>> Logger.configure()
>>> file_handler = logging.FileHandler("app.log")
>>> Logger.add_handler(file_handler)
>>> Logger.remove_handler(file_handler)
static set_default_handler(handler: logging.Handler) None[source]

Set the default handler for all loggers, replacing the current default.

Parameters:

handler – Handler to use as default.

Example

>>> from ds_common_logger_py_lib import Logger
>>> import logging
>>> import sys
>>> Logger.configure()
>>> custom_handler = logging.StreamHandler(sys.stderr)
>>> Logger.set_default_handler(custom_handler)
>>> logger = Logger.get_logger(__name__)
>>> logger.info("Message goes to stderr via root logger")
static is_configured() bool[source]

Check if Logger has been configured.

Returns:

True if Logger has been configured, False otherwise.

static get_managed_loggers() set[str][source]

Get the set of managed loggers.

Returns:

The set of registered loggers.

static get_prefix() str[source]

Get the configured prefix.

Returns:

The configured prefix.

static get_format_string() str | None[source]

Get the configured format string.

Returns:

The configured format string.

static get_date_format() str | None[source]

Get the configured date format.

Returns:

The configured date format.

static _register_managed_logger(logger_name: str) None[source]

Register a logger name as being managed by this helper.

This ensures that loggers created via Logger.get_logger() are automatically allowed by the filter, regardless of allowed_prefixes.

Parameters:

logger_name – The name of the logger to register.

static _normalize_logger_name(name: str) str[source]

Normalize internal package names into a dotted namespace.

Parameters:

name – The logger name to normalize.

Returns:

The normalized logger name.

static _create_formatter() ds_common_logger_py_lib.formatter.ExtraFieldsFormatter[source]

Create a formatter with current configuration.

Returns:

ExtraFieldsFormatter instance with current configuration.

static _setup_filter() None[source]

Apply filter to existing handlers managed by Logger.

static _update_existing_loggers() None[source]

Update root logger handlers managed by Logger with current configuration.

static _apply_logger_levels(previous_levels: dict[str, int] | None = None) None[source]

Apply logger-level rules to logger hierarchy.

Parameters:

previous_levels – The previous logger levels.