Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Statsd Client Bundle Laravel Package

liuggio/statsd-client-bundle

Symfony bundle that integrates the StatsD PHP client, letting you send counters, gauges, timings, and sets to a StatsD daemon over UDP. Configure services and start emitting application metrics with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony 2.x bundle wrapping liuggio/statsd-php-client. It gives you a configured StatsD client service plus optional auto-instrumentation listeners and a profiler panel. It is a thin integration layer — almost everything you can do here you can also do with the underlying client directly.

Minimal setup:

composer require "liuggio/statsd-client-bundle:~1.0"

Register the bundle in app/AppKernel.php (namespace is Luggio\StatsDClientBundle; note the capital D):

new Luggio\StatsDClientBundle\LuggioStatsDClientBundle(),

Configure it — the key is luggio_stats_d_client (not luggio_statsd_client):

# app/config/config.yml
luggio_stats_d_client:
    host: 127.0.0.1
    port: 8125
    protocol: udp           # udp (default) or tcp
    namespace: myapp        # prefixes every metric key
    auto_instrument: false  # request/exception/doctrine listeners
    enable_collector: false # Symfony profiler panel
    log_exception: false
    throw_exception: false

First use case — instrument a business event:

$statsd = $this->get('luggio_stats_d_client.service');
$statsd->increment('user.registered');

Where to look first:

  1. DependencyInjection/Configuration.php — the authoritative list of options (the README lags the code).
  2. Resources/config/services.* — exact service IDs and listener wiring; this is where you confirm what auto_instrument actually registers and which metric names it emits.
  3. The upstream liuggio/statsd-php-client API (increment, decrement, updateCount, timing, gauge, startTiming/endTiming) — the bundle is mostly just wiring around it.

Implementation Patterns

Inject the client, don't fetch it from the container. In Symfony 2 this means constructor arguments with the service ID, or type-hint Luggio\StatsdClient\StatsdClientInterface and add an alias:

services:
    luggio_stats_d_client.client_alias:
        alias: luggio_stats_d_client.service

Centralize metric names in one small wrapper service (App\Metrics\Statsd) so key spelling and prefixing are consistent and the client can be swapped for a null implementation in tests.

The four metric types you'll actually use:

// Counters — events, errors, cache misses
$statsd->increment('order.created');
$statsd->updateCount('queue.processed', 25);

// Timers — always milliseconds
$start = microtime(true);
$result = $this->api->call();
$statsd->timing('api.payment.duration', (microtime(true) - $start) * 1000);

// Or the built-in pair
$statsd->startTiming('api.payment.duration');
// ... work ...
$statsd->endTiming('api.payment.duration');

// Gauges — "current value" measures (queue depth, pool size)
$statsd->gauge('queue.pending', $count);

Batch when you emit several metrics together. The factory service (luggio_stats_d_client.factory) returns value objects, and the client's send() accepts an array — one socket write instead of N:

$factory = $this->get('luggio_stats_d_client.factory');
$statsd->send([
    $factory->increment('checkout.started'),
    $factory->timing('checkout.duration', $ms),
    $factory->gauge('cart.items', $items),
]);

Turn on auto_instrument in production only. It registers listeners that emit baseline HTTP request timing/memory/status-code metrics, exception counts, and Doctrine query metrics. That's a good free dashboard for a legacy app, but it's noise (and overhead) in dev/test. A common split:

# config_prod.yml
luggio_stats_d_client:
    host: statsd.internal
    namespace: myapp.prod
    auto_instrument: true
    enable_collector: false

# config_dev.yml / config_test.yml
luggio_stats_d_client:
    namespace: myapp.dev
    auto_instrument: false
    enable_collector: true   # profiler panel for eyeballing metrics

Use the namespace for environment separation. One StatsD/Graphite backend, myapp.prod.* vs myapp.staging.*, and deleting an environment is a prefix drop rather than a hunt through dashboards.

Extension point — decorate the sender. The socket sender is a separate service (luggio_stats_d_client.connection). Override/decorate it to drop metrics by prefix, log what's sent in dev, fan out to two backends, or substitute an echo/null sender in tests. This is cleaner than wrapping the client.

Where metrics belong in day-to-day code: controllers stay thin; emit from domain services and event listeners. A kernel.terminate listener that flushes a small batch is a reasonable place for request-scoped totals, though the client writes on each send() anyway.

Gotchas and Tips

The bundle is unmaintained (last release 2016) and Symfony 2-only. composer.json pins Symfony ~2.x, and services are written for the old container. Do not plan to carry it onto Symfony 3.4+/4+/5+. For legacy 2.x apps in maintenance it's fine; for anything new, use the underlying client directly or a modern metrics path (Monolog handler, Prometheus, OpenTelemetry).

It's fire-and-forget UDP. Packets can be dropped, reordered, or duplicated. Never use StatsD counters as the source of truth for billing or anything auditable — they're for trends. Large batched payloads may exceed the MTU and get fragmented or lost; keep batches small.

Metric-name cardinality is the classic mistake. Dots are hierarchy separators in Graphite. order.created.12345 creates a series per order and will melt your metrics store. Bucket instead: order.created, order.amount.bucket.50_100. Never put user IDs, URLs, or exception messages in a key — exception class is acceptable.

Sample rates are client-side and mean different things per type. increment($key, 0.1) sends |@0.1; StatsD scales counters back up, but timers are simply sampled — you lose the long tail. Default to 1 unless you're genuinely flooding the network.

Timing units are milliseconds everywhere. startTiming/endTiming already multiply the delta by 1000. If you hand-roll a timer, convert.

Gauge semantics vary by server. Etsy's StatsD treats a value starting with +/- as a delta; Influx/Telegraf-style backends may not. The client just forwards the number, so "decrement a gauge" is backend-specific. Test it against your actual daemon.

Failures are silent by default. With throw_exception: false and log_exception: false, a wrong host/port produces zero packets and zero complaints. Set throw_exception: true in dev/staging to catch misconfiguration, and leave it quiet in prod. Also watch for DNS resolution blocking on the first send — point at an IP if your resolver is slow.

Service visibility breaks on Symfony 3+. Everything assumes public services and $container->get('luggio_stats_d_client.service'). If you're on a transitional 2.8 setup with private services, you'll need explicit public: true.

Config key spelling is easy to get wrong: luggio_stats_d_client — two ds, no statsd contraction. A typo silently means "no config", so the client defaults to 127.0.0.1:8125 and your metrics vanish. After editing config, clear the cache and verify with app/console container:debug luggio_stats_d_client (or debug:container on 2.8+).

Debugging without a StatsD server: nc -u -l 8125 prints raw packets (metric:1|c, metric:123|ms). tcpdump -n -i any udp port 8125 confirms they leave the box. Running the real statsd with its console/debug backend is the fastest way to see what the auto-instrumentation listeners actually emit — useful because the metric names aren't documented clearly in the README.

protocol: tcp requires server support and can block under backpressure; UDP is the sane default. The profiler collector (enable_collector) holds metrics in memory per request — dev only.

Version pinning: no tag since 2016, so audit what composer.lock actually resolved and pin the commit. Also check the resolved liuggio/statsd-php-client version — the bundle's behavior (prefix handling, sender API) follows it.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource