diff --git a/README.md b/README.md index d411126..b1e6a85 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ composer require bethinkpl/elastic-apm-laravel ## Additional features * `X-Requested-By` HTTP request header value is set as `labels.requested_by` APM transaction field (`end-user-ajax` value is used when `X-Requested-With: XMLHttpRequest` is set) +* sampling of transactions reported to APM * tracking of HTTP requests performed using GuzzleHttp library. Simply add the following middleware to your Guzzle client: ```php @@ -115,6 +116,7 @@ The following environment variables are supported in the default configuration: |APM_BACKTRACEDEPTH | Defaults to `25`. Depth of backtrace in query span. | |APM_RENDERSOURCE | Defaults to `true`. Include source code in query span. | |APM_HTTPLOG | Defaults to `true`. Will record HTTP requests performed via GuzzleHttp. | +|APM_SAMPLING | Defaults to `100`. Sets the percentage of transactions that will be reported to APM (ranges from 0 to 100). You may also publish the `elastic-apm.php` configuration file to change additional settings: diff --git a/config/elastic-apm.php b/config/elastic-apm.php index a1be827..afc8e7f 100644 --- a/config/elastic-apm.php +++ b/config/elastic-apm.php @@ -4,6 +4,9 @@ // Sets whether the apm reporting should be active or not 'active' => env('APM_ACTIVE', true), + // Applies sampling of transactions to be reported to APM, defaults to 100% + 'sampling' => env('APM_SAMPLING', 100), + 'app' => [ // The app name that will identify your app in Kibana / Elastic APM 'appName' => env('APM_APPNAME', 'Laravel'), diff --git a/src/Providers/ElasticApmServiceProvider.php b/src/Providers/ElasticApmServiceProvider.php index 46991b3..97c669c 100644 --- a/src/Providers/ElasticApmServiceProvider.php +++ b/src/Providers/ElasticApmServiceProvider.php @@ -28,6 +28,9 @@ class ElasticApmServiceProvider extends ServiceProvider /** @var float */ private static $lastHttpRequestStart; + /** @var bool */ + private static $isSampled = true; + /** * Bootstrap the application services. * @@ -41,7 +44,7 @@ public function boot() ], 'config'); } - if (config('elastic-apm.active') === true && config('elastic-apm.spans.querylog.enabled') !== false) { + if (config('elastic-apm.active') === true && config('elastic-apm.spans.querylog.enabled') !== false && self::$isSampled) { $this->listenForQueries(); } } @@ -59,6 +62,10 @@ public function register() 'elastic-apm' ); + // apply transactions reporting sampling + $samplingRate = intval(config('elastic-apm.sampling')) ?: 100; + self::$isSampled = $samplingRate > mt_rand(0, 100); + $this->app->singleton(Agent::class, function ($app) { return new Agent( array_merge( @@ -67,7 +74,7 @@ public function register() 'frameworkVersion' => app()->version(), ], [ - 'active' => config('elastic-apm.active'), + 'active' => config('elastic-apm.active') && self::$isSampled, 'httpClient' => config('elastic-apm.httpClient'), ], $this->getAppConfig(), @@ -88,7 +95,6 @@ public function register() $this->app->alias(Agent::class, 'elastic-apm'); $this->app->instance('apm-spans-log', $collection); - } /** @@ -227,8 +233,8 @@ function(RequestInterface $request, array $options) { self::$lastHttpRequestStart = microtime(true); }, function (RequestInterface $request, array $options, PromiseInterface $promise) { - // leave early if monitoring is disabled - if (config('elastic-apm.active') !== true || config('elastic-apm.spans.httplog.enabled') !== true) { + // leave early if monitoring is disabled or when this transaction is not sampled + if (config('elastic-apm.active') !== true || config('elastic-apm.spans.httplog.enabled') !== true || !self::$isSampled) { return; }