orqestrahub / scoped-logger
Lightweight scoped logging utilities built on PSR-3.
Requires
- php: ^8.3
- psr/log: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- phpunit/phpunit: ^11.0
- roave/security-advisories: dev-latest
This package is auto-updated.
Last update: 2026-08-31 15:29:11 UTC
README
Lightweight scoped logging utilities built on top of PSR-3.
The package provides a small wrapper around any Psr\Log\LoggerInterface implementation and allows log messages to be enriched with a reusable prefix and dynamically managed scopes.
It is framework-agnostic and can be used with Laravel, Symfony, Monolog, or any other PSR-3 compatible logger.
Requirements
- PHP 8.3+
- PSR-3 compatible logger
Installation
Install the package using Composer:
composer require orqestrahub/scoped-logger
Basic Usage
Create a ScopedLogger by wrapping any PSR-3 logger.
<?php use OrqestraHub\ScopedLogger\ScopedLogger; use Psr\Log\LoggerInterface; /** @var LoggerInterface $logger */ $scopedLogger = new ScopedLogger( logger: $logger, prefix: '<USERS>', ); $scopedLogger->info('User profile loaded.');
The resulting log message will include the configured prefix:
<USERS>: User profile loaded.
Scopes
Scopes can be added dynamically to provide additional context.
$scopedLogger ->appendScope('user-id=55') ->appendScope('session=abc123'); $scopedLogger->info('User profile loaded.');
Example output:
<USERS> user-id=55 session=abc123: User profile loaded.
Scopes can also be prepended:
$scopedLogger->prependScope('tenant=main');
Result:
<USERS> tenant=main user-id=55 session=abc123: User profile loaded.
Removing Scopes
A scope can be removed by its exact value:
$scopedLogger->removeScope('session=abc123');
All scopes can be cleared:
$scopedLogger->clearScope();
Changing the Prefix
The logger prefix can be changed at runtime:
$scopedLogger->setPrefix('<USER-SERVICE>');
The current prefix can be retrieved with:
$prefix = $scopedLogger->getPrefix();
Message Delimiter
The default delimiter between the prefix and the message is :.
It can be changed:
$scopedLogger->setMessageDelimiter(' ->');
For example:
<USERS> user-id=55 -> User profile loaded.
PSR-3 Compatibility
ScopedLogger implements Psr\Log\LoggerInterface, so it can be used anywhere a PSR-3 logger is expected.
<?php use Psr\Log\LoggerInterface; function loadUser(LoggerInterface $logger): void { $logger->info('Loading user.'); } loadUser($scopedLogger);
All standard PSR-3 logging levels are supported:
$scopedLogger->emergency('...'); $scopedLogger->alert('...'); $scopedLogger->critical('...'); $scopedLogger->error('...'); $scopedLogger->warning('...'); $scopedLogger->notice('...'); $scopedLogger->info('...'); $scopedLogger->debug('...');
The generic log() method is also supported:
$scopedLogger->log('info', 'User profile loaded.');
Accessing the Logger
ScopedLogger itself implements LoggerInterface.
Calling getLogger() returns the scoped logger instance as a PSR-3 logger:
$logger = $scopedLogger->getLogger(); $logger->info('This message still includes the configured scopes.');
This makes it possible to expose the logger through a generic LoggerInterface contract without losing scoped logging behavior.
Replacing the Underlying Logger
The wrapped PSR-3 logger can be replaced at runtime:
$scopedLogger->setLogger($anotherLogger);
Existing scopes and the configured prefix remain attached to the ScopedLogger.
Modifying the Underlying Logger
The underlying logger can also be modified through a callback:
$scopedLogger->modifyLogger(function (LoggerInterface $logger): void { // Configure or modify the wrapped logger. });
This can be useful when the concrete logger implementation provides additional configuration APIs.
HasScopedLogger
The package provides a reusable trait for classes that need to hold a scoped logger.
<?php use OrqestraHub\ScopedLogger\Concerns\HasScopedLogger; final class UserService { use HasScopedLogger; public function loadUser(): void { $this->getScopedLogger() ->appendScope('action=load-user') ->info('Loading user profile.'); } }
The logger can be injected through the trait:
$service->setScopedLogger($scopedLogger);
This is useful for reusable services, jobs, workers, or other application components that need contextual logging without depending on a specific logging implementation.
Example
A service can maintain a base logging context and temporarily add more specific scopes during execution.
<?php use OrqestraHub\ScopedLogger\ScopedLogger; $logger = new ScopedLogger( logger: $baseLogger, prefix: '<USER-SERVICE>', ); $logger->appendScope('user-id=55'); $logger->info('Processing started.'); $logger->appendScope('action=profile-update'); $logger->info('Updating user profile.'); $logger->removeScope('action=profile-update'); $logger->info('Processing completed.');
Example output:
<USER-SERVICE> user-id=55: Processing started.
<USER-SERVICE> user-id=55 action=profile-update: Updating user profile.
<USER-SERVICE> user-id=55: Processing completed.
Stability
This package is used in production applications.
Automated tests have not yet been extracted into the standalone package repository. The code has been exercised and tested as part of production systems prior to its extraction into this package.
Standalone test coverage will be added incrementally.
License
This package is open-sourced software licensed under the MIT License.