pystatsd
A lightweight, dependency-free Python client for sending counters, gauges, timers, and sets to a statsd daemon.
Repository Health
Technical Analysis
pystatsd is the reference Python client for statsd, the network daemon that aggregates application metrics and forwards them to Graphite or compatible backends. It ships three interchangeable client classes covering UDP, TCP, and Unix domain socket transports, all built on a shared base class that formats and dispatches stat updates.
Beyond basic counters and gauges, it provides a pipelining API for batching multiple stats into a single network packet, a Timer helper that works as a decorator, context manager, or manual start/stop object (with native async support), and per-call sample rates for cheaply instrumenting high-volume code paths. Ready-made Django and environment-variable configuration modules remove setup boilerplate for the most common deployment contexts.
What You Get
- Three interchangeable client classes (StatsClient, TCPStatsClient, UnixSocketStatsClient) sharing one API for counters, gauges, timers, and sets
- A pipeline/context-manager API that batches stats into fewer network packets
- A Timer helper usable as a decorator, context manager, or manual start/stop for measuring code duration, with native async function support
- Ready-made Django and environment-variable configuration modules under statsd.defaults
- Per-call sample rate support for cheaply instrumenting high-frequency code paths
Common Use Cases
- Recording request latency and endpoint timing for Graphite dashboards
- Counting feature usage and business events with simple incr()/decr() calls
- Wiring a shared statsd client into a Django settings-based application
- Sampling noisy, high-volume events to control metric traffic to the statsd daemon
Under The Hood
Architecture pystatsd is layered around a transport-agnostic StatsClientBase (statsd/client/base.py) that implements stat formatting and dispatch (_prepare, _send_stat, _after) shared by every client; StatsClient (statsd/client/udp.py) sends over UDP by default, while TCPStatsClient and UnixSocketStatsClient (statsd/client/stream.py) share a StreamClientBase that adds connect/reconnect semantics for stream sockets. Each transport pairs with its own PipelineBase subclass (Pipeline in udp.py, StreamPipeline in stream.py) so pipeline() batches multiple stat calls into a single packet without touching the base formatting logic. Timer (statsd/client/timer.py) is composed into the base class via the .timer() method rather than inherited, letting it double as a decorator, context manager, or manually started/stopped object. Because every transport and pipeline variant inherits _prepare/_send_stat from StatsClientBase, changing that core formatting logic would ripple through all three client types at once.
Tech Stack The library has zero runtime dependencies — it is built entirely on the Python standard library (socket, functools, inspect, time, collections.deque) — and targets Python 3.10 through 3.14 plus PyPy per its GitHub Actions matrix. Packaging uses a modern pyproject.toml with a setuptools backend (setuptools>=61.2), and documentation is built with Sphinx from the docs/ directory. Optional statsd.defaults.django and statsd.defaults.env modules provide thin, dependency-free integration shims for the two most common deployment contexts.
Code Quality Testing is thorough: a single 1000+ line statsd/tests.py exercises every client, pipeline, sample-rate, and Timer code path using unittest and unittest.mock, and CI runs this matrix across six Python/PyPy versions plus a dedicated flake8 lint job and a scheduled CodeQL scan. Error handling is explicit rather than typed — there are no type hints or a py.typed marker — and the UDP client’s _send() intentionally swallows OSError/RuntimeError on send since a dropped metric shouldn’t crash the caller. Naming is consistent, idiomatic snake_case throughout, with docstrings on public methods.
API Design The public surface is deliberately small: instantiate one of three client classes with a host/port or socket path, then call incr/decr/gauge/set/timing directly, with no setup ceremony beyond that. The Timer class is the standout ergonomic touch, working interchangeably as a decorator, a context manager, or manual start()/stop() calls, including native async function support. Sample rates and prefixes are plain constructor/call arguments rather than separate configuration objects, and the defaults.django/defaults.env modules remove all remaining boilerplate for the two most common deployment contexts.
Used by 4 apps in this directory
Apache Airflow
Data Engineering
Define, schedule, and monitor complex data workflows as Python code — with a powerful UI, 80+ provider integrations, and battle-tested scalability across thousands of production deployments.
Healthchecks
Monitoring · Devops
Open-source cron job and background task monitoring that alerts you when your scheduled jobs go silent.
Redash
Analytics · Data Engineering
Redash lets anyone connect to 35+ SQL and NoSQL data sources, write a query in the browser, and turn the result into a shared dashboard — no separate BI suite required.
Sentry
Security · Developer Tools · Monitoring
Developer-first error tracking and performance monitoring platform with AI-powered root-cause analysis across 20+ languages and frameworks.