A client needed a solution to filter PHP APM traces before sending them to the Datadog server to reduce ingestion fees.
The filter rules were to exclude everything except requests exceeding 1 second and errors (HTTP code >= 400, exceptions, PHP errors).
They still wanted to utilize automatic instrumentation for several libraries (e.g., Laravel, Curl, PDO).
(The client is still using PHP 7.4, which is end-of-life; I know - they will upgrade to 8.x later.)
This auto-prepend script will filter out the specified request traces (returning from the function will retain the trace).
<?php // dd-filter.php register_shutdown_function(function() { // config $TIME_LIMIT_SEC = 1.0; // exit if Datadog (DDTrace) is NOT loaded if (!class_exists('\DDTrace\GlobalTracer') || !class_exists('\DDTrace\Tag')) { return; } // get HTTP status code $httpResponseCode = http_response_code(); if ($httpResponseCode >= 400) { return; // keep DD trace } // is the script exited with an error? $lastError = error_get_last(); if ($lastError) { return; // keep DD trace } // get current request time if (empty($_SERVER['REQUEST_TIME_FLOAT'])) { return; // keep DD trace } $startTime = $_SERVER['REQUEST_TIME_FLOAT']; $currentTime = microtime(true); $elapsedTime = max($currentTime - $startTime, 0.0); if ($elapsedTime > $TIME_LIMIT_SEC) { return; // keep DD trace } // drop DD trace $tracer = \DDTrace\GlobalTracer::get(); $span = $tracer->getActiveSpan(); if (null !== $span) { $span->setTag(\DDTrace\Tag::MANUAL_DROP, true); } });
(Yes, I know it would be better if the configuration, for example, TIME_LIMIT_SEC
, were kept in a separate file.)
This can be set up in the following way:
- Place this script to
/etc/php/7.4/datadog-filter/dd-filter.php
- Set the script for auto-prepending in
/etc/php/7.4/fpm/php.ini
:auto_prepend_file = /etc/php/7.4/datadog-filter/dd-filter.php
- Restart PHP-FPM:
systemctl restart php7.4-fpm
(The client is using their app on a Debian 12 Linux VM.)
Top comments (0)