Unified metrics library supporting DataDog (DogStatsD) and OpenTelemetry/OpenObserve with automatic backend selection and dual-write mode.
Project description
grass-metrics
Unified metrics library for Grass projects. Supports DataDog (DogStatsD/UDP) and OpenTelemetry/OpenObserve (OTLP gRPC/HTTP) with automatic backend selection and dual-write mode.
Installation
# Core (no backend dependencies -- bring your own)
pip install grass-metrics
# With DataDog support
pip install "grass-metrics[datadog]"
# With OpenTelemetry support
pip install "grass-metrics[otel]"
# Both backends
pip install "grass-metrics[all]"
Quick Start
from grass_metrics import create_metrics_manager
metrics = create_metrics_manager()
metrics.increment("wl.my_service.items.processed")
metrics.gauge("wl.my_service.queue.size", 42)
metrics.histogram("wl.my_service.latency_seconds", 1.23)
# With extra tags
metrics.increment("wl.my_service.uploads.success", extra_tags=["provider:s3"])
# Shutdown (flushes OTel buffers)
metrics.shutdown()
Backend Selection
The factory picks the backend in this priority order:
| Priority | Source | Example |
|---|---|---|
| 1 | backend argument to create_metrics_manager() |
create_metrics_manager("otel") |
| 2 | METRICS_BACKEND env var |
METRICS_BACKEND=dual |
| 3 | Local Redis key metrics_backend |
Set by preloader from cluster config |
| 4 | Default | "datadog" |
Supported values: datadog, otel, dual
- datadog -- Sends metrics via DogStatsD UDP to the DataDog Agent
- otel -- Sends metrics via OTLP (gRPC or HTTP) to an OpenTelemetry Collector / OpenObserve
- dual -- Sends to both simultaneously (DataDog primary, OTel secondary). Useful during migration.
Environment Variables
Common
| Variable | Description | Default |
|---|---|---|
METRICS_BACKEND |
Backend selection | datadog |
ENVIRONMENT |
Environment name for tags | unknown |
CLUSTER_NAME or CLUSTERNAME |
Cluster name for tags | unknown |
HOSTNAME |
Host name for tags | unknown |
SERVICE_NAME |
Service name for tags | - |
POD_NAME |
Pod name for tags (optional) | - |
LOCAL_REDIS_DB_URI |
Redis URI for dynamic backend override | - |
DataDog
| Variable | Description | Default |
|---|---|---|
DD_AGENT_HOST |
DataDog agent host | 172.17.0.1 |
DD_DOGSTATSD_PORT |
DogStatsD port | 8125 |
OpenTelemetry / OpenObserve
| Variable | Description | Default |
|---|---|---|
OTEL_EXPORTER_ENDPOINT |
OTLP endpoint | auto (see below) |
OTEL_EXPORTER_AUTH_TOKEN |
Auth header value | - |
NODE_IP |
K8s node IP for local agent | - |
OTel endpoint resolution: explicit > OTEL_EXPORTER_ENDPOINT > http://{NODE_IP}:4317 > gateway fallback.
Kubernetes Pod Spec
env:
- name: METRICS_BACKEND
valueFrom:
configMapKeyRef:
name: scraper-config
key: metrics_backend
# DataDog
- name: DD_AGENT_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
# OTel
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
Docker Compose
environment:
METRICS_BACKEND: "otel"
DD_AGENT_HOST: "datadog" # service name
OTEL_EXPORTER_ENDPOINT: "http://otel-collector:4317"
Domain-Specific Metrics (Consumer Pattern)
For projects with many metrics, wrap MetricsManager in a thin domain class:
from grass_metrics import create_metrics_manager
class YtdMetrics:
DOWNLOADS_SUCCESS = "wl.ytd.downloads.healthy_count"
DOWNLOADS_FAILED = "wl.ytd.downloads.failed_count"
UPLOAD_DURATION = "wl.ytd.upload.duration_seconds"
def __init__(self):
self._m = create_metrics_manager()
def increment_downloaded_videos_count(self):
self._m.increment(self.DOWNLOADS_SUCCESS)
def increment_failed_downloads_count(self):
self._m.increment(self.DOWNLOADS_FAILED)
def send_upload_duration(self, seconds: float):
self._m.histogram(self.UPLOAD_DURATION, seconds)
def shutdown(self):
self._m.shutdown()
Direct Publisher Access
For advanced use cases, publishers can be used directly:
from grass_metrics import DatadogPublisher, OtelPublisher
dd = DatadogPublisher(statsd_host="172.17.0.1", statsd_port=8125)
dd.increment_count("my.counter", 1, ["env:prod"])
otel = OtelPublisher(service_name="my-svc", use_grpc=True)
otel.increment_count("my.counter", 1, ["env:prod"])
otel.shutdown()
Architecture
┌──────────────────────────────────────────────────┐
│ Consumer Project │
│ (e.g. YtdMetrics with domain-specific methods) │
└──────────────────────┬───────────────────────────┘
│
create_metrics_manager(backend=...)
│
┌──────▼──────┐
│ Factory │ resolves backend from
│ factory.py │ env / Redis / default
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌─────▼─────┐ ┌───▼────┐ ┌────▼─────┐
│ MetricsMgr│ │MetrMgr │ │ DualMgr │
│ + DD Pub │ │+ OTel │ │ DD + OTel│
└───────────┘ └────────┘ └──────────┘
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file grass_metrics-0.2.0.tar.gz.
File metadata
- Download URL: grass_metrics-0.2.0.tar.gz
- Upload date:
- Size: 13.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
975f306485e7d598e36d94fa7b65ce4f19e16a1f5e5fe8b4dadc5a388083a368
|
|
| MD5 |
27049a8e2a979bc5e398922ab006e092
|
|
| BLAKE2b-256 |
dd141f833be498105c3568c930171e7987dfd1e7af2c3e3fda462455b6177726
|
File details
Details for the file grass_metrics-0.2.0-py3-none-any.whl.
File metadata
- Download URL: grass_metrics-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
673d52c90220b59231b7c48c82933585beae9ce963bff9a17f91b62a51bb73fa
|
|
| MD5 |
af70a205fbca9ea1c9ad72f90cad31fd
|
|
| BLAKE2b-256 |
e4ce74e7d564815ca8e42983a6e474ec79680ccc1ba0ad4daf8f98195821810d
|