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

Datadog Laravel Laravel Package

christian98/datadog-laravel

christian98/datadog-laravel integrates Laravel applications with Datadog, forwarding logs, metrics, and traces to your Datadog account. It ships a service provider, configurable handlers, and helpers for quick, low-effort observability setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish

composer require christian98/datadog-laravel
php artisan vendor:publish --tag=datadog-config   # verify the tag name in the provider

The service provider is auto-discovered on Laravel 5.5+. On older versions register Christian98\Datadog\DatadogServiceProvider in config/app.php and alias the facade.

Point it at an agent. This package wraps datadog/php-datadogstatsd, so it speaks UDP/8125 to a local Datadog Agent — it is not an APM tracer. Run the agent (or the datadog/datadog container) and confirm:

docker run -d --name dd-agent -e DD_API_KEY=$DD_API_KEY \
  -e DD_DOGSTATSD_NON_LOCAL_TRAFFIC=true -p 8125:8125/udp datadog/agent:latest

First use case — count something you already care about:

use Datadog; // facade, verify the alias the provider registers

Datadog::increment('user.signup', 1, ['plan' => 'pro']);
Datadog::timing('checkout.render', $ms, ['step' => 'payment']);

Where to look first (in this order): config/datadog.php for host/port/namespace/global tags/enabled flag → the service provider's container binding (this tells you whether you get a singleton DogStatsd or a lazily-built client) → the facade class for the exact method surface → the pinned datadog/php-datadogstatsd version in composer.lock, because the SDK's method names and signatures are what you're really programming against.

Implementation Patterns

Wrap it, don't call it everywhere. Because this package is a thin, low-traffic wrapper, the highest-value thing you can do is put your own interface in front of it:

interface Metrics
{
    public function increment(string $metric, int $value = 1, array $tags = []): void;
    public function timing(string $metric, float $ms, array $tags = []): void;
    public function gauge(string $metric, float $value, array $tags = []): void;
}

final class DatadogMetrics implements Metrics { /* delegates to the facade */ }
final class NullMetrics implements Metrics { /* no-ops */ }

Bind Metrics in a provider and choose the implementation off config('datadog.enabled') and app()->environment(). This gives you a no-op in testing/local for free, and lets you swap the transport if the package stalls.

Tag discipline is the whole game. Tags are the only dimension you get; every unique tag combination is a billable time series.

// good — bounded cardinality
Datadog::increment('order.placed', 1, ['plan' => $plan, 'currency' => $currency]);
// bad — one time series per user forever
Datadog::increment('order.placed', 1, ['user_id' => $user->id, 'order_id' => $order->id]);

Anything unbounded (user IDs, request IDs, emails, URLs with IDs, exception messages) belongs in logs or traces, never tags.

Middleware for request timing, registered globally or on a group:

public function handle($request, Closure $next)
{
    $start = microtime(true);
    $response = $next($request);
    Datadog::timing('http.request', (microtime(true) - $start) * 1000, [
        'route' => optional($request->route())->getName() ?? 'unmatched',
        'method' => $request->method(),
        'status' => $response->getStatusCode(),
    ]);
    return $response;
}

Queue jobs — JobProcessing/JobProcessed listeners keyed on $event->job->resolveName(), emitting timing plus separate increment for success/failure. Scheduler — wrap each task in timing and emit a service_check so a silent non-run is visible.

Use distribution, not histogram, when you want percentiles. Histograms on the agent give you avg/max/median and a rough approximation; distributions are aggregated server-side for real p50/p95/p99.

Sample high-volume events rather than emitting per row:

Datadog::increment('cache.hit', 1, ['pool' => 'redis'], 0.1); // verify the sample-rate arg position for your SDK version

Gotchas and Tips

  • UDP is fire-and-forget. If the agent isn't reachable, packets are dropped and nothing throws, logs, or queues. A typo'd host costs you a week of blank dashboards. Verify end-to-end with Datadog::increment('debug.ping') and check the Metrics Explorer immediately after deploying.
  • This is StatsD metrics, not tracing. It does not create spans, propagate context, or instrument queries. For APM you need datadog/dd-trace configured separately; the two coexist fine but solve different problems.
  • config:cache will bite you. Any env() call outside a config/ file returns null once config is cached. Keep DATADOG_ENABLED, DATADOG_HOST, DD_AGENT_HOST reads inside config/datadog.php only.
  • Docker networking. 127.0.0.1 inside your app container is not the host. Set DATADOG_HOST=host.docker.internal (or the agent's compose service name) and remember DD_DOGSTATSD_NON_LOCAL_TRAFFIC=true — it defaults to false and silently drops external packets.
  • Namespace double-prefixing. If you set a namespace in config and hand-prefix metric names ('myapp.orders'), you get myapp.myapp.orders. Pick one convention and grep for it.
  • Octane / long-lived workers. A singleton holding a UDP socket survives across requests; sockets can go stale after agent restarts. If you see metrics dry up after an agent redeploy, try a scoped() binding or periodically re-resolving the client. Also call the SDK's flush method (if your pinned version has one) at the end of long CLI commands, since batched packets may not be sent.
  • Packet size. A single UDP datagram is capped (~1432 bytes safe). Emitting a metric with dozens of long tags per row fragments or drops. Keep tag sets small.
  • Units. timing is milliseconds. Passing microtime(true) (seconds) yields a dashboard reading ~1000× low and looks like a "traffic drop."
  • Testing. Bind NullMetrics in the test environment and assert on your interface with a spy, rather than trying to inspect UDP. If you must integration-test, point the client at a local UDP listener socket.
  • Vendor risk. Zero stars, zero dependents, a single-maintainer GitLab repo. Pin the version with composer require christian98/datadog-laravel:^x.y, never dev-main. The abstraction layer from Implementation Patterns is your exit ramp — replacing it with a 40-line service binding directly to DataDog\DogStatsd is trivial if the package goes unmaintained.
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