watchlog / laravel-apm
Lightweight APM integration for Laravel apps using Watchlog
Requires
- php: >=7.4
- illuminate/support: ^8.0|^9.0|^10.0|^11.0|^12.0
This package is not auto-updated.
Last update: 2025-06-16 10:51:23 UTC
README
๐ฏ Lightweight, production-ready Application Performance Monitoring (APM) middleware for Laravel apps, designed for Watchlog.
Tracks request duration, memory usage, and status codes โ stores metrics in a buffer file, and automatically flushes them to your Watchlog Agent every 10 seconds.
๐ Features
- โ Compatible with Laravel 10 & 12+
- ๐ง Smart file-based metric buffering (no database or queue needed)
- ๐ Aggregates metrics per route (e.g.
/users/{id}
) - ๐ Tracks duration, memory, and status codes
- ๐ Safe and non-blocking โ doesn't slow down your requests
- ๐ Sends data automatically every 10 seconds to your Watchlog Agent
- ๐ท๏ธ Auto-detects service name from
.env
(WATCHLOG_APM_SERVICE
or fallback toAPP_NAME
)
๐ฆ Installation
1. Link local package (for development)
composer config repositories.watchlog-apm path ../laravel-watchlog-apm
composer require "watchlog/laravel-apm:*"
Adjust the path to match your local project structure.
โ๏ธ Usage (Laravel 12+)
In your bootstrap/app.php
, register the middleware:
use Watchlog\LaravelAPM\Middleware\WatchlogAPM; return Application::configure(basePath: dirname(__DIR__)) ->withRouting(...) ->withMiddleware(function (Middleware $middleware) { $middleware->append(WatchlogAPM::class); }) ->create();
๐ ๏ธ Service Identification
You can define your service name explicitly in .env
:
WATCHLOG_APM_SERVICE=orders-api
If not set, it will fallback to:
APP_NAME=laravel-app
๐ค How it works
During each request:
- The middleware tracks route, status code, duration, and memory.
- The data is written to a file:
storage/logs/apm-buffer.json
After the request ends:
- A shutdown function checks if 10 seconds have passed since the last flush.
- If yes, it:
- Reads all pending metrics from
apm-buffer.json
- Aggregates them by route/method
- Sends them to your Watchlog Agent as a JSON payload
- Clears the buffer
- Reads all pending metrics from
๐ฆ What gets sent?
{ "collected_at": "2025-05-18T12:00:00Z", "platformName": "laravel", "metrics": [ { "type": "aggregated_request", "service": "orders-api", "path": "hello/{id}", "method": "GET", "request_count": 3, "error_count": 0, "avg_duration": 6.1, "max_duration": 8.2, "avg_memory": { "rss": 18432000, "heapUsed": 23998464, "heapTotal": 25600000 } } ] }
๐ File structure
laravel-watchlog-apm/ โโโ src/ โ โโโ Middleware/ โ โ โโโ WatchlogAPM.php โ โโโ Collector.php โ โโโ Sender.php โโโ composer.json โโโ README.md
๐งช Debugging & Testing
You can manually flush metrics via tinker:
php artisan tinker >>> (new \Watchlog\LaravelAPM\Sender())->flush();
๐ Recommended .gitignore
Add the following to your Laravel app's .gitignore
:
/storage/logs/apm-buffer.json /storage/logs/apm-debug.log /storage/framework/cache/watchlog-apm.lock
โ Notes
- The route path is captured via
$request->route()?->uri()
for correct dynamic segment grouping (/users/{id}
) - Multiple requests within 10 seconds are buffered, then aggregated and sent in a single payload
- The flush lock uses a simple file timestamp (
watchlog-apm.lock
) to prevent oversending - The middleware is safe: flush failures won't crash your app
๐ License
MIT ยฉ Mohammadreza
Built for Watchlog.io