Skip to main content

python-statsd

Metrics leave your application over UDP, statsd aggregates them, Graphite stores and graphs them

CI on master CodeQL status Documentation Coverage on master
PyPI version Supported Python versions Monthly downloads BSD-3-Clause licence
Type checked: mypy, basedpyright, pyrefly and ty Linted and formatted with ruff

python-statsd is a client for statsd, the metrics aggregation daemon that started at Etsy and now lives in its own organisation, sitting in front of Graphite. It supports Python 3.10 and newer, and it has no dependencies.

pip install python-statsd
import statsd

counter = statsd.Counter('app')
counter += 1

with statsd.Timer('app').time('render'):
    pass  # the work you are measuring

Two metrics, two UDP packets, nothing blocking. A statsd server that is down costs you graphs rather than requests.

What goes on the wire

Every line under udp :8125 < in this recording is a packet the client sent, caught by a real listener on the other end:

A terminal session sending a counter, a gauge, a timer and a sampled counter, with each UDP payload printed as it arrives

Note the last one. At sample_rate=0.5 four increments produced a single packet, and it carries |@0.5 so the server knows to multiply back up.

The metric types

Type A burst of values becomes Reach for it when
Counter their sum you are counting events
Gauge the last one you are reporting a level
Timer mean, median, percentiles you are measuring duration
Average their mean the server should average samples
Raw stored as sent you already did the summarising
import statsd

counter = statsd.Counter('app')
counter.increment('requests')  # app.requests:1|c

gauge = statsd.Gauge('app')
gauge.send('queue_depth', 42)  # app.queue_depth:42|g

average = statsd.Average('app')
average.send('batch', 123)  # app.batch:123|a

raw = statsd.Raw('app')
raw.send('summary', 42, timestamp=1234567890)  # app.summary:42|r|1234567890

Timers come in three forms, and the context manager is the one to reach for, because it reports the block that raised as well as the block that did not:

import statsd

timer = statsd.Timer('app')

with timer.time('render'):
    pass  # the work you are measuring


@timer.decorate
def render_page():  # sends app.render_page
    pass

Names build themselves when you nest clients, which keeps the string formatting out of your call sites:

import statsd

app = statsd.Client('app')
queries = app.get_client('database').get_client('queries', statsd.Counter)

queries.increment()  # app.database.queries:1|c

See it working

The repository ships a compose file with the real statsd, Graphite and Grafana, so you can watch a metric arrive instead of taking anyone's word for it:

docker compose up -d --wait
uv run python examples/send_metrics.py --seconds 120

--wait returns once every service reports healthy. No local Python? docker compose --profile demo up -d --wait generates the traffic from a container instead. Then open http://localhost:3000: Grafana has the datasource configured and this dashboard loaded, no login in the way:

A Grafana dashboard showing request rate, render time percentiles, queue depth and packets received

That screenshot is the stack in this repository, fed by examples/send_metrics.py through this client. statsd runs from examples/statsd/config.js, so the aggregation you see is configured in a file you can read and change.

Already running Grafana? Import the dashboard straight into it from examples/grafana/import/python-statsd.json, which asks which datasource to use instead of assuming one. The local stack guide covers how statsd renames your metrics on the way through, and what to check when nothing shows up.

Configuration

Set the defaults once at startup and every client built afterwards follows:

import statsd

statsd.Connection.set_defaults(host='localhost', port=8125, sample_rate=1)

Or build connections yourself when one destination is not enough:

import statsd

connection = statsd.Connection(host='statsd-1', port=8125, sample_rate=0.1)
statsd.Counter('app.requests', connection).increment()

One trap worth knowing before it costs you an afternoon: a falsy argument means "use the default", so Connection(sample_rate=0) sends everything. Pass disabled=True to send nothing.

Documentation

Full documentation is at python-statsd.readthedocs.io.

  • Quickstart: nothing to metrics on a graph, in two tracks
  • Metrics: the five types, how to choose, and the exact bytes each one writes
  • Connections: destinations, sampling, disabling, failure behaviour, threads and forks
  • Patterns: naming, cardinality, client trees, WSGI and Celery integration
  • Local stack: docker compose, and how to debug a metric that never arrives

For Django, use django-statsd, the sister project built on this client. It times views and reports the queries per request without you writing any of it.

Note on the package name

This project is published on PyPI as python-statsd and installs a module called statsd. A different project, jsocol's client, is published as statsd and installs a module called statsd as well. Installing both in one environment leaves you with whichever was written last, so pick one.

Contributing

Bug reports and patches are welcome, and CONTRIBUTING.md covers the development setup: uv sync --all-extras, uv run pytest, and uv run tox -p auto to run everything CI runs. Every code sample in this README and in the documentation is executed by the test suite, so a change in behaviour tends to tell you which paragraph it just made wrong.

Support

python-statsd is maintained by Rick van Hattem in his own time.

If it saved you an afternoon, a tip covers an hour of issue triage: Ko-fi or GitHub Sponsors.

If your company funds its dependencies, this package is on thanks.dev.

ko-fi

Metadata

Release files for python-statsd 3.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for python-statsd 3.0.1
File Size Uploaded Provenance Actions
python_statsd-3.0.1.tar.gz 14.5 kB With provenance Details for python_statsd-3.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for python-statsd 3.0.1
File Interpreter ABI Platform Actions
python_statsd-3.0.1-py3-none-any.whl Python 3 none any Details for python_statsd-3.0.1-py3-none-any.whl

Total release size: 31.5 kB

Release files / python_statsd-3.0.1.tar.gz

Download URL python_statsd-3.0.1.tar.gz
Size 14.5 kB
Tags Source
SHA-256 checksum
How to use checksums
693b4a94a7bd2fe69ac1739bf1edb3a3133a8d9fa953a8e377d6f87947281e75
BLAKE2b-256 checksum
How to use checksums
9fa92fdb017138efb4358c8f7b8edc8f9240f912cd8a3bcc87e93941e65c13e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / python_statsd-3.0.1-py3-none-any.whl

Download URL python_statsd-3.0.1-py3-none-any.whl
Size 17.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9eae0eeda242871666d2c13d485338ba2d81b4cc0aa90b9d7cd42fbd52a6b50e
BLAKE2b-256 checksum
How to use checksums
1f2457a2d6771a3328dcc2949f3fdce98dde6923b3e9db1acb346d0d1c86a5de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Security for python-statsd 3.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for python_statsd-3.0.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page