MetricUtils: Logging & Telemetry#
- class my.utils.MetricUtils.MetricUtils#
Methods that deal with logging, telemetry, and other measurement tasks.
Important
These methods are only usable if the optional
metricsdependency is installed (pip install my-basis[metrics]). If you try to call them without it, anImportErrorwill be thrown.
I Logging#
Important
Remote telemetry is content-denying by default: Logfire scrubbing stays enabled, argument inspection and distributed trace propagation are off, and Python log export plus per-process system metrics require explicit opt-in.
Configuration overrides use a closed allowlist, custom or unknown scrub behavior is rejected, and environment-derived service identities must be bounded machine identifiers.
Application OTLP exporters accept local collectors (including the Podman host and an otel-collector sidecar) or the HTTPS <group-id>.gitlab-o11y.com endpoint; other destinations are rejected before providers change.
A destination comes from LOGFIRE_TOKEN, OTEL_EXPORTER_OTLP_ENDPOINT, or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT; without one, applications continue with local logs and retry remote setup on the next call.
Failures in optional Python-log, system-metric, or ASGI instrumentation remain local warnings and do not tear down an already-configured trace provider.
- classmethod MetricUtils.setup_py_logging(logdir: Annotated[Path, PathType(path_type=dir)], is_dev: bool, package: str, logger: Logger | None = None, app: Any | None = None, maxsize: int = 67108864, maxcount: int = 1024) Logger#
Configure Python file-based logging with rotation.
- Parameters:
logdir – Directory for log files.
is_dev – If True, use DEBUG level; otherwise INFO.
package – Package name for logger identification.
logger – Existing logger to configure, or None to create new.
app – Optional ASGI app to register logger with.
maxsize – Maximum log file size in bytes (default: 64 MB).
maxcount – Maximum number of backup files (default: 1024).
- Returns:
Configured Logger instance.
Examples
Attach a rotating file handler for a package:
>>> from pathlib import Path >>> from my import ut >>> logger = ut.setup_py_logging(Path('logs'), True, 'my-basis') >>> logger.info('ready')
- classmethod MetricUtils.setup_fire_logging(fire_token: str, package: str, logger: Logger, is_dev: bool = True, app: Any | None = None, export_logs: bool = False, system_metrics: bool = False, log_level: str | None = None, **kwargs: Any) None#
Configure Logfire observability and logging.
- Parameters:
fire_token – Logfire API token; an empty value falls back to
LOGFIRE_TOKENand permits an OTLP-only destination.package – Package name for service identification.
logger – Logger to attach Logfire handler to.
is_dev – If True, use development mode with console output (default: True).
app – Optional ASGI app to instrument.
export_logs – Attach the Python logging handler for already-scrubbed event names.
system_metrics – Enable Logfire’s per-process system metrics instrumentation.
log_level – Stdlib level name (e.g.
WARNING) for the exported log handler; when None, the handler floor stays DEBUG in dev and INFO otherwise.**kwargs – Additional configuration options for Logfire.
- Raises:
ValueError – If the service identity/destination is missing or a privacy control is weakened.
Examples
Configure Logfire against an existing logger:
>>> import logging >>> from my import ut >>> ut.setup_fire_logging( ... fire_token='', package='my-basis', logger=logging.getLogger('my-basis'))
- classmethod MetricUtils.get_package_name() str#
Retrieve this utility’s distribution or source-project name.
Standard installed-package metadata is preferred. Editable installs often omit the import-to-distribution map, so their
direct_url.jsonproject root is matched against this module; a source checkout falls back to its nearestpyproject.toml. A standalone script without either kind of metadata retains the root import name.- Returns:
Canonical distribution/project name, or the root import name as a fallback.
Examples
Identify the distribution even from an editable checkout:
>>> from my import ut >>> ut.get_package_name() 'my-basis'
- static MetricUtils.setup_logging(logdir: Annotated[Path, PathType(path_type=dir)], is_dev: bool, fire_token: str, package: str = '', logger: Logger | None = None, app: Any | None = None, maxsize: int = 67108864, maxcount: int = 1024, export_logs: bool = False, system_metrics: bool = False, log_level: str | None = None, **fire_kwargs: Any) Logger#
Configure comprehensive logging (Python file logging + Logfire).
- Parameters:
logdir – Directory for log files.
is_dev – If True, use development mode with DEBUG level.
fire_token – Logfire API token (empty string to skip Logfire).
package – Package name (auto-detected if empty).
logger – Existing logger to configure, or None to create new.
app – Optional ASGI app to instrument.
maxsize – Maximum log file size in bytes (default: 64 MB).
maxcount – Maximum number of backup files (default: 1024).
export_logs – Export already-scrubbed Python log records through Logfire.
system_metrics – Enable per-process system metrics instrumentation.
log_level – Stdlib level name (e.g.
WARNING) for the exported log handler; when None, the handler floor stays DEBUG in dev and INFO otherwise. Like the other options, only a package’s first configuration applies it.**fire_kwargs – Additional Logfire configuration options.
- Returns:
Configured Logger instance (cached per package).
Examples
One call wires both file logging and Logfire:
>>> from pathlib import Path >>> from my import ut >>> logger = ut.setup_logging(Path('logs'), True, fire_token='')
- static MetricUtils.setup_warnings()#
Configure warning filters to suppress common deprecation warnings.
Filters out warnings for class-based config, config key changes, and pkg_resources deprecation. Only runs once per session.
II Metrics#
- classmethod MetricUtils.setup_metrics(metrics: Annotated[Path, PathType(path_type=dir)], logger: Logger)#
Perform setup for Prometheus metrics, ensuring directory exists and is empty.
- Parameters:
metrics – Directory for Prometheus multiprocess metrics.
logger – Logger for recording setup actions.
- Raises:
AssertionError – If PROMETHEUS_MULTIPROC_DIR not set or mismatches metrics path.
Examples
Prepare the Prometheus multiprocess directory:
>>> import logging >>> from pathlib import Path >>> from my import ut >>> metrics_dir = Path('/tmp/prometheus') # must match $PROMETHEUS_MULTIPROC_DIR >>> ut.setup_metrics(metrics_dir, logging.getLogger())
- classmethod MetricUtils.measure_context(name: str, counter: dict[str, float])#
Context manager to measure execution time of a code block.
Timing is recorded even if the block raises, so a slow-then-crashing path still shows up in
counter.- Parameters:
name – Metric name for recording.
counter – Dictionary counter to record elapsed time.
- Yields:
None (timing measured around context block).
Examples
Accumulate elapsed milliseconds into a plain dict:
>>> from my import ut >>> counter = {} >>> with ut.measure_context('step', counter): ... total = sum(range(1000)) >>> counter['step'] > 0 True
- classmethod MetricUtils.monitor(*args: Any, **kwargs: Any) Callable#
Create a Logfire instrumentation decorator for a function.
- Parameters:
*args – Positional arguments for fire.instrument().
**kwargs – Keyword arguments for fire.instrument().
- Returns:
Decorator that instruments function with Logfire monitoring.
Examples
Instrument a function with a Logfire span:
>>> from my import ut >>> @ut.monitor('fetch-page') ... def fetch(url): ...