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│
└───────────┘ └────────┘ └──────────┘
Metadata
Release files for grass-metrics 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| grass_metrics-0.2.0.tar.gz | 13.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| grass_metrics-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.8 kB
Release files / grass_metrics-0.2.0.tar.gz
| Download URL | grass_metrics-0.2.0.tar.gz |
|---|---|
| Size | 13.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
975f306485e7d598e36d94fa7b65ce4f19e16a1f5e5fe8b4dadc5a388083a368
|
|
BLAKE2b-256 checksum How to use checksums |
dd141f833be498105c3568c930171e7987dfd1e7af2c3e3fda462455b6177726
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / grass_metrics-0.2.0-py3-none-any.whl
| Download URL | grass_metrics-0.2.0-py3-none-any.whl |
|---|---|
| Size | 13.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
673d52c90220b59231b7c48c82933585beae9ce963bff9a17f91b62a51bb73fa
|
|
BLAKE2b-256 checksum How to use checksums |
e4ce74e7d564815ca8e42983a6e474ec79680ccc1ba0ad4daf8f98195821810d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|