theplankmeister/datadog_bundle
A Symfony bundle that integrates Datadog monitoring into your PHP applications, helping you ship metrics, traces, and logs to Datadog from your Symfony services with minimal configuration.
Before you start — framework mismatch. This is a Symfony 4 bundle, not a Laravel package. The naming (_bundle suffix, config/bundles.php) and the "for your Symfony4 app" description make this clear. If you are working in a Laravel codebase, this bundle will not register via App\Providers\...; you would be importing Symfony framework conventions into a Laravel app, which does not work. For Laravel, prefer datadog/php-datadogstatsd, the official DataDog/dd-trace-php extension, or a small custom service wrapper around the Datadog API. Treat the rest of this assessment as Symfony-only guidance.
Minimal Symfony 4 setup
composer require theplankmeister/datadog_bundle
config/bundles.php:
return [
// ...
ThePlankmeister\DatadogBundle\DatadogBundle::class => ['all' => true],
];
(Verify the exact namespace — check composer.json → autoload.psr-4 and the bundle class name after install.)config/packages/datadog.yaml. The package expects Datadog API key and app key plus an environment/tag set. Read src/DependencyInjection/Configuration.php for the exact tree — that file is the source of truth for config keys..env (DATADOG_API_KEY, DATADOG_APP_KEY) and reference them with %env(...)% in the YAML. Never commit keys.bin/console cache:clear.Where to look first, in order
README.md — usage example and the service alias to inject.src/DependencyInjection/Configuration.php — the real config schema.src/Resources/config/services.yaml (or .xml) — the service ID, alias, and constructor args you actually autowire against.composer.json — supported Symfony versions, PHP constraint, and last-updated dependency versions.First use case. Inject the bundle's service into a controller and emit a counter on a business event:
public function checkout(StatsService $stats) // use the actual service ID/alias
{
$stats->increment('orders.completed', ['channel' => 'web']);
// ...
}
Confirm the real method names (increment, gauge, histogram, timing, event) against the source — this package wraps Datadog's API, and the method set is not guaranteed to match Datadog's official client 1:1.
Wrap it, don't scatter it. Define your own narrow interface (e.g. App\Metrics\MetricsInterface with increment(), timing(), gauge()) and implement it against this bundle's service. Application code depends on your interface, not the bundle. This gives you:
Environment-aware wiring. Register the real implementation in config/services.yaml for prod/staging, and a NullMetrics implementation in config/services_dev.yaml/services_test.yaml. Metrics in local dev either fail loudly or pollute your dashboards — neither is acceptable.
Emit at boundaries, not in loops. Datadog API calls are HTTP round-trips. The right pattern is one call per request/job/command: a timing in a kernel.terminate listener or an API call in a job completion handler. Do not call it per-item inside a foreach on a batch job — batch the counts and emit once.
Integration points that work well:
kernel.request/kernel.terminate to time whole requests.timing plus a gauge for rows processed.error tag on failure.Tagging discipline. Every metric should carry a small, fixed tag set: env, service, and version at minimum. Keep cardinality bounded — do not tag with user IDs, request IDs, or raw URLs, or your Datadog bill will surprise you.
Failure isolation. Wrap calls in your wrapper:
try {
$this->client->increment($name, $tags);
} catch (\Throwable $e) {
$this->logger->warning('metric failed', ['name' => $name, 'e' => $e]);
}
Metrics must never break the request that generates them.
Testing. Bind your MetricsInterface to a spy that records calls, then assert in a functional test:
$client = static::createClient();
$client->request('POST', '/checkout');
$this->assertSame(['orders.completed'], $spy->increments());
Bundle class and routing/config APIs changed), and there are no dependents to reveal maintained forks. Budget time to either pin Symfony 4 or replace the bundle.src/), every metric is a blocking HTTPS call to api.datadoghq.com. That is tens of milliseconds per call and a hard dependency on Datadog's availability for your request latency. Consider StatsD (datadog/php-datadogstatsd) or the dd-trace-php extension for anything on a hot path.Configuration.php no longer matches. Always grep the real class before writing YAML, and run bin/console debug:config <bundle_alias> to see the merged tree Symfony actually resolved.datadog) and the service ID you autowire (theplankmeister_datadog.service or similar) are different names. Get the alias from DebugExtension::getAlias() in src/DependencyInjection/; get the service ID from src/Resources/config/services.*. bin/console debug:container <name> confirms what is injectable.services.yaml or add a config file, bin/console cache:clear (and rm -rf var/cache) — Symfony 4 caches DI aggressively and a stale container gives misleading "service not found" errors.debug: true.decorates: in services.yaml) rather than editing vendor code. A decorator lets you add batching, sampling, or a kill-switch without forking.sample_rate tag) rather than sending everything and paying for it.How can I help you explore Laravel packages today?