orqestrahub/scoped-logger

Lightweight scoped logging utilities built on PSR-3.

Maintainers

Package info

github.com/orqestrahub/scoped-logger

pkg:composer/orqestrahub/scoped-logger

Transparency log

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-31 15:27 UTC

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.