Skip to content
CAI
Software that uses CAICheck a score

Seldaek/monolog

75.8

Strong · 25 September 2026

13.9k

lines of production code

PHP

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is Monolog, a PHP logging library that provides structured logging capabilities through a flexible handler, formatter, and processor architecture. It enables developers to capture, enrich, and serialize log records into various formats for diverse infrastructure targets, including cloud services, databases, and messaging platforms. The library supports modern PHP features and integrates with frameworks via attributes, while ensuring type safety and performance through strict typing and lazy evaluation mechanisms.

How it got here

2011 — Monolog 3.0 major release

11 changes.

This period marks the release of Monolog 3.0, a major overhaul requiring PHP 8.1+ and enforcing PSR-3 compliance through a new LogRecord object and Level enum. The architecture was refactored with modern handler hierarchies, new processors for context enrichment, and expanded formatter support for contemporary logging infrastructure. Comprehensive test coverage and strict static analysis were implemented to ensure stability across these breaking changes.

2012–2026 — Handler refactoring and PHP 8 attributes

9 changes.

This period focused on refactoring internal handler logic to improve type safety and maintainability, including the introduction of a dedicated UdpSocket class and the extraction of cURL retry mechanisms. It also introduced PHP 8 attributes for declarative configuration of processors and channels, alongside comprehensive test coverage updates for new and existing components like SlackRecord and MonologTestCase.

Features

New PHP attributes for configuring Monolog processors and channels

Added \AsMonologProcessor\ and \WithMonologChannel\ attributes to allow developers to declaratively configure logging processors and logger channels via PHP 8+ attribute syntax. \AsMonologProcessor\ supports targeting classes, methods, or parameters and allows specifying the channel, handler, method name, and priority for the processor. \WithMonologChannel\ targets classes or constructor/method parameters to indicate the expected logger channel. These attributes are metadata-only and require a third-party consumer (such as a framework bundle) to interpret and apply the configuration; they have no effect when used with the Monolog library alone.

src/Monolog/Attribute · high confidence

New UdpSocket class with configurable datagram length and Unix socket support

The SyslogUdp handler now uses a dedicated UdpSocket class that allows users to configure the maximum UDP datagram length to avoid packet fragmentation and loss, and supports sending logs via Unix sockets in addition to standard IPv4 UDP.

src/Monolog/Handler/SyslogUdp · high confidence

New and updated formatters for modern logging targets

The formatter component now includes dedicated formatters for ChromePHP, Elastica, Elasticsearch, Flowdock, Fluentd, GELF, Google Cloud Logging, HTML, Loggly, Logmatic, Logstash, and MongoDB, alongside updated versions of the Line, JSON, Normalizer, and Redacting formatters. These additions provide native support for serializing log records into formats required by modern infrastructure (such as Elasticsearch and GCP Logging) and tools (like ChromePHP and Fluentd), while the updated formatters introduce features like stack trace inclusion, sensitive data redaction, and improved normalization depth controls.

src/Monolog/Formatter · high confidence

New processors for context enrichment and lazy evaluation

This release adds several new processor classes to the src/Monolog/Processor directory to enrich log records with additional context. The new ClosureContextProcessor allows for lazy evaluation of context data by wrapping it in a closure, which is useful for reducing performance overhead in conditional logging scenarios. New GitProcessor and MercurialProcessor automatically inject repository branch and commit/revision information into log records. System-level context is now available via HostnameProcessor (injects hostname), LoadAverageProcessor (injects system load averages), and ProcessIdProcessor (injects the process ID). Memory monitoring is supported through MemoryProcessor (an abstract base class), MemoryUsageProcessor, and MemoryPeakUsageProcessor. Additionally, IntrospectionProcessor provides file, line, class, and function details from the call stack, while TagProcessor allows attaching custom tags to records. The UidProcessor has been updated to use random\_bytes for better uniqueness and includes a configurable length argument. The PsrLogMessageProcessor now supports removing used context fields after interpolation and handles UnitEnum values.

src/Monolog/Processor · high confidence

Behavioural changes

Activation strategies now use the new Level enum and LogRecord

The FingersCrossed handler's activation strategies (ChannelLevelActivationStrategy and ErrorLevelActivationStrategy) have been refactored to accept and compare against the new Level enum instead of raw integers or strings. This change ensures that level comparisons are type-safe and consistent with the rest of the library, as strategies now operate on LogRecord objects and Level instances, normalizing input via Logger::toMonologLevel.

src/Monolog/Handler/FingersCrossed · high confidence

Curl retry logic extracted to internal Util class

The retry mechanism for cURL requests has been moved into a new internal \Monolog\\Handler\\Curl\\Util\ class. This refactoring isolates the logic that handles transient errors (such as connection timeouts or DNS failures) by automatically retrying failed requests up to five times before throwing a \RuntimeException\. The class is marked as \@internal\ and \final\, meaning it is not part of the public API and may change without notice.

src/Monolog/Handler/Curl · high confidence

Handler architecture refactored for Monolog 2.0

The handler hierarchy has been restructured to support the new LogRecord object and modern PHP features. AbstractHandler now serves as the base class for level and bubbling logic, while AbstractProcessingHandler adds processor and formatter support. This change introduces a new handler structure that requires updating existing handler implementations to extend the new base classes.

src/Monolog/Handler · high confidence

Major architectural overhaul: new LogRecord model, Level enum, and ErrorHandler

Monolog has been refactored to use a new LogRecord class for log entries, replacing the previous array-based structure, and introduces a native Level enum to manage log levels (Debug through Emergency) with RFC 5424 support. The library now includes a dedicated ErrorHandler class to capture and log runtime errors, exceptions, and fatal errors, along with a SignalHandler for POSIX signal logging. Legacy classes like Log and Writer have been removed, and the Logger class now implements ResettableInterface to support resetting handlers and processors between requests or jobs.

src/Monolog · high confidence

Refactored Slack message formatting via new SlackRecord class

The logic for preparing Slack messages has been extracted into a dedicated \SlackRecord\ class, which now handles the construction of Slack attachments, color mapping, and context/extra data inclusion. This change introduces fluent setters for configuration, allows the channel to be optional (supporting webhooks), and ensures that context and extra variables are properly stringified even when nested more than one level deep. Users will see more consistent message formatting in Slack, with improved handling of special characters and attachment structures.

src/Monolog/Handler/Slack · high confidence

Repository initialization with PHP 8.1+ requirements and PSR-3 compliance

The repository has been initialized with a new structure and configuration, establishing Monolog 3.x as the current version. This release requires PHP 8.1 or higher and enforces PSR-3 compliance by converting log records from arrays to a \Monolog\\LogRecord\ object, replacing the previous \Logger::DEBUG\, \Logger::ERROR\, etc. constants with the \Monolog\\Level\ enum, and updating interfaces to accept \LogRecord\ instances. The project now includes a \.editorconfig\ for consistent coding standards, a \.php-cs-fixer.php\ configuration, and a \phpstan.neon.dist\ file with strict type checking (level 8). Documentation has been updated to reflect these changes, including an \UPGRADE.md\ guide for migrating from previous versions, and the \README.md\ has been refreshed to highlight the new requirements and supported frameworks.

(repo-wide) · high confidence

Test coverage

Added e2e test script for FrankenPhpHandler; Added test coverage for Monolog formatters; Added tests for Monolog PHP 8 attributes; Added unit tests for Monolog handler base classes and core handlers; Added unit tests for Monolog processor classes; Added unit tests for SlackRecord; Expanded test coverage for core Monolog components; New MonologTestCase helper class for testing log records; Update test bootstrap for strict types and PSR-4 autoloading.

Dependencies

Monolog 3.0 release with PHP 8.1+ and PSR-3 v3 support

This update introduces Monolog 3.0, which raises the minimum PHP version to 8.1 and updates the PSR-3 logger interface requirement to support versions 2.0 and 3.0. The package now provides psr/log-implementation version 3.0.0. Development dependencies have been updated to include PHPUnit 10/11, PHPStan 2, and various handler libraries like Elasticsearch 7/8, MongoDB 1.8/2.0, and Rollbar 4.0. The autoloading has been switched to PSR-4, and the branch alias is set to 3.x-dev for the main branch.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 52 → 76 (+24.3)
  • Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 97 → 94 (-2.2)
  • Architecture 96 → 98 (+2.9)
  • Maturity 45 → 58 (+12.8)
  • Readiness 30 → 89 (+58.3)
  • Security 97 → 98 (+0.8)

Resolved (11)

  • Context/problem and consequences/trade-offs are absent (only handler/formatter/processor lists appear) (doc/02-handlers-formatters-processors.md)
  • Coverage not measured — test suite did not build
  • Dimension evaluation failed
  • Duplicated block (10 lines × 2) (src/Monolog/Handler/NewRelicHandler.php)
  • Duplicated block (6 lines × 2) (src/Monolog/Formatter/GelfMessageFormatter.php)
  • Duplicated block (6 lines × 2) (src/Monolog/Formatter/LineFormatter.php)
  • LLM evaluation failed
  • No context/problem (why these utilities matter) and no explicit decision; only a list of classes is present (doc/03-utilities.md)
  • No exposed public API
  • No tests found
  • Test reliability not included

New (128)

  • Change coupling: FilterHandler.php ↔ SamplingHandler.php (src/Monolog/Handler/FilterHandler.php)
  • Change coupling: FingersCrossedHandler.php ↔ SamplingHandler.php (src/Monolog/Handler/FingersCrossedHandler.php)
  • DeduplicationHandler.flush (cognitive 17) (src/Monolog/Handler/DeduplicationHandler.php)
  • Dependency hygiene PARTLY measured — Composer dependencies read, no committed lock to grade for currency
  • Documentation: no installation or build instructions (README.md)
  • Duplicate intent with confusing naming. ElasticaHandler and ElasticsearchHandler appear to serve the same purpose (logging to Elasticsearch) but use different client types and class names. The constructor signature for ElasticsearchHandler shows Client|Client which is likely a typo for Client|ElasticsearchClient, but the existence of two separate handlers for the same backend with different constructor signatures (one taking an Elastica client, one taking an Elasticsearch client) creates confusion.
  • Duplicated block (10 lines × 2) (src/Monolog/Handler/NewRelicHandler.php)
  • Duplicated block (10 lines × 5) (src/Monolog/Formatter/ChromePHPFormatter.php)
  • Duplicated block (11 lines × 2) (src/Monolog/Handler/FallbackGroupHandler.php)
  • Duplicated block (16 lines × 2) (src/Monolog/Handler/InsightOpsHandler.php)
  • Duplicated block (22 lines × 2) (src/Monolog/Formatter/JsonFormatter.php)
  • Duplicated block (5 lines × 2) (src/Monolog/Handler/BufferHandler.php)
  • Duplicated block (6 lines × 2) (src/Monolog/Formatter/LineFormatter.php)
  • Duplicated block (6 lines × 4) (src/Monolog/Handler/FilterHandler.php)
  • Duplicated block (7 lines × 2) (src/Monolog/Handler/BufferHandler.php)
  • Duplicated block (7 lines × 2) (src/Monolog/Handler/PushoverHandler.php)
  • Duplicated block (7 lines × 2) (src/Monolog/Processor/GitProcessor.php)
  • Duplicated block (8 lines × 4) (src/Monolog/Handler/FilterHandler.php)
  • Duplicated block (9 lines × 2) (src/Monolog/Processor/MemoryPeakUsageProcessor.php)
  • Duplicated block (9 lines × 4) (src/Monolog/Handler/FilterHandler.php)
  • …and 108 more

Changes since last survey

  • 32 commits — 22 feature/other, 10 fixes

By area

  • src/Monolog — 10 commits
  • .github/workflows — 9 commits
  • (root) — 7 commits
  • tests/Monolog — 3 commits
  • doc/01-usage.md — 1 commit
  • doc/02-handlers-formatters-processors.md — 1 commit
  • doc/03-utilities.md — 1 commit

Notable commits

  • fix: Fix CI
  • fix: Fix RedactingFormatter missing secrets nested in array-valued sensitive keys (#2067)
  • fix: Fix TelegramBotHandler breaking HTML tags when truncating or splitting long messages (#1990) (#2066)
  • fix: Fix baseline
  • fix: Fix baseline
  • fix: Fix couchdb install warning
  • fix: Fix mongodb version in phpstan build as well
  • fix: Fix potential XSS in BrowserConsoleHandler when logging user content
  • fix: Fix warning when setting the http response code in case a status has already been registered
  • fix: fix(SyslogUdp): allow configuring the max UDP datagram length (#2049)
  • change: Add FrankenPhpHandler (#2056)
  • change: Add LogMonsterHandler that requires at least some amount of logging or it logs an error that the code is not logging enough (#2039)
  • change: Add RedactingFormatter to automatically redact keys/sensitive data before logging records (#2041)
  • change: Add a way to turn on stack traces for ErrorHandler-generated records (#2060)
  • change: Add more mongodb version pins
  • change: Align FrankenPhpHandler's level scale with OpenTelemetry's mapping (#2062)
  • change: Allow WithMonologChannel to target a constructor/method parameter (#2068)
  • change: Allow reading the timestamp of log records from a PSR-20 clock (#2065)
  • change: Bump actions/checkout from 7.0.0 to 7.0.1 (#2051)
  • change: Bump zizmorcore/zizmor-action from 0.5.7 to 0.6.1 (#2052)
  • …and 12 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

Seldaek/monolog was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 25 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 783156abfbecb292a19ef737361e1bbb7f963df6 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-9630dbd8b4f7.