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

Elastic Apm Laravel Laravel Package

arkaitzgarro/elastic-apm-laravel

Integrates Elastic APM with Laravel to monitor application performance. Automatically traces HTTP requests, database queries, and background jobs, sending transaction and span data to the Elastic APM server for analysis and debugging.

View on GitHub
Deep Wiki
Context7

Getting Started

Requirements for v8.0.0: PHP 8.3+ and Laravel 12 or 13. If you are still on Laravel 11 or PHP 8.2 you cannot upgrade — this is a hard gate, not a soft deprecation.

  1. Install the package:

    composer require arkaitzgarro/elastic-apm-laravel
    
  2. Publish the config:

    php artisan vendor:publish --tag=elastic-apm-laravel-config
    

    This creates config/elastic-apm-laravel.php.

  3. Add the minimum set of environment variables to .env:

    ELASTIC_APM_SERVICE_NAME=my-laravel-app
    ELASTIC_APM_SERVER_URL=http://localhost:8200
    ELASTIC_APM_SECRET_TOKEN=
    ELASTIC_APM_ENVIRONMENT=local
    ELASTIC_APM_ENABLED=true
    

    Add the same keys to .env.example, but leave ELASTIC_APM_SECRET_TOKEN and ELASTIC_APM_API_KEY empty.

  4. Register the package middleware. In Laravel 12/13 (bootstrap/app.php):

    ->withMiddleware(function (Middleware $middleware) {
        $middleware->prepend(\Arkaitzgarro\ElasticApmLaravel\Middleware\RecordTransaction::class);
    })
    

    Place it early in the stack so the transaction starts before routing, auth, and DB work you want measured.

  5. First use case — validate on one known endpoint. Hit GET / through the app, then open Kibana → Observability → APM → Services and confirm a transaction appears with a sane name, duration, and no PHP-agent warnings. Once you see that single trace, enable it in staging.

Where to look first: config/elastic-apm-laravel.php (the whole integration is driven from here), then the package README for the exact middleware class names and tags it ships with — class names have shifted across majors.

Implementation Patterns

Global transaction capture via middleware. The standard pattern is one global middleware that opens a transaction per request and names it. Keep it in the global stack, not the web group, so API routes and health checks are covered too.

Keep transaction names low-cardinality. Prefer the route pattern (GET /users/{id}) over the concrete URI (GET /users/42). High-cardinality names blow up Kibana’s aggregation and make the APM UI useless. If the package does not normalise this for you, override it after the transaction is created.

Custom spans around outbound I/O. Wrap third-party HTTP calls, S3 uploads, or slow internal RPC in explicit spans so they show up as children of the request rather than as an unexplained gap:

$transaction = \Elastic\Apm\ElasticApm::getCurrentTransaction();
$span = $transaction->beginCurrentSpan('stripe.charge', 'external.http');
try {
    $response = $this->stripe->charges->create([...]);
} finally {
    $span->end();
}

The finally block matters — an un-ended span corrupts the parent/child timing.

Use labels for slicing, not for messages. Attach low-cardinality tags (tenant_tier, api_version, feature_flag) to the transaction. Never put user IDs, emails, or request bodies in labels; they are indexed and retained.

Pair the middleware with exception handling. Middleware catches the request lifecycle, but exceptions rendered by the handler can escape the transaction. Verify that a thrown ModelNotFoundException or a 500 still produces an error event with the stack trace attached to the current transaction — if not, capture it in App\Exceptions\Handler / bootstrap/app.php and record it explicitly.

Disable aggressively outside production-like environments. In phpunit.xml and local .env:

ELASTIC_APM_ENABLED=false

This avoids test-suite slowdowns and phantom transactions from feature tests polluting your service metrics.

Tune sampling per environment. Start at ELASTIC_APM_TRANSACTION_SAMPLE_RATE=1.0 in staging, drop to 0.1–0.2 in production once the service is validated. Sampling applies to transactions, not errors — error events still come through.

Deploy as a config-published package, not a black box. Commit config/elastic-apm-laravel.php to the repo rather than relying on vendor defaults, so that upgrades in v8.x don’t silently change behaviour under you.

Version-stamp your deployments. Set ELASTIC_APM_SERVICE_VERSION from your release tag (e.g. git describe --tags) so APM can correlate error-rate spikes to a deploy.

Integrate with CI as a gate. Run the app against a throwaway APM Server container in an integration job and assert that one request produces one transaction — this catches middleware-ordering regressions that unit tests never see.

Gotchas and Tips

  • v8.0.0 drops Laravel 11 and PHP 8.2. Before bumping, audit: composer.json platform config, CI matrix (shivammathur/setup-php versions), Dockerbase images, and any laravel/framework constraint that still permits ^11. If any downstream package pins Laravel 11, this is a blocker, not a warning.
  • Check whether you also need the native elastic_apm PHP extension. The package is a Laravel wrapper; whether it drives the extension or talks to the APM Server directly determines your Dockerfile (docker-php-ext-install / PECL) and your php.ini. Get this wrong and you get a silently no-op integration that never errors.
  • php artisan config:cache freezes env vars. Deploy pipelines that cache config at build time will bake in whatever ELASTIC_APM_* values existed then. Cache after env injection, or read these values via env() in a non-cached bootstrap path.
  • Middleware ordering. If the middleware runs after StartSession or after the auth middleware, unauthenticated-request traces and early exceptions are invisible. Prepend it.
  • Silent failure is the default. APM agents are designed not to break your app, which means a bad SERVER_URL or a missing token produces zero data and zero logs. When debugging, set ELASTIC_APM_LOG_LEVEL=debug and watch storage/logs/laravel.log — this is the first thing to check when "nothing shows up in Kibana".
  • Long-running processes distort numbers. Octane, queue workers, and php artisan serve keep a single process alive; per-request memory and transaction boundaries need explicit attention. Test under Octane if you deploy there — behaviour can differ meaningfully from FPM.
  • Health checks and Horizon/queue polling dominate transaction counts. Exclude /health, /up, and /_horizon/* (middleware exclusion or route-level opt-out) or they will swamp real traffic in the service view and skew p95 latency.
  • Secret leakage risk. ELASTIC_APM_SECRET_TOKEN / ELASTIC_APM_API_KEY in a committed .env or a config file is a real incident. Keep them in your secret manager and confirm config:cache output isn’t written to a public artefact.
  • Queue jobs are not automatically traced like HTTP requests. If you rely on job-level APM data, confirm the package version instruments the queue worker; otherwise wrap handle() manually with a transaction.
  • Upgrade path: pin "arkaitzgarro/elastic-apm-laravel": "^8.0" only after your Laravel 12/13 and PHP 8.3+ baselines are confirmed across all environments; the package has no graceful fallback for the dropped platform versions — Composer will simply refuse to install.
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.
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
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource