Advanced: Logging¶
Erlenmeyer includes a flexible logging system designed for both file-based and console-based environments.
It provides standardized severity levels and supports context-aware exception logging, including request details and stack traces.
Overview¶
Logging in Erlenmeyer is powered by the LoggerInterface, which defines two main methods:
public function log(LogLevel $level, string $message): void;
public function logException(Exception $e, ?Request $request = null): void;
Two implementations are included by default:
| Class | Description |
|---|---|
FileLogger |
Writes structured log entries to disk, with automatic rotation. |
ConsoleLogger |
Writes log entries to the PHP error log or STDERR (useful in CLI/testing). |
You can also create custom loggers by implementing LoggerInterface — covered in the Custom Handlers section.
Log Levels¶
Erlenmeyer defines standard log severity levels using the LogLevel enum:
enum LogLevel: string {
case DEBUG = 'DEBUG';
case INFO = 'INFO';
case WARNING = 'WARNING';
case ERROR = 'ERROR';
case CRITICAL = 'CRITICAL';
}
All loggers support these levels consistently.
1. FileLogger¶
Basic Setup¶
The FileLogger stores logs in a directory of your choice and automatically rotates log files when they reach 3MB.
use AdaiasMagdiel\Erlenmeyer\Logging\FileLogger;
use AdaiasMagdiel\Erlenmeyer\App;
$logger = new FileLogger(__DIR__ . '/logs');
$app = new App(null, $logger);
- Logs are stored in
info.loginside the specified directory. - When
info.logexceeds 3MB, it is renamed toinfo.log.1, and older logs are shifted up toinfo.log.5.
Example Log Entry¶
[2025-10-15 14:03:21] [INFO] Route registered: GET /users
Exception Logging¶
Exceptions are logged with full context, including the request method, URI, and stack trace:
[2025-10-15 14:05:11] [ERROR] Invalid argument in /app/UserController.php:84
Request: POST /users
#0 /app/App.php(210): ...
2. ConsoleLogger¶
The ConsoleLogger writes directly to PHP’s error log or STDERR.
This is ideal for development, testing, or containerized deployments.
use AdaiasMagdiel\Erlenmeyer\Logging\ConsoleLogger;
$logger = new ConsoleLogger();
$app = new App(null, $logger);
You can also exclude specific levels to reduce verbosity:
use AdaiasMagdiel\Erlenmeyer\Logging\LogLevel;
$logger = new ConsoleLogger([LogLevel::DEBUG, LogLevel::INFO]);
Now only warnings, errors, and critical messages will appear in your logs.
3. Custom Logger Injection¶
Any logger implementing LoggerInterface can be injected into the application.
use AdaiasMagdiel\Erlenmeyer\App;
use MyApp\CustomLogger;
$logger = new CustomLogger();
$app = new App(null, $logger);
The logger is used internally by the App to record:
- Route registration and middleware execution
- 404 and 500 errors
- Unhandled exceptions
- Asset serving and redirect handling
4. Handling Exceptions Manually¶
You can also log exceptions directly in your route handlers or middlewares:
use AdaiasMagdiel\Erlenmeyer\Logging\LogLevel;
$app->get('/users', function ($req, $res) use ($app) {
try {
// ...
} catch (Exception $e) {
$appLogger = new FileLogger(__DIR__ . '/logs');
$appLogger->logException($e, $req);
$res->setStatusCode(500)->withText('An internal error occurred');
}
});
5. When Logging is Disabled¶
If you initialize FileLogger without a directory path:
$logger = new FileLogger('');
Logging is silently disabled — no files are created, and all log calls become no-ops.
This can be useful for production builds where logs are handled by external systems.
Summary¶
| Logger | Output | Rotation | Contextual Exceptions | Recommended For |
|---|---|---|---|---|
| FileLogger | Files (info.log) |
✅ Yes | ✅ Yes | Production |
| ConsoleLogger | error_log() / STDERR |
❌ No | ✅ Yes | Development / CI |
| Custom Logger | User-defined | Optional | Optional | Advanced setups |
Next: 📘 Custom Handlers →