methorz / http-request-logger
PSR-3 HTTP request logging middleware with request tracking and performance monitoring
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/methorz/http-request-logger
Requires
- php: ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0
- psr/http-message: ^1.0 || ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^3.0
Requires (Dev)
- monolog/monolog: ^3.0
- nyholm/psr7: ^1.8
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0 || ^12.0
- psr/container: ^2.0
- slevomat/coding-standard: ^8.25
- squizlabs/php_codesniffer: ^4.0
Suggests
- laminas/laminas-servicemanager: For Mezzio integration (use Integration\Mezzio\ConfigProvider)
- monolog/monolog: PSR-3 compatible logger implementation
This package is auto-updated.
Last update: 2025-12-01 09:38:27 UTC
README
PSR-3 structured logging with request tracking and performance monitoring for PSR-15 applications
Automatically add request IDs and performance metrics to all logs in PSR-15 middleware applications. Zero configuration, framework-agnostic, production-ready.
โจ Features
- ๐ Request ID Tracking - Unique ID for every request, added to all logs automatically
- โฑ๏ธ Performance Monitoring - Track execution time and memory usage for requests and operations
- ๐ฏ PSR-15 Middleware - Drop-in middleware for automatic logging
- ๐ Structured Logs - JSON-compatible context for easy parsing and analysis
- ๐ง PSR-3 Compatible - Works with any PSR-3 logger (Monolog, etc.)
- ๐ Response Headers - Optionally adds
X-Request-IDheader to responses - ๐ Zero Configuration - Works out-of-the-box with sensible defaults
- ๐จ Customizable - Full control over processors and logging behavior
๐ฆ Installation
composer require methorz/http-request-logger
๐ Quick Start
1. Add Middleware to Your Application
use MethorZ\RequestLogger\Middleware\LoggingMiddleware; // Mezzio / Laminas $app->pipe(new LoggingMiddleware($logger)); // Any PSR-15 application $dispatcher->pipe(new LoggingMiddleware($logger));
That's it! Every request will now have:
- Unique request ID in all logs
- Request start/end logging
- Automatic performance metrics
- Exception logging with context
๐ Detailed Usage
Request ID Processor
Adds a unique request ID to all log records:
use MethorZ\RequestLogger\Processor\RequestIdProcessor; use Monolog\Logger; $logger = new Logger('app'); $logger->pushProcessor(new RequestIdProcessor()); $logger->info('User logged in', ['user_id' => 123]); // Log output includes: {"message": "User logged in", "extra": {"request_id": "req_..."}"}
Custom Request ID:
$processor = new RequestIdProcessor('custom-request-id');
Retrieve Request ID:
$requestId = $processor->getRequestId();
Performance Logger
Track performance metrics for operations:
use MethorZ\RequestLogger\Logger\PerformanceLogger; $perfLogger = new PerformanceLogger($logger); // Method 1: Start/End $perfLogger->start('database-query'); $users = $repository->findAll(); $perfLogger->end('database-query', ['query' => 'SELECT * FROM users']); // Method 2: Measure callable $result = $perfLogger->measure('api-call', function () use ($apiClient) { return $apiClient->fetchData(); }, ['endpoint' => '/api/users']); // Method 3: Log request performance $startTime = microtime(true); // ... handle request ... $perfLogger->logRequest($startTime, [ 'method' => 'POST', 'uri' => '/api/users', 'status' => 201, ]);
Logged Performance Metrics:
{
"message": "Performance: database-query",
"context": {
"operation": "database-query",
"duration_ms": 45.23,
"memory_peak_mb": 12.5,
"query": "SELECT * FROM users"
}
}
Logging Middleware
PSR-15 middleware for automatic request logging:
use MethorZ\RequestLogger\Middleware\LoggingMiddleware; use MethorZ\RequestLogger\Processor\RequestIdProcessor; // Basic usage $middleware = new LoggingMiddleware($logger); // Custom request ID processor $processor = new RequestIdProcessor('custom-id'); $middleware = new LoggingMiddleware($logger, $processor); // Disable X-Request-ID header $middleware = new LoggingMiddleware($logger, null, false);
What It Logs:
Request start:
{
"message": "Request started",
"context": {
"method": "POST",
"uri": "https://example.com/api/users",
"request_id": "req_673e5c2f47a0c1.23456789"
}
}
Request completion:
{
"message": "Request completed",
"context": {
"method": "POST",
"uri": "https://example.com/api/users",
"status": 201,
"duration_ms": 127.45,
"memory_peak_mb": 15.2,
"request_id": "req_673e5c2f47a0c1.23456789"
}
}
Exception:
{
"message": "Request failed with exception",
"context": {
"method": "POST",
"uri": "https://example.com/api/users",
"exception": "User not found",
"exception_class": "App\\Exception\\NotFoundException",
"request_id": "req_673e5c2f47a0c1.23456789"
}
}
๐ฏ Use Cases
Distributed Tracing
Correlate logs across services using request IDs:
// Service A $requestId = $processor->getRequestId(); $client->request('POST', '/api/service-b', [ 'headers' => ['X-Request-ID' => $requestId], ]); // Service B receives request with same ID // All logs from both services share the request ID
Performance Bottleneck Detection
Track slow operations:
$perfLogger->start('slow-operation'); $result = $this->processData($largeDataset); $perfLogger->end('slow-operation', [ 'records_processed' => count($largeDataset), ], LogLevel::WARNING); // Use WARNING level if it's slow
Production Debugging
Find all logs for a specific request:
# Filter logs by request ID cat app.log | jq 'select(.extra.request_id == "req_673e5c2f47a0c1.23456789")'
๐ง Configuration
Mezzio Configuration
// config/autoload/logging.global.php use MethorZ\RequestLogger\Middleware\LoggingMiddleware; use MethorZ\RequestLogger\Processor\RequestIdProcessor; use Monolog\Handler\StreamHandler; use Monolog\Logger; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; return [ 'dependencies' => [ 'factories' => [ LoggerInterface::class => function (ContainerInterface $container): Logger { $logger = new Logger('app'); $logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO)); return $logger; }, RequestIdProcessor::class => fn() => new RequestIdProcessor(), LoggingMiddleware::class => function (ContainerInterface $container): LoggingMiddleware { return new LoggingMiddleware( $container->get(LoggerInterface::class), $container->get(RequestIdProcessor::class), ); }, ], ], ]; // config/pipeline.php $app->pipe(LoggingMiddleware::class);
๐ Log Structure
All logs follow a consistent structure for easy parsing:
{
"message": "User action",
"context": {
"user_id": 123,
"action": "login"
},
"level": 200,
"level_name": "INFO",
"channel": "app",
"datetime": "2024-11-26T10:30:45.123456+00:00",
"extra": {
"request_id": "req_673e5c2f47a0c1.23456789"
}
}
๐ Monolog Integration
Works seamlessly with Monolog:
use Monolog\Logger; use Monolog\Handler\StreamHandler; use Monolog\Formatter\JsonFormatter; use MethorZ\RequestLogger\Processor\RequestIdProcessor; $logger = new Logger('app'); // JSON formatter for structured logs $handler = new StreamHandler('php://stdout', Logger::INFO); $handler->setFormatter(new JsonFormatter()); $logger->pushHandler($handler); // Add request ID processor $logger->pushProcessor(new RequestIdProcessor());
๐งช Testing
# Run tests composer test # Static analysis composer analyze # Code style composer cs-check composer cs-fix
๐ Related Packages
This package is part of the MethorZ HTTP middleware ecosystem:
| Package | Description |
|---|---|
| methorz/http-dto | Automatic HTTP โ DTO conversion with validation |
| methorz/http-problem-details | RFC 7807 error handling middleware |
| methorz/http-cache-middleware | HTTP caching with ETag support |
| methorz/http-request-logger | Structured logging (this package) |
| methorz/openapi-generator | Automatic OpenAPI spec generation |
These packages work together seamlessly in PSR-15 applications.
๐ License
MIT License. See LICENSE for details.
๐ค Contributing
Contributions welcome! See CONTRIBUTING.md for guidelines.