watchlog / laravel-apm
Lightweight APM integration for Laravel apps using Watchlog
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
pkg:composer/watchlog/laravel-apm
Requires
- php: >=7.4
- illuminate/support: ^8.0|^9.0|^10.0|^11.0|^12.0
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_SERVICEor 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();
๐ ๏ธ Configuration
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
Agent URL Configuration
The package automatically detects the agent endpoint, but you can override it for Docker:
Option 1: Environment Variable (Recommended for Docker)
WATCHLOG_APM_AGENT_URL=http://watchlog-agent:3774/apm
Option 2: Config File
Publish the config file (if available) or add to your config/services.php:
'watchlog' => [ 'apm' => [ 'agent_url' => env('WATCHLOG_APM_AGENT_URL', ''), ], ],
Option 3: Direct Usage
use Watchlog\LaravelAPM\Sender; $sender = new Sender('http://watchlog-agent:3774/apm'); $sender->flush();
If not provided, the package will auto-detect:
- Local / non-K8s:
http://127.0.0.1:3774/apm - Kubernetes:
http://watchlog-node-agent.monitoring.svc.cluster.local:3774/apm
๐ค 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
๐ณ Docker Setup
When running your Laravel app in Docker, configure the agent URL:
Docker Compose Example:
version: '3.8' services: watchlog-agent: image: watchlog/agent:latest container_name: watchlog-agent ports: - "3774:3774" environment: - WATCHLOG_APIKEY=your-api-key - WATCHLOG_SERVER=https://log.watchlog.ir networks: - app-network laravel-app: build: . container_name: laravel-app ports: - "8000:8000" environment: - WATCHLOG_APM_AGENT_URL=http://watchlog-agent:3774/apm - WATCHLOG_APM_SERVICE=my-laravel-app depends_on: - watchlog-agent networks: - app-network networks: app-network: driver: bridge
Docker Run Example:
# 1. Create network docker network create app-network # 2. Run Watchlog Agent docker run -d \ --name watchlog-agent \ --network app-network \ -p 3774:3774 \ -e WATCHLOG_APIKEY="your-api-key" \ -e WATCHLOG_SERVER="https://log.watchlog.ir" \ watchlog/agent:latest # 3. Run Laravel app (set WATCHLOG_APM_AGENT_URL in your .env or docker run) docker run -d \ --name laravel-app \ --network app-network \ -p 8000:8000 \ -e WATCHLOG_APM_AGENT_URL="http://watchlog-agent:3774/apm" \ my-laravel-app
Important Notes:
- When using Docker, use the container name as the hostname (e.g.,
watchlog-agent) - Both containers must be on the same Docker network
- The agent must be running before your app starts
- Set
WATCHLOG_APM_AGENT_URLin your.envfile or as an environment variable - If
WATCHLOG_APM_AGENT_URLis not provided, auto-detection will be used (local or Kubernetes)
โ 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