Logging
Logging channels, PSR logger bindings, log file path convention and practical usage patterns.
Provider wiring
LoggingServiceProvider registers LogFilePathResolver, LogManager, alias log, alias log.app, alias log.benchmark and maps Psr\Log\LoggerInterface to log.app. The provider also sets the container diagnostic logger to the app logger channel.
$container->singleton(LogFilePathResolver::class, LogFilePathResolver::class);
$container->singleton(LogManager::class, LogManager::class);
$container->singleton('log', LogManager::class);
$container->singleton('log.app', static function (ContainerInterface $container): LoggerInterface {
$manager = $container->get(LogManager::class);
$logger = $manager->app();
$container->setDiagnosticLogger($logger);
return $logger;
});
$container->singleton('log.benchmark', static fn (ContainerInterface $container): LoggerInterface => $container->get(LogManager::class)->benchmark());
$container->singleton(LoggerInterface::class, static fn (ContainerInterface $container): LoggerInterface => $container->get('log.app'));
Configuration
Logging channels are configured via merged application config (typically app/Config/Logging.php) with keys like app.log.*, error.log.*, request.log.* and benchmark.log.*. Channel methods on LogManager are app(), error(), request() and benchmark().
APP_LOG_FILE=app.log
ERROR_LOG_FILE=error.log
REQUEST_LOG_FILE=request.log
BENCHMARK_LOG_FILE=benchmark.log
Log file path convention
Log filenames are resolved through LogFilePathResolver. Relative filenames such as app.log are stored under storage/writable/logs. Absolute paths are preserved.
Framework internal logging
Kernel and CLI failures are logged via ExceptionLogger. Container diagnostics also use the logger configured by LoggingServiceProvider through the container diagnostic logger binding.
Channel behavior
Disabled channels resolve to Psr\Log\NullLogger, so application code can log safely without per-call channel availability checks.
Usage through dependency injection
Prefer constructor injection of Psr\Log\LoggerInterface for application services. Use LogManager only when explicit channel selection is required.
final class ImportService
{
public function __construct(
private readonly LoggerInterface $logger,
) {
}
public function run(): void
{
$this->logger->info('Import started');
}
}