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 Request Headers Bundle Laravel Package

m6web/statsd-request-headers-bundle

A Symfony bundle that emits StatsD metrics for incoming HTTP request headers, so you can track header presence, sizes, and distributions across your application. It hooks into the m6web StatsD ecosystem to instrument requests with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: v1.1.0 adds route information to emitted events and reworks the metric names. The package is still the archived 2016 codebase targeting the Symfony 2/3 era — treat it as a reference implementation of "put request headers into statsd" rather than something you composer require into a modern app. What changed in v1.1.0 is worth knowing even if you rewrite: it confirms the two things you actually want are (a) a header presence/value signal and (b) the route it happened on.

If you still want to run it:

  1. Install — expect platform conflicts on PHP 7.4+/8.x:
    composer require m6web/statsd-request-headers-bundle:^1.1
    # if constraints block you, fork it and use a path/vcs repository
    
  2. Register the bundle — AppKernel::registerBundles() on Symfony 3, or append to config/bundles.php on Symfony 4+ (the bundle class namespace is M6Web\Bundle\StatsdRequestHeadersBundle\M6WebStatsdRequestHeadersBundle; verify the exact class name in the repo root).
  3. Provide a statsd service. The bundle does not ship a client — it expects a statsd service (from m6web/statsd or an equivalent). Confirm the expected service id by reading Resources/config/services.yml before wiring anything.
  4. Configure the header allowlist:
    # app/config/config.yml — verify the root key against DependencyInjection/Configuration.php
    m6_web_statsd_request_headers:
        headers:
            - X-Request-Id
            - X-Forwarded-Proto
    
  5. Diff the emitted metric names against what you had on v1.0.x. "Optimise… names" means the wire format changed. Sniff one request before and after (see below) and reconcile your dashboards before deploying, not after.

Where to look first, in this order:

  • DependencyInjection/Configuration.php — the real config schema. v1.1.0 may have added a route/name option here; assume nothing.
  • EventListener/ (or EventSubscriber/) — which kernel event fires, at what priority, and where it now reads the route from ($request->attributes->get('_route'), _route_params, or the raw path). This is the substance of the release.
  • Resources/config/services.yml — the service id you must satisfy, and whether it's a required constructor argument.

First use case worth shipping: measuring adoption of a header your edge sets, now broken down by route. "What fraction of /checkout requests arrive with X-Request-Id?" is the number that tells you whether log/trace correlation is actually possible per surface — and it's the one thing v1.1.0 makes easier than v1.0.

Implementation Patterns

Presence counters, not value gauges. The natural shape is still "header present / absent" per request, now attributed to a route:

app.request.header.x_request_id.present.<route_name>:1|c
app.request.header.x_request_id.absent.<route_name>:1|c

Verify the exact separator/segment order the release uses — "optim names" almost certainly means they flattened or reordered something here.

Use the route name, never the path. _route gives you checkout_submit — a bounded, code-controlled set. The raw path gives you /orders/12345 — one metric series per order id. If the listener in v1.1.0 appends $request->getPathInfo() rather than _route, that's a cardinality landmine: strip numerics/UUIDs or turn the feature off before it reaches production.

Pick your kernel event deliberately — and this release raises the stakes. The router listener runs at priority 32 on kernel.request; anything listening above that sees _route === null. If v1.1.0 reads the route at a high priority, you'll emit a large pile of …present.n/a series that look like a config bug. Read getSubscribedEvents() and confirm the priority is below the router. On kernel.response, _route is reliably set (including _route for 404s sometimes absent) — that's the safe point if the release didn't already handle it.

Gate by environment. UDP statsd from a test suite is pure noise and can mask real metrics:

# config/packages/test/…
m6_web_statsd_request_headers:
    enabled: false   # or point at a noop client

Better: swap the statsd client service for a no-op implementation in test and dev rather than toggling the bundle. Route-tagged metrics are especially noisy in functional tests, where every kernel boot may be a different route.

Run a local collector and diff v1.0 → v1.1. docker run -p 8125:8125/udp statsd/statsd (or a statsd_exporter with --statsd.listen-udp) plus nc -ul 8125 is the fastest way to see actual metric strings. Do this twice — once on the old tag, once on the new — and keep the transcript. The client gives you no feedback and the release notes are three words long; the wire is the only spec.

Per-route ratios, not per-route counts. Once route is a dimension you'll be tempted to alert on raw counts. Ratios (present / (present+absent) per route) survive traffic swings and are the metric that actually answers "did the CDN stop injecting this header on checkout?".

Decorating rather than forking. The cleanest extension point is to override the listener service definition in your app and add a metric prefix or an environment tag, keeping the bundle's parsing logic untouched. With v1.1.0, this is also how you'd remove the route segment if the naming scheme doesn't suit your backend.

Pair it with logs, not instead of them. Headers-in-statsd is an aggregate signal ("is the CDN injecting X-Cache-Status, and on which routes?"); headers in a Monolog processor are the per-request detail. Route-tagged statsd plus route-tagged logs is a genuinely useful pair; route-tagged statsd alone rarely answers an incident question.

Gotchas and Tips

  • Silent metric rename between 1.0 and 1.1. Statsd has no schema and no server-side error for "unknown metric". Your dashboards will simply go blank and your presence-ratio alerts will stop firing — the worst kind of failure. Grep your dashboard/alert definitions for the old names before upgrading, and keep both series emitting for one release if you can.
  • It is still archived. No security patches, no Symfony 4/5/6 DI compatibility (expect ContainerAware, non-autowired service definitions, and possibly a compiler pass that no longer resolves). A new tag on an archived repo is a courtesy release, not a maintenance commitment — it doesn't reset the migration clock. Budget for a fork, or better, a rewrite.
  • No changelog detail. "Optimise event (add route and optim names)" doesn't say whether the route is appended, prepended, or substituted for something. Read the diff of the listener between tags; three words are not a migration guide, and a formatting change here is indistinguishable from a breaking change at the statsd layer.
  • Route may be null. Unmatched requests, console/queue contexts, and listeners above priority 32 all yield an empty route. Decide explicitly whether that becomes unknown (bounded, safe) or an empty metric segment (app.request.header.x.present.:1|c — which some backends reject outright).
  • Cardinality is the trap, and v1.1.0 widens it. Never configure high-entropy headers (Authorization, Cookie, User-Agent, free-form X-Tenant) — raw values as metric names will blow up your statsd/Graphite/Prometheus backend. And now multiply by route: 40 routes × 10 header values is 400 series from a package that used to emit 10. Allowlist both axes explicitly.
  • Sensitive data leaks. Authorization, Cookie, X-Api-Key, and internal trace headers can end up in a metrics pipeline with weaker access controls than your logs. Route names also leak internal structure (feature flags, A/B variants, admin paths) into a shared metrics backend. Audit both before merging.
  • Header lookup is case-insensitive but single-valued. Symfony's HeaderBag::get() returns the first value; multi-value headers (Forwarded, Via, Accept) will be silently truncated. If you need all values, check whether the listener uses all().
  • PHP version ceiling. The 2016 composer.json likely constrains to ~5.5|~7.0. On PHP 8 you'll hit composer platform errors and runtime deprecations — and v1.1.0, being a small optimisation release, almost certainly didn't lift them. Forking to bump constraints is usually cheaper than fighting it.
  • UDP is fire-and-forget. If the daemon is down, the bundle throws nothing and logs nothing. Add an independent health check on the collector; don't infer "metrics work" from a green test suite.
  • Silent configuration drift. A typo'd header name doesn't error — you get a permanent absent series. Same for a renamed route: refactor checkout_submit → checkout_store and you get two half-populated series with no warning. Alert on the presence ratio per route dropping, not on the metric existing.
  • Extension points are limited by the era: no tags/dimensions, no sample rates exposed in config, no per-header formatting hooks. v1.1.0 hardcodes one more naming decision (route placement) rather than making naming configurable — which is itself the argument for replacing the listener.
  • The honest migration path is unchanged and now slightly better specified: a kernel.request subscriber (priority below 32) or kernel.response listener that reads _route, iterates an allowlist, calls $request->headers->has() / ->get(), and increments a counter on a modern client (league/statsd, or an OTel meter with route as an attribute) is roughly 30–40 lines and gives you real dimensions instead of string concatenation. v1.1.0 essentially documents the design you should copy. For a package with zero dependents, use the repo as a spec, not a dependency.
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.
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
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console