PHPackages                             philiprehberger/php-structured-logger - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. philiprehberger/php-structured-logger

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

philiprehberger/php-structured-logger
=====================================

PSR-3 compatible logger that outputs structured JSON log lines

v1.3.0(2mo ago)138MITPHPPHP ^8.2CI passing

Since Mar 13Pushed 1mo agoCompare

[ Source](https://github.com/philiprehberger/php-structured-logger)[ Packagist](https://packagist.org/packages/philiprehberger/php-structured-logger)[ Docs](https://github.com/philiprehberger/php-structured-logger)[ GitHub Sponsors](https://github.com/philiprehberger)[ RSS](/packages/philiprehberger-php-structured-logger/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (8)Versions (6)Used By (0)

PHP Structured Logger
=====================

[](#php-structured-logger)

[![Tests](https://github.com/philiprehberger/php-structured-logger/actions/workflows/tests.yml/badge.svg)](https://github.com/philiprehberger/php-structured-logger/actions/workflows/tests.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/4b5c0b749921755f1790a06d6b0cd2ae6b0eb255b90109e1ab4aa142ae275e61/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068696c69707265686265726765722f7068702d737472756374757265642d6c6f676765722e737667)](https://packagist.org/packages/philiprehberger/php-structured-logger)[![Last updated](https://camo.githubusercontent.com/f6241b1ab23908eced68287a08578bae3fd3fd18250197981d942ac002443ac9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f7068696c69707265686265726765722f7068702d737472756374757265642d6c6f67676572)](https://github.com/philiprehberger/php-structured-logger/commits/main)

PSR-3 compatible logger that outputs structured JSON log lines.

Requirements
------------

[](#requirements)

- PHP 8.2+
- psr/log ^3.0

Installation
------------

[](#installation)

```
composer require philiprehberger/php-structured-logger
```

Usage
-----

[](#usage)

### Basic logging

[](#basic-logging)

```
use PhilipRehberger\StructuredLogger\JsonLogger;

// Log to stdout (default)
$logger = new JsonLogger();
$logger->info('Application started');

// Log to a file
$logger = new JsonLogger(output: '/var/log/app.log');
$logger->info('User logged in', ['user_id' => 42]);
```

### Logging with context

[](#logging-with-context)

```
$logger = new JsonLogger(output: 'php://stderr');

$logger->error('Payment failed', [
    'order_id' => 'ORD-123',
    'amount' => 49.99,
    'currency' => 'USD',
]);
```

Output:

```
{"timestamp":"2026-03-13T10:00:00+00:00","level":"error","message":"Payment failed","channel":"app","context":{"order_id":"ORD-123","amount":49.99,"currency":"USD"}}
```

### Sensitive data redaction

[](#sensitive-data-redaction)

By default, the following context keys are automatically redacted: `password`, `token`, `secret`, `api_key`, `authorization`, `credit_card`. Redaction applies recursively to nested arrays.

```
$logger = new JsonLogger();

$logger->info('Auth attempt', [
    'username' => 'alice',
    'password' => 's3cret',
    'token' => 'abc123',
]);
// password and token values replaced with "[REDACTED]"
```

You can provide a custom list of keys to redact:

```
$logger = new JsonLogger(
    redactKeys: ['password', 'ssn', 'credit_card'],
);
```

### Persistent context

[](#persistent-context)

Use `withContext()` to create a new logger instance with fields that are automatically included in every log entry:

```
$logger = new JsonLogger(output: '/var/log/app.log');

$requestLogger = $logger->withContext([
    'request_id' => 'req-abc-123',
    'service' => 'api',
]);

$requestLogger->info('Request received');
$requestLogger->info('Processing complete', ['duration_ms' => 42]);
// Both entries include request_id and service in context
```

### Minimum log level

[](#minimum-log-level)

Use `setMinLevel()` to filter out log entries below a severity threshold:

```
use Psr\Log\LogLevel;

$logger = new JsonLogger();
$logger->setMinLevel(LogLevel::WARNING);

$logger->debug('This is skipped');
$logger->info('This is also skipped');
$logger->warning('This is logged');
$logger->error('This is logged');
```

### Custom channel

[](#custom-channel)

Use the channel parameter to identify different services or application components:

```
$logger = new JsonLogger(
    output: '/var/log/payments.log',
    channel: 'payments',
);

$logger->info('Payment processed');
// {"timestamp":"...","level":"info","message":"Payment processed","channel":"payments"}
```

### Log sampling

[](#log-sampling)

Use `withSampling()` to probabilistically sample log output. Messages at `error` level and above are always logged regardless of the sampling rate:

```
$logger = new JsonLogger();
$logger->withSampling(0.1); // Only 10% of debug/info/warning/notice messages are written

$logger->info('Might be skipped');
$logger->error('Always logged');
```

### Buffered logging

[](#buffered-logging)

Use `BufferedLogger` to batch log entries and flush them together:

```
use PhilipRehberger\StructuredLogger\BufferedLogger;
use PhilipRehberger\StructuredLogger\JsonLogger;

$logger = new BufferedLogger(new JsonLogger(), bufferSize: 50);

$logger->info('Buffered entry 1');
$logger->info('Buffered entry 2');
$logger->flush(); // Writes all buffered entries
```

### Correlation ID

[](#correlation-id)

Use `withCorrelationId()` to automatically include a correlation ID in every log entry:

```
$logger = new JsonLogger();
$logger->withCorrelationId('req-abc-123');

$logger->info('Processing request');
// context includes "correlation_id": "req-abc-123"
```

### Multiple output targets

[](#multiple-output-targets)

Use `MultiLogger` to fan out log calls to multiple logger instances:

```
use PhilipRehberger\StructuredLogger\MultiLogger;
use PhilipRehberger\StructuredLogger\JsonLogger;
use PhilipRehberger\StructuredLogger\EcsLogger;

$jsonLogger = new JsonLogger(output: '/var/log/app.log');
$ecsLogger = new EcsLogger(output: '/var/log/app-ecs.log');

$multi = new MultiLogger([$jsonLogger, $ecsLogger]);
$multi->info('Logged to both targets', ['user_id' => 42]);
```

Each logger in the array respects its own minimum level and configuration independently.

### ECS (Elastic Common Schema) format

[](#ecs-elastic-common-schema-format)

Use `EcsLogger` to output logs in [Elastic Common Schema](https://www.elastic.co/guide/en/ecs/current/index.html) format:

```
use PhilipRehberger\StructuredLogger\EcsLogger;

$logger = new EcsLogger(output: '/var/log/app-ecs.log', channel: 'api');
$logger->info('Request processed', ['http.method' => 'GET', 'url.path' => '/users']);
```

Output:

```
{"@timestamp":"2026-04-01T10:00:00+00:00","log.level":"info","message":"Request processed","ecs.version":"8.11","service.name":"api","http.method":"GET","url.path":"/users"}
```

### Structured exception formatting

[](#structured-exception-formatting)

When an `exception` key containing a `Throwable` is passed in context, both `JsonLogger` and `EcsLogger` automatically serialize it into structured fields:

```
try {
    riskyOperation();
} catch (\Throwable $e) {
    $logger->error('Operation failed', ['exception' => $e]);
}
```

The exception is serialized into `error.type`, `error.message`, `error.code`, and `error.stack_trace` fields. You can also use `ExceptionSerializer` directly:

```
use PhilipRehberger\StructuredLogger\ExceptionSerializer;

$data = ExceptionSerializer::serialize($exception, traceDepth: 5);
// ['error.type' => 'RuntimeException', 'error.message' => '...', 'error.code' => 0, 'error.stack_trace' => [...]]
```

### Output Format

[](#output-format)

Each log line is a single JSON object with the following fields:

FieldTypeDescription`timestamp`stringISO 8601 timestamp`level`stringPSR-3 log level`message`stringLog message`channel`stringApplication/service name (default: `app`)`context`objectAdditional data (omitted when empty)API
---

[](#api)

### `JsonLogger`

[](#jsonlogger)

ParameterTypeDefaultDescription`output``string``'php://stdout'`File path or PHP stream wrapper`channel``string``'app'`Application/service identifier`redactKeys``string[]``['password', 'token', 'secret', 'api_key', 'authorization', 'credit_card']`Context keys to redactMethodReturnsDescription`withContext(array $context)``self`New logger instance with persistent context fields`setMinLevel(string $level)``void`Set minimum log level threshold`withSampling(float $rate)``self`Enable probabilistic log sampling (0.0-1.0)`withCorrelationId(string $id)``self`Set correlation ID for all log entriesAll PSR-3 log methods are available: `emergency()`, `alert()`, `critical()`, `error()`, `warning()`, `notice()`, `info()`, `debug()`, `log()`.

### `BufferedLogger`

[](#bufferedlogger)

ParameterTypeDefaultDescription`logger``JsonLogger`Wrapped logger to flush entries to`bufferSize``int``100`Flush when buffer reaches this sizeMethodReturnsDescription`flush()``void`Write all buffered entries to the wrapped logger`count()``int`Number of entries currently buffered### `MultiLogger`

[](#multilogger)

ParameterTypeDefaultDescription`loggers``LoggerInterface[]``[]`Logger instances to fan out calls toAll PSR-3 log methods are available. Each call is forwarded to every logger in the array.

### `EcsLogger`

[](#ecslogger)

ParameterTypeDefaultDescription`output``string``'php://stdout'`File path or PHP stream wrapper`channel``string``'app'`Service name (`service.name`)MethodReturnsDescription`setMinLevel(string $level)``void`Set minimum log level thresholdAll PSR-3 log methods are available. Output follows the Elastic Common Schema (ECS 8.11) format.

### `ExceptionSerializer`

[](#exceptionserializer)

MethodReturnsDescription`serialize(Throwable $exception, int $traceDepth = 10)``array`Serialize exception into structured fieldsReturns an array with keys: `error.type`, `error.message`, `error.code`, `error.stack_trace`.

### `LogEntry`

[](#logentry)

Immutable value object representing a single log entry. Implements `JsonSerializable`.

MethodReturnsDescription`toArray()``array`Entry as associative array`toJson()``string`Entry as JSON string`jsonSerialize()``array`For `json_encode()` supportDevelopment
-----------

[](#development)

```
composer install
vendor/bin/phpunit
vendor/bin/pint --test
```

Support
-------

[](#support)

If you find this project useful:

⭐ [Star the repo](https://github.com/philiprehberger/php-structured-logger)

🐛 [Report issues](https://github.com/philiprehberger/php-structured-logger/issues?q=is%3Aissue+is%3Aopen+label%3Abug)

💡 [Suggest features](https://github.com/philiprehberger/php-structured-logger/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)

❤️ [Sponsor development](https://github.com/sponsors/philiprehberger)

🌐 [All Open Source Projects](https://philiprehberger.com/open-source-packages)

💻 [GitHub Profile](https://github.com/philiprehberger)

🔗 [LinkedIn Profile](https://www.linkedin.com/in/philiprehberger)

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance88

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 94.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~5 days

Total

5

Last Release

84d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfd7d24cbbf32400fa13ce0bbe7a31edd2d66a6d4488eafdb3d64c5337bf0435?d=identicon)[philiprehberger](/maintainers/philiprehberger)

---

Top Contributors

[![philiprehberger](https://avatars.githubusercontent.com/u/8218077?v=4)](https://github.com/philiprehberger "philiprehberger (18 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

logpsr-3jsonloggerstructured

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/philiprehberger-php-structured-logger/health.svg)

```
[![Health](https://phpackages.com/badges/philiprehberger-php-structured-logger/health.svg)](https://phpackages.com/packages/philiprehberger-php-structured-logger)
```

###  Alternatives

[analog/analog

Fast, flexible, easy PSR-3-compatible PHP logging package with dozens of handlers.

3511.6M24](/packages/analog-analog)[inpsyde/wonolog

Monolog-based logging package for WordPress.

184631.3k7](/packages/inpsyde-wonolog)[apix/log

Minimalist, thin and fast PSR-3 compliant (multi-bucket) logger.

511.1M20](/packages/apix-log)[markrogoyski/simplelog-php

Powerful PSR-3 logging. So easy, it's simple.

2819.1k4](/packages/markrogoyski-simplelog-php)[wa72/simplelogger

Wa72SimpleLogger is a collection of very simple loggers implementing \\Psr\\Log\\LoggerInterface (PSR-3)

13253.9k14](/packages/wa72-simplelogger)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
