metrics
Datadog metrics telemetry: handler, lifecycle, logger, and metric registry.
Module
Submodules
- bitfount.telemetry.metrics.handler - Datadog metrics handler for sending custom metrics to Datadog's API.
- bitfount.telemetry.metrics.models - Canonical names for Datadog custom metrics.
Functions
emit_metric
def emit_metric( metric_name: str, value: float, *, timestamp: int | None = None, tags: list[str] | None = None, metric_type: MetricIntakeType | None = None,) ‑> None:Emit a custom metric point to Datadog via metrics_logger.
Preferred public API for emitting metrics. Builds the log record contract
expected by DatadogMetricsHandler (metric name as the message; point
timestamp/value and options carried on extra) so call sites do not
hand-build it. The timestamp/value are passed via extra rather than as
logging args so the record's message never depends on %-formatting.
Arguments
metric_name: The metric name. Accepts aMetricNamemember or a raw string.value: The metric value.timestamp: Unix timestamp (seconds) for the point. Defaults to now.tags: Per-call tags applied to this metric's series.metric_type: The Datadog intake type for this metric. If omitted, the handler defaults the series toGAUGE.
flush_datadog_metrics
def flush_datadog_metrics() ‑> None:Flush the Datadog metrics buffer.
Should be called after each task completes, mirroring flush_datadog_telemetry.
record_execution_time
def record_execution_time(start: float, *, tags: list[str] | None = None) ‑> None:Emit elapsed time since start as the EXECUTION_TIME_SECONDS gauge.
Shared emission core for execution-time telemetry. Used by
track_execution_time (which supplies function:/class: tags) and
by call sites that need a dynamic tag the decorator cannot express — e.g. a
per-DAG-step step:<name>. Only active when
config.settings.enable_execution_time_metrics is True, and never raises:
telemetry must not break execution.
Arguments
start:time.perf_counter()captured before the timed work began.tags: Tags applied to the emitted gauge series.
setup_datadog_metrics
def setup_datadog_metrics( dd_client_token: str | None = None, dd_site: str | None = None, hostname: str | None = None, tags: list[str] | None = None,) ‑> None:Setup Datadog metrics if credentials are available.
Mirrors setup_datadog_telemetry but routes to the Datadog Metrics API
(/api/v2/series) rather than the Logs API. Must be called alongside
setup_datadog_telemetry at pod startup.
This function is idempotent - calling it multiple times is safe.
Arguments
dd_client_token: The Datadog API key.dd_site: The Datadog site (e.g.'datadoghq.com','datadoghq.eu').hostname: The host name attached to every metric series. Defaults to the system hostname.tags: Static tags applied to every metric series (e.g.['env:prod']).
Returns None
shutdown_datadog_metrics
def shutdown_datadog_metrics() ‑> None:Shutdown Datadog metrics and flush any pending series.
Should be called at pod shutdown, mirroring shutdown_datadog_telemetry.
track_execution_time
def track_execution_time(func: F) ‑> F:Decorator that emits function execution time as a Datadog gauge metric.
Supports both sync and async callables. Only active when
config.settings.enable_execution_time_metrics is True. Emits the
MetricName.EXECUTION_TIME_SECONDS gauge with the wrapped callable's
class and function name attached as class:<X> / function:<Y> tags.
Arguments
func: The function to wrap.
Returns The wrapped function.
Classes
DatadogMetricsHandler
class DatadogMetricsHandler( api_instance: MetricsApi, hostname: str, tags: list[str] | None = None,):A logging handler that sends custom metrics to Datadog's Metrics API.
Buffers points per unique (metric_name, tags) combination, so each
combination becomes its own MetricSeries. Each buffer is monitored
independently and flushed when it approaches 90% of the 5 MB uncompressed
limit, and again on flush()/close().
Call sites do not use this handler directly; they go through
emit_metric, which forwards to metrics_logger:
metrics_logger.info(metric_name, extra={...})
where metric_name maps to record.msg and the point's timestamp/value
and options are carried as record attributes via extra:
metric_timestamp/metric_value: the point. Carried onextra(not as loggingargs) so the message never depends on%-formatting.tags: per-call tags appended to this series' tags.metric_type: the Datadog intake type for the series. It is set per call site; calls that omit it default the series toGAUGE.
See: https://docs.datadoghq.com/api/latest/metrics/
Initialise the handler.
Arguments
api_instance: A configured DatadogMetricsApiinstance.hostname: Attached to everyMetricSeriesviaresourcesso metrics are filterable by host in Datadog.tags: Static tags applied to every series (e.g.['env:prod']).
Ancestors
Variables
- static
MAX_SERIES_SIZE
Methods
close
def close(self) ‑> None:Flush and close the handler.
emit
def emit(self, record: logging.LogRecord) ‑> None:Buffer a metric point.
Expects record.msg to be the metric name, with the point's timestamp
and value carried as the metric_timestamp / metric_value attributes
(set via extra=...). Per-call tags can be supplied via
extra={"tags": [...]}. Records that do not match this shape are
silently dropped. The timestamp/value are deliberately not passed as
logging args so the record's message never depends on %-formatting
and cannot break a foreign formatter.
Each unique (metric_name, tags) combination is buffered
independently and flushed as its own MetricSeries when it
approaches the size limit.
Arguments
record: The log record.
flush
def flush(self) ‑> None:Flush all series buffers.
MetricName
class MetricName(*args, **kwds):Canonical names for all Datadog custom metrics.
Inherits from str so values serialise directly as metric names. The
intake type for each metric is set at the call site (see emit_metric),
defaulting to GAUGE when omitted.
Ancestors
Variables
- static
EHR_REQUEST_COUNT
- static
EHR_RESPONSE_BODY_SIZE_BYTES
- static
EHR_RESPONSE_TIME_SECONDS
- static
EXECUTION_TIME_SECONDS