arkaitzgarro / elastic-apm-laravel
Laravel APM agent for Elastic v2 intake API
Installs: 291 849
Dependents: 1
Suggesters: 0
Security: 0
Stars: 80
Watchers: 4
Forks: 17
Open Issues: 2
Requires
- php: ^8.0.2
- http-interop/http-factory-guzzle: ^1.0
- illuminate/contracts: ^10.0|^11.0
- illuminate/database: ^10.0|^11.0
- illuminate/http: ^10.0|^11.0
- illuminate/routing: ^10.0|^11.0
- illuminate/support: ^10.0|^11.0
- jasny/persist-sql-query: ^2.0
- nipwaayoni/elastic-apm-php-agent: ^8.0
Requires (Dev)
- codeception/codeception: ^5
- codeception/mockery-module: ^0.5
- friendsofphp/php-cs-fixer: ^3.0
- orchestra/testbench: ^8.0|^9.0
- php-http/guzzle7-adapter: ^1.0.0
- symfony/service-contracts: ^2.0|^3.0
Suggests
- php-http/guzzle6-adapter: Guzzle Http client adapter for guzzlehttp/guzzle version 6
- php-http/guzzle7-adapter: Guzzle Http client adapter for guzzlehttp/guzzle version 7
- dev-master
- v6.1.0
- v6.0.0
- v5.0.0
- v4.0.1
- v4.0.0
- v4.0.0-BETA-2
- v4.0.0-BETA
- v3.1.0
- v3.0.9
- v3.0.8
- v3.0.7
- v3.0.6
- v3.0.5
- v3.0.4
- v3.0.3
- v3.0.2
- v3.0.1
- v3.0
- v3.0-RC2
- v3.0-RC1
- 2.x-dev
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0
- v2.0-RC5
- v2.0-RC4
- v2.0-RC3
- v2.0-RC2
- v2.0-RC1
- v1.5.6
- v1.5.5
- v1.5.4
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.0
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.0
- v1.0.1
- v1.0.0
- dev-chore/service-provider-tests
This package is auto-updated.
Last update: 2024-11-07 08:36:12 UTC
README
Elastic APM agent for v2 intake API. Compatible with Laravel 6+.
Prerequisites
You are responsible for completing the following as part of installing this package.
HTTP Client
In order to minimize potential dependency conflicts, this package does not dictate the HTTP client which will be used to send data to APM. Instead, your project must include a suitable PSR-18 compatible implementation. The easiest way to do this is using the php-http adapter for GuzzleHTTP. Require either the guzzle6 or guzzle7 adapter, depending on your specific needs.
# if you are using guzzlehttp/guzzle version 6 # note that you must use >=2.0 of the guzzle6-adapter composer require php-http/guzzle6-adapter
# if you are using guzzlehttp/guzzle version 7
composer require php-http/guzzle7-adapter
Installation
Require this package with composer:
# Laravel 8+ and PHP 8+ composer require arkaitzgarro/elastic-apm-laravel # Laravel 6+ composer require arkaitzgarro/elastic-apm-laravel:^3.0 # Laravel 5.5 - 5.8 composer require arkaitzgarro/elastic-apm-laravel:^2.0
Laravel's provider auto-discover should find the package ServiceProvider. Otherwise, add the ServiceProvider class to the providers array in config/app.php
:
'providers' => [ // ... more providers \AG\ElasticApmLaravel\ServiceProvider::class, ],
From here, we will take care of everything based on your configuration. The agent and the middleware will be registered, and transactions will be sent to Elastic.
Agent configuration
The underlying APM Agent may be configured using environment variables as of version 2.0 of this package. Place the ELASTIC_APM_*
variables in your .env
file or use any other appropriate means to make them available to your project.
Note that features of the Agent may not be documented here and you should refer to the nipwaayoni/elastic-apm-php-agent
project documentation for the full feature set.
The following options are still supported by this package and will take precedence over their ELASTIC_APM_*
counterparts if present.
The APM_*
variables listed above may be removed in a future release.
Laravel Options
The following environment variables are supported in the default configuration:
You may also publish the elastic-apm-laravel.php
configuration file to change additional settings:
php artisan vendor:publish --tag=config
Once published, open the config/elastic-apm-laravel.php
file and review the various settings.
Logging
The Monolog instance used by your Laravel application will be automatically given to the Agent for logging. The log level for the Agent package is independent of the log level for your Laravel application. This allows you to only include Agent messages when they are useful. Use the APM_LOG_LEVEL
environment setting for this. The default log level for the agent package is info
.
Collectors
The default collectors typically listen on events to measure portions of the request such as framework loading, database queries, or jobs.
The SpanCollector in particular allows you to measure any section of your own code via the ApmCollector
Facade:
use AG\ElasticApmLaravel\Facades\ApmCollector; ApmCollector::startMeasure('my-custom-span', 'custom', 'measure', 'My custom span'); // do something amazing ApmCollector::stopMeasure('my-custom-span');
To record an additional span around your job execution, you may include the provided job middleware:
public function middleware() { return [ app(\AG\ElasticApmLaravel\Jobs\Middleware\RecordTransaction::class), ]; }
Note Job middleware is not run when a job is created with the dispatchNow()
method. Spans explicitly created within the job will still be collected, but the overall job span will not be included.
Add a collector for other events
You can add extra collector(s) to listen to your own application events or Laravel events like Illuminate\Mail\Events\MessageSending
for example. We created a base collector that already includes functionality to measure events, that you can extend from:
// app/Collectors/MailMessageCollector.php namespace YourApp\Collectors; use AG\ElasticApmLaravel\Contracts\DataCollector; use AG\ElasticApmLaravel\Collectors\EventDataCollector; use Illuminate\Mail\Events\MessageSending; use Illuminate\Mail\Events\MessageSent; class MailMessageCollector extends EventDataCollector implements DataCollector { public function getName(): string { return 'mail-message-collector'; } protected function registerEventListeners(): void { $this->app->events->listen(MessageSending::class, function (\Swift_Message $message) { $this->startMeasure( 'mail #' . $message->getId(), 'mail.delivery', ); }); $this->app->events->listen(MessageSent::class, function (\Swift_Message $message) { $this->stopMeasure('mail #' . $message->getId()); }); } }
Don't forget to register your collector when the application starts:
// app/Providers/AppServiceProvider.php use AG\ElasticApmLaravel\Facades\ApmCollector; use YourApp\Collectors\MailMessageCollector; public function boot() { // ... ApmCollector::addCollector(MailMessageCollector::class); }
Alternatively, you can now simply tag your collector in the container and it will be discovered. Note that the collector must be tagged before the Agent
is first resolved from the container, normally in the boot
method of your provider.
// app/Providers/AppServiceProvider.php use YourApp\Collectors\MailMessageCollector; public function boot() { $this->app->tag(MailMessageCollector::class, \AG\ElasticApmLaravel\ServiceProvider::COLLECTOR_TAG); }
Note Collecting events is subject to the APM_MAXTRACEITEMS
setting. If your collector defers adding events until the request is complete, and the total event count exceeds the max trace items, a higher than expected number of your events may be dropped. You should make every effort to collect events at the point they occur during the request processing. Using the EventDataCollector::startMeasure()
method will flag an event for collection even if the max trace items has been reached when the measure is stopped.
Distributed Tracing
Distributed tracing allows you to associate transactions in your Laravel application with transactions in services your application consumes. For example, if your Laravel application calls REST resources as part of handling a request, the REST transaction details will appear within your application transaction in Elastic APM. You enable distributed tracing by including an appropriate header in the http request your application makes to another service. For example:
$request = new Request( 'PUT', '/some/backend/resource', [ 'Content-Type' => 'application/json', ], json_encode(...) ); $request = \AG\ElasticApmLaravel\Facades\ApmAgent::addTraceParentHeader($request); $this->client->send($request);
If you are not dealing with a RequestInterface
object, you can get the current transaction and use the array or string methods to get the traceparent
.
$transaction = ApmAgent::getCurrentTransaction(); $headerArray = $transaction->traceHeaderAsArray(); $headerString = $transaction->traceHeaderAsString();
Development
Get Composer. Follow the instructions defined on the official Composer page, or if you are using homebrew
, just run:
brew install composer
Install project dependencies:
composer install
Run the unit test suite:
php vendor/bin/codecept run
Please adhere to PSR-2 and Symfony coding standard. Run the following commands before pushing your code:
php ./vendor/bin/php-cs-fixer fix
Integrate with a running application
To be able to test your changes with a locally running application, use Composer's functionality to require packages from local paths. On your project, add a local repository, just make sure the path to elastic-apm-laravel
folder is correct:
composer config repositories.local '{"type": "path", "url": "../elastic-apm-laravel"}' --file composer.json
Then install the package from the source:
composer require arkaitzgarro/elastic-apm-laravel:@dev --prefer-source
You should see a message indicating that the package has been installed as symlink:
- Installing arkaitzgarro/elastic-apm-laravel (dev-chore/branch-name): Symlinking from ../elastic-apm-laravel