File: README.md
Monolog - Logging for PHP [](https://github.com/Seldaek/monolog/actions)
Note This is the documentation for Monolog 3.x, if you are using older releases
see the documentation for Monolog 2.x or Monolog 1.x
Monolog sends your logs to files, sockets, inboxes, databases and various
web services. See the complete list of handlers below. Special handlers
allow you to build advanced logging strategies.
This library implements the PSR-3
interface that you can type-hint against in your own libraries to keep
a maximum of interoperability. You can also use it in your applications to
make sure you can always use another compatible logger at a later time.
As of 1.11.0 Monolog public APIs will also accept PSR-3 log levels.
Internally Monolog still uses its own level scheme since it predates PSR-3.
Better Stack lets you centralize, search, and visualize your logs.Installation
Install the latest version with
composer require monolog/monologBasic Usage
<?php
use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Level::Warning));
// add records to the log
$log->warning('Foo');
$log->error('Bar');Documentation
- Usage Instructions
- Handlers, Formatters and Processors
- Utility Classes
- Extending Monolog
- Log Record Structure
Support Monolog Financially
Get supported Monolog and help fund the project with the Tidelift Subscription or via GitHub sponsorship.
Tidelift delivers commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
Third Party Packages
Third party handlers, formatters and processors are
listed in the wiki. You
can also add your own there if you publish one.
About
Requirements
- Monolog
^3.0works with PHP 8.1 or above. - Monolog
^2.5works with PHP 7.2 or above. - Monolog
^1.25works with PHP 5.3 up to 8.1, but is not very maintained anymore and will not receive PHP support fixes anymore.
Support
Monolog 1.x support is somewhat limited at this point and only important fixes will be done. You should migrate to Monolog 2 or 3 where possible to benefit from all the latest features and fixes.
Submitting bugs and feature requests
Bugs and feature request are tracked on GitHub
Framework Integrations
- Frameworks and libraries using PSR-3
can be used very easily with Monolog since it implements the interface. - Symfony comes out of the box with Monolog.
- Laravel comes out of the box with Monolog.
- Lumen comes out of the box with Monolog.
- PPI comes out of the box with Monolog.
- CakePHP is usable with Monolog via the cakephp-monolog plugin.
- XOOPS 2.6 comes out of the box with Monolog.
- Aura.Web_Project comes out of the box with Monolog.
- Nette Framework is usable with Monolog via the contributte/monolog or orisai/nette-monolog extensions.
- Proton Micro Framework comes out of the box with Monolog.
- FuelPHP comes out of the box with Monolog.
- Equip Framework comes out of the box with Monolog.
- Yii 2 is usable with Monolog via the yii2-monolog or yii2-psr-log-target plugins.
- Hawkbit Micro Framework comes out of the box with Monolog.
- SilverStripe 4 comes out of the box with Monolog.
- Drupal is usable with Monolog via the monolog module.
- Aimeos ecommerce framework is usable with Monolog via the ai-monolog extension.
- Magento comes out of the box with Monolog.
- Spiral Framework comes out of the box with Monolog bridge.
- WebFramework comes out of the box with Monolog.
Author
Jordi Boggiano - [email protected] - http://twitter.com/seldaek
See also the list of contributors who participated in this project.
License
Monolog is licensed under the MIT License - see the LICENSE file for details
Acknowledgements
This library is heavily inspired by Python's Logbook
library, although most concepts have been adjusted to fit to the PHP world.
File: _config.yml
theme: jekyll-theme-slate
File: CHANGELOG.md
3.12.1 (2026-09-29)
- Fixed
Loggersilently dropping every record for the rest of the process once the infinite loop guard aborted a nested logging cycle, which could hit long-running workers (#2072) - Fixed
RedactingFormatterletting secrets containing&,<or>through when wrapping anHtmlFormatter(#2069) - Fixed
SocketHandlerthrowing the writing timeout immediately when the first write made no progress, instead of waiting for the configured timeout (#2071) - Fixed
RotatingFileHandlercomputing the first rotation in the default timezone instead of the$timezonepassed to the constructor (#2070)
3.12.0 (2026-09-09)
- Added support for reading the timestamp of new records from a PSR-20 clock, via a new
$clockconstructor param andLogger::setClock()(#2065) - Added support for
#[WithMonologChannel]on constructor/method parameters, so a channel can be bound to a single argument instead of the whole class (#2068) - Fixed
TelegramBotHandlerbreaking HTML markup when truncating or splitting long messages, open tags are now closed at the end of a chunk and reopened in the next one (#2066) - Fixed
RedactingFormatternot redacting secrets nested inside array values of sensitive keys (#2067)
3.11.0 (2026-09-02)
- Security: Fixed potential XSS in
BrowserConsoleHandlerwhen logging user provided content - Added
RedactingFormatterto automatically redact sensitive data from records, based on key names,#[SensitiveParameter]constructor params and/or regex patterns (#2041) - Added
FrankenPhpHandlerto log records via FrankenPHP's frankenphp_log() function (#2056) - Added
LogMonsterHandlerwhich complains if the code did not log enough records before the process/request ends, like a dead man's switch for logs (#2039) - Added
FILE_PER_HOURrotation mode toRotatingFileHandler(#2040) - Added
ErrorHandler::captureStackTraces()to attach the stack trace of PHP errors to the records it generates (#2060) - Added
NormalizerFormatter::setMaxTraceLength()to limit how many stack trace frames are included when normalizing exceptions (#2015) - Added extension points to
TelegramBotHandlerto change the API URL (e.g. for a self-hosted Bot API server) and to send extra curl headers (#2029) - Added ability to override
IntrospectionProcessor'sSKIP_FUNCTIONSin subclasses (#2050) - Added
$maxLengthparam toSyslogUdpHandler/UdpSocketto keep datagrams below the path MTU, as fragmented UDP packets are often dropped (#2049) - Fixed
StreamHandlertruncating writes on non-blocking streams, it now loops until the whole record is written (#2016) - Fixed stack trace frames without file/line being skipped, they are now reported as
internal[function]entries so traces are not truncated or empty (#2061) - Fixed
RotatingFileHandlercleanup not finding files behind stream wrappers (e.g. private://) as glob() cannot see through those (#2058) - Fixed
RotatingFileHandlernot using the configured timezone when computing the next rotation time (#2022) - Fixed scalars being replaced by the "Over N levels deep" message instead of being output when the max normalization depth is reached (#2042)
- Fixed
DeduplicationHandlerfailing with an undefined array key error when the store file is written to concurrently (#2020) - Fixed
TelegramBotHandlerswallowing errors when the API returns a non-JSON response (#2030) - Fixed
AbstractProcessingHandler::handle()reading$bubbledirectly instead of callinggetBubble(), so overrides of it were ignored (#2031) - Fixed warning on PHP 8.5 when
ErrorHandlersets the HTTP response code and a status line was already registered (#2027)
3.10.0 (2026-01-02)
- Added automatic directory cleanup in RotatingFileHandler (#2000)
- Added timezone-aware file rotation to RotatingFileHandler (#1982)
- Added support for mongodb/mongodb 2.0+ (#1998)
- Added NoDiscard attribute to TestHandler methods to ensure the result is used (#2013)
- Fixed JsonFormatter crashing if __toString throws while normalizing data (#1968)
- Fixed PHP 8.5 deprecation warnings (#1997, #2009)
- Fixed DeduplicatingHandler collecting duplicate logs if the file cannot be locked (2e97231)
- Fixed GelfMessageFormatter to use integers instead of bool for gelf 1.1 support (#1973)
- Fixed empty stack traces being output anyway (#1979)
- Fixed StreamHandler not reopening the file if the inode changed (#1963)
- Fixed TelegramBotHandler sending empty messages (#1992)
- Fixed file paths in stack traces containing backslashes on windows, always using / now to unify logs (#1980)
- Fixed RotatingFileHandler unlink errors not being suppressed correctly (#1999)
3.9.0 (2025-03-24)
- BC Warning: Fixed SendGridHandler to use the V3 API as V2 is now shut down, but this requires a new API key (#1952)
- Deprecated Monolog\Test\TestCase in favor of Monolog\Test\MonologTestCase (#1953)
- Added extension point for NativeMailerHandler::mail (#1948)
- Added setHandler method to BufferHandler to modify the nested handler at runtime (#1946)
- Fixed date format in ElasticsearchFormatter to use +00:00 vs +0000 tz identifiers (#1942)
- Fixed GelfMessageFormatter handling numeric context/extra keys (#1932)
3.8.1 (2024-12-05)
- Deprecated Monolog\DateTimeImmutable in favor of Monolog\JsonSerializableDateTimeImmutable (#1928)
- Fixed gelf keys not being valid when context/extra data keys have spaces in them (#1927)
- Fixed empty lines appearing in the stack traces when a custom formatter returned null (#1925)
3.8.0 (2024-11-12)
- Added
$fileOpenModeparam toStreamHandlerto define a custom fopen mode to open the log file (#1913) - Fixed PHP 8.4 deprecation notices (#1903)
- Added ability to extend/override
IntrospectionProcessor(#1899) - Added
$timeoutparam toProcessHandlerto configure the stream_select() timeout to avoid blocking too long (default is 1.0 sec) (#1916) - Fixed JsonFormatter batch handling to normalize records individually to make sure they look the same as if they were handled one by one (#1906)
- Fixed
StreamHandlerhandling of write failures so that it now closes/reopens the stream and retries the write once before failing (#1882) - Fixed
StreamHandlererror handler causing issues if a stream handler triggers an error (#1866) - Fixed
StreamHandler::resetnot closing the stream, so that it would fail to write in some cases with long running processes (#1862) - Fixed
RotatingFileHandlerissue where rotation does not happen in some long running processes (#1905) - Fixed
JsonFormatterhandling of incomplete classes (#1834) - Fixed
RotatingFileHandlerbug where rotation could sometimes not happen correctly (#1905)
3.7.0 (2024-06-28)
- Added
NormalizerFormatter->setBasePath(...)(andJsonFormatterby extension) that allows removing the project's path from the stack trace output (47e301d3e) - Fixed JsonFormatter handling of incomplete classes (#1834)
- Fixed private error handlers causing problems with custom StreamHandler implementations (#1866)
3.6.0 (2024-04-12)
- Added
LineFormatter->setBasePath(...)that allows removing the project's path from the stack trace output (#1873) - Added
$includeExtraoption inPsrHandlerto also use extra data to replace placeholder values in the message (#1852) - Added ability to customize what is a duplicated message by extending the
DeduplicationHandler(#1879) - Added handling for using
GelfMessageFormattertogether with theAmqpHandler(#1869) - Added ability to extend
GoogleCloudLoggingFormatter(#1859) - Fixed
__toStringfailures in context data crashing the normalization process (#1868) - Fixed PHP 8.4 deprecation warnings (#1874)
3.5.0 (2023-10-27)
- Added ability to indent stack traces in LineFormatter via e.g.
indentStacktraces(' ')(#1835) - Added ability to configure a max level name length in LineFormatter via e.g.
setMaxLevelNameLength(3)(#1850) - Added support for indexed arrays (i.e.
[]and not{}arrays once json serialized) containing inline linebreaks in LineFormatter (#1818) - Added
WithMonologChannelattribute for integrators to use to configure autowiring (#1847) - Fixed log record
extradata leaking between handlers that have handler-specific processors set (#1819) - Fixed LogglyHandler issue with record level filtering (#1841)
- Fixed display_errors parsing in ErrorHandler which did not support string values (#1804)
- Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815)
- Fixed normalization error when normalizing incomplete classes (#1833)
3.4.0 (2023-06-21)
- Added
LoadAverageProcessorto track one of the 1, 5 or 15min load averages (#1803) - Added support for priority to the
AsMonologProcessorattribute (#1797) - Added
TelegramBotHandlertopic/message_thread_idsupport (#1802) - Fixed
FingersCrossedHandlerpassthruLevel checking (#1801) - Fixed support of yearly and monthly rotation log file to rotate only once a month/year (#1805)
- Fixed
TestHandlermethod docs (#1794) - Fixed handling of falsey
display_errorsstring values (#1804)
3.3.1 (2023-02-06)
- Fixed Logger not being serializable anymore (#1792)
3.3.0 (2023-02-06)
- Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748)
- Added
ClosureContextProcessorto allow delaying the creation of context data by setting a Closure in context which is called when the log record is used (#1745) - Added an ElasticsearchHandler option to set the
op_typetocreateinstead of the defaultindex(#1766) - Added support for enum context values in PsrLogMessageProcessor (#1773)
- Added graylog2/gelf-php 2.x support (#1747)
- Improved
BrowserConsoleHandlerlogging to use more appropriate methods than just console.log in the browser (#1739) - Fixed GitProcessor not filtering correctly based on Level (#1749)
- Fixed
WhatFailureGroupHandlernot catching errors happening insideclose()(#1791) - Fixed datetime field in
GoogleCloudLoggingFormatter(#1758) - Fixed infinite loop detection within Fibers (#1753)
- Fixed
AmqpHandler->setExtraAttributesnot working with buffering handler wrappers (#1781)
3.2.0 (2022-07-24)
- Deprecated
CubeHandlerandPHPConsoleHandleras both projects are abandoned and those should not be used anymore (#1734) - Marked
Logger@finalas it should not be extended, prefer composition or talk to us if you are missing something - Added RFC 5424 level (
7to0) support toLogger::logandLogger::addRecordto increase interoperability (#1723) - Added
SyslogFormatterto output syslog-like files which can be consumed by tools like lnav (#1689) - Added support for
__toStringfor objects which are not json serializable inJsonFormatter(#1733) - Added
GoogleCloudLoggingFormatter(#1719) - Added support for Predis 2.x (#1732)
- Added
AmqpHandler->setExtraAttributesto allow configuring attributes when using an AMQPExchange (#1724) - Fixed serialization/unserialization of handlers to make sure private properties are included (#1727)
- Fixed allowInlineLineBreaks in LineFormatter causing issues with windows paths containing
\nor\rsequences (#1720) - Fixed max normalization depth not being taken into account when formatting exceptions with a deep chain of previous exceptions (#1726)
- Fixed PHP 8.2 deprecation warnings (#1722)
- Fixed rare race condition or filesystem issue where StreamHandler is unable to create the directory the log should go into yet it exists already (#1678)
3.1.0 (2022-06-09)
- Added
$datetimeparameter toLogger::addRecordas low level API to allow logging into the past or future (#1682) - Added
Logger::useLoggingLoopDetectionto allow disabling cyclic logging detection in concurrent frameworks (#1681) - Fixed handling of fatal errors if callPrevious is disabled in ErrorHandler (#1670)
- Fixed interop issue by removing the need for a return type in ProcessorInterface (#1680)
- Marked the reusable
Monolog\Test\TestCaseclass as@internalto make sure PHPStorm does not show it above PHPUnit, you may still use it to test your own handlers/etc though (#1677) - Fixed RotatingFileHandler issue when the date format contained slashes (#1671)
3.0.0 (2022-05-10)
Changes from RC1
- The
Monolog\LevelNameenum does not exist anymore, useMonolog\Level->getName()instead.
3.0.0-RC1 (2022-05-08)
This is mostly a cleanup release offering stronger type guarantees for integrators with the
array->object/enum changes, but there is no big new feature for end users.
See UPGRADE notes for details on all breaking changes especially if you are extending/implementing Monolog classes/interfaces.
Noteworthy BC Breaks:
- The minimum supported PHP version is now
8.1.0. - Log records have been converted from an array to a
Monolog\LogRecordobject
with public (and mostly readonly) properties. e.g. instead of doing$record['context']use$record->context.
In formatters or handlers if you rather need an array to work with you can use$record->toArray()
to get back a Monolog 1/2 style record array. This will contain the enum values instead of enum cases
in thelevelandlevel_namekeys to be more backwards compatible and use simpler data types. FormatterInterface,HandlerInterface,ProcessorInterface, etc. changed to containLogRecord $record
instead ofarray $recordparameter types. If you want to support multiple Monolog versions this should
be possible by type-hinting nothing, orarray|LogRecordif you support PHP 8.0+. You can then code
against the $record using Monolog 2 style as LogRecord implements ArrayAccess for BC.
The interfaces do not require aLogRecordreturn type even where it would be applicable, but if you only
support Monolog 3 in integration code I would recommend you useLogRecordreturn types wherever fitting
to ensure forward compatibility as it may be added in Monolog 4.- Log levels are now enums
Monolog\LevelandMonolog\LevelName - Removed deprecated SwiftMailerHandler, migrate to SymfonyMailerHandler instead.
ResettableInterface::reset()now requires a void return type.- All properties have had types added, which may require you to do so as well if you extended
a Monolog class and declared the same property.
New deprecations:
Logger::DEBUG,Logger::ERROR, etc. are now deprecated in favor of theMonolog\Levelenum.
e.g. instead ofLogger::WARNINGuseLevel::Warningif you need to pass the enum case
to Monolog or one of its handlers, orLevel::Warning->valueif you need the integer
value equal to whatLogger::WARNINGwas giving you.Logger::getLevelName()is now deprecated.
2.10.0 (2024-11-12)
- Added
$fileOpenModetoStreamHandlerto define a custom fopen mode to open the log file (#1913) - Fixed
StreamHandlerhandling of write failures so that it now closes/reopens the stream and retries the write once before failing (#1882) - Fixed
StreamHandlererror handler causing issues if a stream handler triggers an error (#1866) - Fixed
JsonFormatterhandling of incomplete classes (#1834) - Fixed
RotatingFileHandlerbug where rotation could sometimes not happen correctly (#1905)
2.9.3 (2024-04-12)
- Fixed PHP 8.4 deprecation warnings (#1874)
2.9.2 (2023-10-27)
- Fixed display_errors parsing in ErrorHandler which did not support string values (#1804)
- Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815)
- Fixed normalization error when normalizing incomplete classes (#1833)
2.9.1 (2023-02-06)
- Fixed Logger not being serializable anymore (#1792)
2.9.0 (2023-02-05)
- Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748)
- Added support for enum context values in PsrLogMessageProcessor (#1773)
- Added graylog2/gelf-php 2.x support (#1747)
- Improved
BrowserConsoleHandlerlogging to use more appropriate methods than just console.log in the browser (#1739) - Fixed
WhatFailureGroupHandlernot catching errors happening insideclose()(#1791) - Fixed datetime field in
GoogleCloudLoggingFormatter(#1758) - Fixed infinite loop detection within Fibers (#1753)
- Fixed
AmqpHandler->setExtraAttributesnot working with buffering handler wrappers (#1781)
2.8.0 (2022-07-24)
- Deprecated
CubeHandlerandPHPConsoleHandleras both projects are abandoned and those should not be used anymore (#1734) - Added RFC 5424 level (
7to0) support toLogger::logandLogger::addRecordto increase interoperability (#1723) - Added support for
__toStringfor objects which are not json serializable inJsonFormatter(#1733) - Added
GoogleCloudLoggingFormatter(#1719) - Added support for Predis 2.x (#1732)
- Added
AmqpHandler->setExtraAttributesto allow configuring attributes when using an AMQPExchange (#1724) - Fixed serialization/unserialization of handlers to make sure private properties are included (#1727)
- Fixed allowInlineLineBreaks in LineFormatter causing issues with windows paths containing
\nor\rsequences (#1720) - Fixed max normalization depth not being taken into account when formatting exceptions with a deep chain of previous exceptions (#1726)
- Fixed PHP 8.2 deprecation warnings (#1722)
- Fixed rare race condition or filesystem issue where StreamHandler is unable to create the directory the log should go into yet it exists already (#1678)
2.7.0 (2022-06-09)
- Added
$datetimeparameter toLogger::addRecordas low level API to allow logging into the past or future (#1682) - Added
Logger::useLoggingLoopDetectionto allow disabling cyclic logging detection in concurrent frameworks (#1681) - Fixed handling of fatal errors if callPrevious is disabled in ErrorHandler (#1670)
- Marked the reusable
Monolog\Test\TestCaseclass as@internalto make sure PHPStorm does not show it above PHPUnit, you may still use it to test your own handlers/etc though (#1677) - Fixed RotatingFileHandler issue when the date format contained slashes (#1671)
2.6.0 (2022-05-10)
- Deprecated
SwiftMailerHandler, useSymfonyMailerHandlerinstead - Added
SymfonyMailerHandler(#1663) - Added ElasticSearch 8.x support to the ElasticsearchHandler (#1662)
- Added a way to filter/modify stack traces in LineFormatter (#1665)
- Fixed UdpSocket not being able to reopen/reconnect after close()
- Fixed infinite loops if a Handler is triggering logging while handling log records
2.5.0 (2022-04-08)
- Added
callTypeto IntrospectionProcessor (#1612) - Fixed AsMonologProcessor syntax to be compatible with PHP 7.2 (#1651)
2.4.0 (2022-03-14)
- Added
Monolog\LogRecordinterface that can be used to type-hint records likearray|\Monolog\LogRecord $recordto be forward compatible with the upcoming Monolog 3 changes - Added
includeStacktracesconstructor params to LineFormatter & JsonFormatter (#1603) - Added
persistent,timeout,writingTimeout,connectionTimeout,chunkSizeconstructor params to SocketHandler and derivatives (#1600) - Added
AsMonologProcessorPHP attribute which can help autowiring / autoconfiguration of processors if frameworks / integrations decide to make use of it. This is useless when used purely with Monolog (#1637) - Added support for keeping native BSON types as is in MongoDBFormatter (#1620)
- Added support for a
user_agentkey in WebProcessor, disabled by default but you can use it by configuring the $extraFields you want (#1613) - Added support for username/userIcon in SlackWebhookHandler (#1617)
- Added extension points to BrowserConsoleHandler (#1593)
- Added record message/context/extra info to exceptions thrown when a StreamHandler cannot open its stream to avoid completely losing the data logged (#1630)
- Fixed error handler signature to accept a null $context which happens with internal PHP errors (#1614)
- Fixed a few setter methods not returning
self(#1609) - Fixed handling of records going over the max Telegram message length (#1616)
2.3.5 (2021-10-01)
- Fixed regression in StreamHandler since 2.3.3 on systems with the memory_limit set to >=20GB (#1592)
2.3.4 (2021-09-15)
- Fixed support for psr/log 3.x (#1589)
2.3.3 (2021-09-14)
- Fixed memory usage when using StreamHandler and calling stream_get_contents on the resource you passed to it (#1578, #1577)
- Fixed support for psr/log 2.x (#1587)
- Fixed some type annotations
2.3.2 (2021-07-23)
- Fixed compatibility with PHP 7.2 - 7.4 when experiencing PCRE errors (#1568)
2.3.1 (2021-07-14)
- Fixed Utils::getClass handling of anonymous classes not being fully compatible with PHP 8 (#1563)
- Fixed some
@inheritDocannotations having the wrong case
2.3.0 (2021-07-05)
- Added a ton of PHPStan type annotations as well as type aliases on Monolog\Logger for Record, Level and LevelName that you can import (#1557)
- Added ability to customize date format when using JsonFormatter (#1561)
- Fixed FilterHandler not calling reset on its internal handler when reset() is called on it (#1531)
- Fixed SyslogUdpHandler not setting the timezone correctly on DateTimeImmutable instances (#1540)
- Fixed StreamHandler thread safety - chunk size set to 2GB now to avoid interlacing when doing concurrent writes (#1553)
2.2.0 (2020-12-14)
- Added JSON_PARTIAL_OUTPUT_ON_ERROR to default json encoding flags, to avoid dropping entire context data or even records due to an invalid subset of it somewhere
- Added setDateFormat to NormalizerFormatter (and Line/Json formatters by extension) to allow changing this after object creation
- Added RedisPubSubHandler to log records to a Redis channel using PUBLISH
- Added support for Elastica 7, and deprecated the $type argument of ElasticaFormatter which is not in use anymore as of Elastica 7
- Added support for millisecond write timeouts in SocketHandler, you can now pass floats to setWritingTimeout, e.g. 0.2 is 200ms
- Added support for unix sockets in SyslogUdpHandler (set $port to 0 to make the $host a unix socket)
- Added handleBatch support for TelegramBotHandler
- Added RFC5424e extended date format including milliseconds to SyslogUdpHandler
- Added support for configuring handlers with numeric level values in strings (coming from e.g. env vars)
- Fixed Wildfire/FirePHP/ChromePHP handling of unicode characters
- Fixed PHP 8 issues in SyslogUdpHandler
- Fixed internal type error when mbstring is missing
2.1.1 (2020-07-23)
- Fixed removing of json encoding options
- Fixed type hint of $level not accepting strings in SendGridHandler and OverflowHandler
- Fixed SwiftMailerHandler not accepting email templates with an empty subject
- Fixed array access on null in RavenHandler
- Fixed unique_id in WebProcessor not being disableable
2.1.0 (2020-05-22)
- Added
JSON_INVALID_UTF8_SUBSTITUTEto default json flags, so that invalid UTF8 characters now get converted to ๏ฟฝ instead of being converted from ISO-8859-15 to UTF8 as it was before, which was hardly a comprehensive solution - Added
$ignoreEmptyContextAndExtraoption to JsonFormatter to skip empty context/extra entirely from the output - Added
$parseMode,$disableWebPagePreviewand$disableNotificationoptions to TelegramBotHandler - Added tentative support for PHP 8
- NormalizerFormatter::addJsonEncodeOption and removeJsonEncodeOption are now public to allow modifying default json flags
- Fixed GitProcessor type error when there is no git repo present
- Fixed normalization of SoapFault objects containing deeply nested objects as "detail"
- Fixed support for relative paths in RotatingFileHandler
2.0.2 (2019-12-20)
- Fixed ElasticsearchHandler swallowing exceptions details when failing to index log records
- Fixed normalization of SoapFault objects containing non-strings as "detail" in LineFormatter
- Fixed formatting of resources in JsonFormatter
- Fixed RedisHandler failing to use MULTI properly when passed a proxied Redis instance (e.g. in Symfony with lazy services)
- Fixed FilterHandler triggering a notice when handleBatch was filtering all records passed to it
- Fixed Turkish locale messing up the conversion of level names to their constant values
2.0.1 (2019-11-13)
- Fixed normalization of Traversables to avoid traversing them as not all of them are rewindable
- Fixed setFormatter/getFormatter to forward to the nested handler in FilterHandler, FingersCrossedHandler, BufferHandler, OverflowHandler and SamplingHandler
- Fixed BrowserConsoleHandler formatting when using multiple styles
- Fixed normalization of exception codes to be always integers even for PDOException which have them as numeric strings
- Fixed normalization of SoapFault objects containing non-strings as "detail"
- Fixed json encoding across all handlers to always attempt recovery of non-UTF-8 strings instead of failing the whole encoding
- Fixed ChromePHPHandler to avoid sending more data than latest Chrome versions allow in headers (4KB down from 256KB).
- Fixed type error in BrowserConsoleHandler when the context array of log records was not associative.
2.0.0 (2019-08-30)
- BC Break: This is a major release, see UPGRADE.md for details if you are coming from a 1.x release
- BC Break: Logger methods log/debug/info/notice/warning/error/critical/alert/emergency now have explicit void return types
- Added FallbackGroupHandler which works like the WhatFailureGroupHandler but stops dispatching log records as soon as one handler accepted it
- Fixed support for UTF-8 when cutting strings to avoid cutting a multibyte-character in half
- Fixed normalizers handling of exception backtraces to avoid serializing arguments in some cases
- Fixed date timezone handling in SyslogUdpHandler
2.0.0-beta2 (2019-07-06)
- BC Break: This is a major release, see UPGRADE.md for details if you are coming from a 1.x release
- BC Break: PHP 7.2 is now the minimum required PHP version.
- BC Break: Removed SlackbotHandler, RavenHandler and HipChatHandler, see UPGRADE.md for details
- Added OverflowHandler which will only flush log records to its nested handler when reaching a certain amount of logs (i.e. only pass through when things go really bad)
- Added TelegramBotHandler to log records to a Telegram bot account
- Added support for JsonSerializable when normalizing exceptions
- Added support for RFC3164 (outdated BSD syslog protocol) to SyslogUdpHandler
- Added SoapFault details to formatted exceptions
- Fixed DeduplicationHandler silently failing to start when file could not be opened
- Fixed issue in GroupHandler and WhatFailureGroupHandler where setting multiple processors would duplicate records
- Fixed GelfFormatter losing some data when one attachment was too long
- Fixed issue in SignalHandler restarting syscalls functionality
- Improved performance of LogglyHandler when sending multiple logs in a single request
2.0.0-beta1 (2018-12-08)
- BC Break: This is a major release, see UPGRADE.md for details if you are coming from a 1.x release
- BC Break: PHP 7.1 is now the minimum required PHP version.
- BC Break: Quite a few interface changes, only relevant if you implemented your own handlers/processors/formatters
- BC Break: Removed non-PSR-3 methods to add records, all the
add*(e.g.addWarning) methods as well asemerg,crit,errandwarn - BC Break: The record timezone is now set per Logger instance and not statically anymore
- BC Break: There is no more default handler configured on empty Logger instances
- BC Break: ElasticSearchHandler renamed to ElasticaHandler
- BC Break: Various handler-specific breaks, see UPGRADE.md for details
- Added scalar type hints and return hints in all the places it was possible. Switched strict_types on for more reliability.
- Added DateTimeImmutable support, all record datetime are now immutable, and will toString/json serialize with the correct date format, including microseconds (unless disabled)
- Added timezone and microseconds to the default date format
- Added SendGridHandler to use the SendGrid API to send emails
- Added LogmaticHandler to use the Logmatic.io API to store log records
- Added SqsHandler to send log records to an AWS SQS queue
- Added ElasticsearchHandler to send records via the official ES library. Elastica users should now use ElasticaHandler instead of ElasticSearchHandler
- Added NoopHandler which is similar to the NullHandle but does not prevent the bubbling of log records to handlers further down the configuration, useful for temporarily disabling a handler in configuration files
- Added ProcessHandler to write log output to the STDIN of a given process
- Added HostnameProcessor that adds the machine's hostname to log records
- Added a
$dateFormatoption to the PsrLogMessageProcessor which lets you format DateTime instances nicely - Added support for the PHP 7.x
mongodbextension in the MongoDBHandler - Fixed many minor issues in various handlers, and probably added a few regressions too
1.26.1 (2021-05-28)
- Fixed PHP 8.1 deprecation warning
1.26.0 (2020-12-14)
- Added $dateFormat and $removeUsedContextFields arguments to PsrLogMessageProcessor (backport from 2.x)
1.25.5 (2020-07-23)
- Fixed array access on null in RavenHandler
- Fixed unique_id in WebProcessor not being disableable
1.25.4 (2020-05-22)
- Fixed GitProcessor type error when there is no git repo present
- Fixed normalization of SoapFault objects containing deeply nested objects as "detail"
- Fixed support for relative paths in RotatingFileHandler
1.25.3 (2019-12-20)
- Fixed formatting of resources in JsonFormatter
- Fixed RedisHandler failing to use MULTI properly when passed a proxied Redis instance (e.g. in Symfony with lazy services)
- Fixed FilterHandler triggering a notice when handleBatch was filtering all records passed to it
- Fixed Turkish locale messing up the conversion of level names to their constant values
1.25.2 (2019-11-13)
- Fixed normalization of Traversables to avoid traversing them as not all of them are rewindable
- Fixed setFormatter/getFormatter to forward to the nested handler in FilterHandler, FingersCrossedHandler, BufferHandler and SamplingHandler
- Fixed BrowserConsoleHandler formatting when using multiple styles
- Fixed normalization of exception codes to be always integers even for PDOException which have them as numeric strings
- Fixed normalization of SoapFault objects containing non-strings as "detail"
- Fixed json encoding across all handlers to always attempt recovery of non-UTF-8 strings instead of failing the whole encoding
1.25.1 (2019-09-06)
- Fixed forward-compatible interfaces to be compatible with Monolog 1.x too.
1.25.0 (2019-09-06)
- Deprecated SlackbotHandler, use SlackWebhookHandler or SlackHandler instead
- Deprecated RavenHandler, use sentry/sentry 2.x and their Sentry\Monolog\Handler instead
- Deprecated HipChatHandler, migrate to Slack and use SlackWebhookHandler or SlackHandler instead
- Added forward-compatible interfaces and traits FormattableHandlerInterface, FormattableHandlerTrait, ProcessableHandlerInterface, ProcessableHandlerTrait. If you use modern PHP and want to make code compatible with Monolog 1 and 2 this can help. You will have to require at least Monolog 1.25 though.
- Added support for RFC3164 (outdated BSD syslog protocol) to SyslogUdpHandler
- Fixed issue in GroupHandler and WhatFailureGroupHandler where setting multiple processors would duplicate records
- Fixed issue in SignalHandler restarting syscalls functionality
- Fixed normalizers handling of exception backtraces to avoid serializing arguments in some cases
- Fixed ZendMonitorHandler to work with the latest Zend Server versions
- Fixed ChromePHPHandler to avoid sending more data than latest Chrome versions allow in headers (4KB down from 256KB).
1.24.0 (2018-11-05)
- BC Notice: If you are extending any of the Monolog's Formatters'
normalizemethod, make sure you add the new$depth = 0argument to your function signature to avoid strict PHP warnings. - Added a
ResettableInterfacein order to reset/reset/clear/flush handlers and processors - Added a
ProcessorInterfaceas an optional way to label a class as being a processor (mostly useful for autowiring dependency containers) - Added a way to log signals being received using Monolog\SignalHandler
- Added ability to customize error handling at the Logger level using Logger::setExceptionHandler
- Added InsightOpsHandler to migrate users of the LogEntriesHandler
- Added protection to NormalizerFormatter against circular and very deep structures, it now stops normalizing at a depth of 9
- Added capture of stack traces to ErrorHandler when logging PHP errors
- Added RavenHandler support for a
contextscontext or extra key to forward that to Sentry's contexts - Added forwarding of context info to FluentdFormatter
- Added SocketHandler::setChunkSize to override the default chunk size in case you must send large log lines to rsyslog for example
- Added ability to extend/override BrowserConsoleHandler
- Added SlackWebhookHandler::getWebhookUrl and SlackHandler::getToken to enable class extensibility
- Added SwiftMailerHandler::getSubjectFormatter to enable class extensibility
- Dropped official support for HHVM in test builds
- Fixed normalization of exception traces when call_user_func is used to avoid serializing objects and the data they contain
- Fixed naming of fields in Slack handler, all field names are now capitalized in all cases
- Fixed HipChatHandler bug where slack dropped messages randomly
- Fixed normalization of objects in Slack handlers
- Fixed support for PHP7's Throwable in NewRelicHandler
- Fixed race bug when StreamHandler sometimes incorrectly reported it failed to create a directory
- Fixed table row styling issues in HtmlFormatter
- Fixed RavenHandler dropping the message when logging exception
- Fixed WhatFailureGroupHandler skipping processors when using handleBatch
and implement it where possible - Fixed display of anonymous class names
1.23.0 (2017-06-19)
- Improved SyslogUdpHandler's support for RFC5424 and added optional
$identargument - Fixed GelfHandler truncation to be per field and not per message
- Fixed compatibility issue with PHP <5.3.6
- Fixed support for headless Chrome in ChromePHPHandler
- Fixed support for latest Aws SDK in DynamoDbHandler
- Fixed support for SwiftMailer 6.0+ in SwiftMailerHandler
1.22.1 (2017-03-13)
- Fixed lots of minor issues in the new Slack integrations
- Fixed support for allowInlineLineBreaks in LineFormatter when formatting exception backtraces
1.22.0 (2016-11-26)
- Added SlackbotHandler and SlackWebhookHandler to set up Slack integration more easily
- Added MercurialProcessor to add mercurial revision and branch names to log records
- Added support for AWS SDK v3 in DynamoDbHandler
- Fixed fatal errors occurring when normalizing generators that have been fully consumed
- Fixed RollbarHandler to include a level (rollbar level), monolog_level (original name), channel and datetime (unix)
- Fixed RollbarHandler not flushing records automatically, calling close() explicitly is not necessary anymore
- Fixed SyslogUdpHandler to avoid sending empty frames
- Fixed a few PHP 7.0 and 7.1 compatibility issues
1.21.0 (2016-07-29)
- Break: Reverted the addition of $context when the ErrorHandler handles regular php errors from 1.20.0 as it was causing issues
- Added support for more formats in RotatingFileHandler::setFilenameFormat as long as they have Y, m and d in order
- Added ability to format the main line of text the SlackHandler sends by explicitly setting a formatter on the handler
- Added information about SoapFault instances in NormalizerFormatter
- Added $handleOnlyReportedErrors option on ErrorHandler::registerErrorHandler (default true) to allow logging of all errors no matter the error_reporting level
1.20.0 (2016-07-02)
- Added FingersCrossedHandler::activate() to manually trigger the handler regardless of the activation policy
- Added StreamHandler::getUrl to retrieve the stream's URL
- Added ability to override addRow/addTitle in HtmlFormatter
- Added the $context to context information when the ErrorHandler handles a regular php error
- Deprecated RotatingFileHandler::setFilenameFormat to only support 3 formats: Y, Y-m and Y-m-d
- Fixed WhatFailureGroupHandler to work with PHP7 throwables
- Fixed a few minor bugs
1.19.0 (2016-04-12)
- Break: StreamHandler will not close streams automatically that it does not own. If you pass in a stream (not a path/url), then it will not close it for you. You can retrieve those using getStream() if needed
- Added DeduplicationHandler to remove duplicate records from notifications across multiple requests, useful for email or other notifications on errors
- Added ability to use
%message%and other LineFormatter replacements in the subject line of emails sent with NativeMailHandler and SwiftMailerHandler - Fixed HipChatHandler handling of long messages
1.18.2 (2016-04-02)
- Fixed ElasticaFormatter to use more precise dates
- Fixed GelfMessageFormatter sending too long messages
1.18.1 (2016-03-13)
- Fixed SlackHandler bug where slack dropped messages randomly
- Fixed RedisHandler issue when using with the PHPRedis extension
- Fixed AmqpHandler content-type being incorrectly set when using with the AMQP extension
- Fixed BrowserConsoleHandler regression
1.18.0 (2016-03-01)
- Added optional reduction of timestamp precision via
Logger->useMicrosecondTimestamps(false), disabling it gets you a bit of performance boost but reduces the precision to the second instead of microsecond - Added possibility to skip some extra stack frames in IntrospectionProcessor if you have some library wrapping Monolog that is always adding frames
- Added
Logger->withNameto clone a logger (keeping all handlers) with a new name - Added FluentdFormatter for the Fluentd unix socket protocol
- Added HandlerWrapper base class to ease the creation of handler wrappers, just extend it and override as needed
- Added support for replacing context sub-keys using
%context.*%in LineFormatter - Added support for
payloadcontext value in RollbarHandler - Added setRelease to RavenHandler to describe the application version, sent with every log
- Added support for
fingerprintcontext value in RavenHandler - Fixed JSON encoding errors that would gobble up the whole log record, we now handle those more gracefully by dropping chars as needed
- Fixed write timeouts in SocketHandler and derivatives, set to 10sec by default, lower it with
setWritingTimeout() - Fixed PHP7 compatibility with regard to Exception/Throwable handling in a few places
1.17.2 (2015-10-14)
- Fixed ErrorHandler compatibility with non-Monolog PSR-3 loggers
- Fixed SlackHandler handling to use slack functionalities better
- Fixed SwiftMailerHandler bug when sending multiple emails they all had the same id
- Fixed 5.3 compatibility regression
1.17.1 (2015-08-31)
- Fixed RollbarHandler triggering PHP notices
1.17.0 (2015-08-30)
- Added support for
checksumandreleasecontext/extra values in RavenHandler - Added better support for exceptions in RollbarHandler
- Added UidProcessor::getUid
- Added support for showing the resource type in NormalizedFormatter
- Fixed IntrospectionProcessor triggering PHP notices
1.16.0 (2015-08-09)
- Added IFTTTHandler to notify ifttt.com triggers
- Added Logger::setHandlers() to allow setting/replacing all handlers
- Added $capSize in RedisHandler to cap the log size
- Fixed StreamHandler creation of directory to only trigger when the first log write happens
- Fixed bug in the handling of curl failures
- Fixed duplicate logging of fatal errors when both error and fatal error handlers are registered in monolog's ErrorHandler
- Fixed missing fatal errors records with handlers that need to be closed to flush log records
- Fixed TagProcessor::addTags support for associative arrays
1.15.0 (2015-07-12)
- Added addTags and setTags methods to change a TagProcessor
- Added automatic creation of directories if they are missing for a StreamHandler to open a log file
- Added retry functionality to Loggly, Cube and Mandrill handlers so they retry up to 5 times in case of network failure
- Fixed process exit code being incorrectly reset to 0 if ErrorHandler::registerExceptionHandler was used
- Fixed HTML/JS escaping in BrowserConsoleHandler
- Fixed JSON encoding errors being silently suppressed (PHP 5.5+ only)
1.14.0 (2015-06-19)
- Added PHPConsoleHandler to send record to Chrome's PHP Console extension and library
- Added support for objects implementing __toString in the NormalizerFormatter
- Added support for HipChat's v2 API in HipChatHandler
- Added Logger::setTimezone() to initialize the timezone monolog should use in case date.timezone isn't correct for your app
- Added an option to send formatted message instead of the raw record on PushoverHandler via ->useFormattedMessage(true)
- Fixed curl errors being silently suppressed
1.13.1 (2015-03-09)
- Fixed regression in HipChat requiring a new token to be created
1.13.0 (2015-03-05)
- Added Registry::hasLogger to check for the presence of a logger instance
- Added context.user support to RavenHandler
- Added HipChat API v2 support in the HipChatHandler
- Added NativeMailerHandler::addParameter to pass params to the mail() process
- Added context data to SlackHandler when $includeContextAndExtra is true
- Added ability to customize the Swift_Message per-email in SwiftMailerHandler
- Fixed SwiftMailerHandler to lazily create message instances if a callback is provided
- Fixed serialization of INF and NaN values in Normalizer and LineFormatter
1.12.0 (2014-12-29)
- Break: HandlerInterface::isHandling now receives a partial record containing only a level key. This was always the intent and does not break any Monolog handler but is strictly speaking a BC break and you should check if you relied on any other field in your own handlers.
- Added PsrHandler to forward records to another PSR-3 logger
- Added SamplingHandler to wrap around a handler and include only every Nth record
- Added MongoDBFormatter to support better storage with MongoDBHandler (it must be enabled manually for now)
- Added exception codes in the output of most formatters
- Added LineFormatter::includeStacktraces to enable exception stack traces in logs (uses more than one line)
- Added $useShortAttachment to SlackHandler to minify attachment size and $includeExtra to append extra data
- Added $host to HipChatHandler for users of private instances
- Added $transactionName to NewRelicHandler and support for a transaction_name context value
- Fixed MandrillHandler to avoid outputting API call responses
- Fixed some non-standard behaviors in SyslogUdpHandler
1.11.0 (2014-09-30)
- Break: The NewRelicHandler extra and context data are now prefixed with extra_ and context_ to avoid clashes. Watch out if you have scripts reading those from the API and rely on names
- Added WhatFailureGroupHandler to suppress any exception coming from the wrapped handlers and avoid chain failures if a logging service fails
- Added MandrillHandler to send emails via the Mandrillapp.com API
- Added SlackHandler to log records to a Slack.com account
- Added FleepHookHandler to log records to a Fleep.io account
- Added LogglyHandler::addTag to allow adding tags to an existing handler
- Added $ignoreEmptyContextAndExtra to LineFormatter to avoid empty [] at the end
- Added $useLocking to StreamHandler and RotatingFileHandler to enable flock() while writing
- Added support for PhpAmqpLib in the AmqpHandler
- Added FingersCrossedHandler::clear and BufferHandler::clear to reset them between batches in long running jobs
- Added support for adding extra fields from $_SERVER in the WebProcessor
- Fixed support for non-string values in PrsLogMessageProcessor
- Fixed SwiftMailer messages being sent with the wrong date in long running scripts
- Fixed minor PHP 5.6 compatibility issues
- Fixed BufferHandler::close being called twice
1.10.0 (2014-06-04)
- Added Logger::getHandlers() and Logger::getProcessors() methods
- Added $passthruLevel argument to FingersCrossedHandler to let it always pass some records through even if the trigger level is not reached
- Added support for extra data in NewRelicHandler
- Added $expandNewlines flag to the ErrorLogHandler to create multiple log entries when a message has multiple lines
1.9.1 (2014-04-24)
- Fixed regression in RotatingFileHandler file permissions
- Fixed initialization of the BufferHandler to make sure it gets flushed after receiving records
- Fixed ChromePHPHandler and FirePHPHandler's activation strategies to be more conservative
1.9.0 (2014-04-20)
- Added LogEntriesHandler to send logs to a LogEntries account
- Added $filePermissions to tweak file mode on StreamHandler and RotatingFileHandler
- Added $useFormatting flag to MemoryProcessor to make it send raw data in bytes
- Added support for table formatting in FirePHPHandler via the table context key
- Added a TagProcessor to add tags to records, and support for tags in RavenHandler
- Added $appendNewline flag to the JsonFormatter to enable using it when logging to files
- Added sound support to the PushoverHandler
- Fixed multi-threading support in StreamHandler
- Fixed empty headers issue when ChromePHPHandler received no records
- Fixed default format of the ErrorLogHandler
1.8.0 (2014-03-23)
- Break: the LineFormatter now strips newlines by default because this was a bug, set $allowInlineLineBreaks to true if you need them
- Added BrowserConsoleHandler to send logs to any browser's console via console.log() injection in the output
- Added FilterHandler to filter records and only allow those of a given list of levels through to the wrapped handler
- Added FlowdockHandler to send logs to a Flowdock account
- Added RollbarHandler to send logs to a Rollbar account
- Added HtmlFormatter to send prettier log emails with colors for each log level
- Added GitProcessor to add the current branch/commit to extra record data
- Added a Monolog\Registry class to allow easier global access to pre-configured loggers
- Added support for the new official graylog2/gelf-php lib for GelfHandler, upgrade if you can by replacing the mlehner/gelf-php requirement
- Added support for HHVM
- Added support for Loggly batch uploads
- Added support for tweaking the content type and encoding in NativeMailerHandler
- Added $skipClassesPartials to tweak the ignored classes in the IntrospectionProcessor
- Fixed batch request support in GelfHandler
1.7.0 (2013-11-14)
- Added ElasticSearchHandler to send logs to an Elastic Search server
- Added DynamoDbHandler and ScalarFormatter to send logs to Amazon's Dynamo DB
- Added SyslogUdpHandler to send logs to a remote syslogd server
- Added LogglyHandler to send logs to a Loggly account
- Added $level to IntrospectionProcessor so it only adds backtraces when needed
- Added $version to LogstashFormatter to allow using the new v1 Logstash format
- Added $appName to NewRelicHandler
- Added configuration of Pushover notification retries/expiry
- Added $maxColumnWidth to NativeMailerHandler to change the 70 chars default
- Added chainability to most setters for all handlers
- Fixed RavenHandler batch processing so it takes the message from the record with highest priority
- Fixed HipChatHandler batch processing so it sends all messages at once
- Fixed issues with eAccelerator
- Fixed and improved many small things
1.6.0 (2013-07-29)
- Added HipChatHandler to send logs to a HipChat chat room
- Added ErrorLogHandler to send logs to PHP's error_log function
- Added NewRelicHandler to send logs to NewRelic's service
- Added Monolog\ErrorHandler helper class to register a Logger as exception/error/fatal handler
- Added ChannelLevelActivationStrategy for the FingersCrossedHandler to customize levels by channel
- Added stack traces output when normalizing exceptions (json output & co)
- Added Monolog\Logger::API constant (currently 1)
- Added support for ChromePHP's v4.0 extension
- Added support for message priorities in PushoverHandler, see $highPriorityLevel and $emergencyLevel
- Added support for sending messages to multiple users at once with the PushoverHandler
- Fixed RavenHandler's support for batch sending of messages (when behind a Buffer or FingersCrossedHandler)
- Fixed normalization of Traversables with very large data sets, only the first 1000 items are shown now
- Fixed issue in RotatingFileHandler when an open_basedir restriction is active
- Fixed minor issues in RavenHandler and bumped the API to Raven 0.5.0
- Fixed SyslogHandler issue when many were used concurrently with different facilities
1.5.0 (2013-04-23)
- Added ProcessIdProcessor to inject the PID in log records
- Added UidProcessor to inject a unique identifier to all log records of one request/run
- Added support for previous exceptions in the LineFormatter exception serialization
- Added Monolog\Logger::getLevels() to get all available levels
- Fixed ChromePHPHandler so it avoids sending headers larger than Chrome can handle
1.4.1 (2013-04-01)
- Fixed exception formatting in the LineFormatter to be more minimalistic
- Fixed RavenHandler's handling of context/extra data, requires Raven client >0.1.0
- Fixed log rotation in RotatingFileHandler to work with long running scripts spanning multiple days
- Fixed WebProcessor array access so it checks for data presence
- Fixed Buffer, Group and FingersCrossed handlers to make use of their processors
1.4.0 (2013-02-13)
- Added RedisHandler to log to Redis via the Predis library or the phpredis extension
- Added ZendMonitorHandler to log to the Zend Server monitor
- Added the possibility to pass arrays of handlers and processors directly in the Logger constructor
- Added
$useSSLoption to the PushoverHandler which is enabled by default - Fixed ChromePHPHandler and FirePHPHandler issue when multiple instances are used simultaneously
- Fixed header injection capability in the NativeMailHandler
1.3.1 (2013-01-11)
- Fixed LogstashFormatter to be usable with stream handlers
- Fixed GelfMessageFormatter levels on Windows
1.3.0 (2013-01-08)
- Added PSR-3 compliance, the
Monolog\Loggerclass is now an instance ofPsr\Log\LoggerInterface - Added PsrLogMessageProcessor that you can selectively enable for full PSR-3 compliance
- Added LogstashFormatter (combine with SocketHandler or StreamHandler to send logs to Logstash)
- Added PushoverHandler to send mobile notifications
- Added CouchDBHandler and DoctrineCouchDBHandler
- Added RavenHandler to send data to Sentry servers
- Added support for the new MongoClient class in MongoDBHandler
- Added microsecond precision to log records' timestamps
- Added
$flushOnOverflowparam to BufferHandler to flush by batches instead of losing
the oldest entries - Fixed normalization of objects with cyclic references
1.2.1 (2012-08-29)
- Added new $logopts arg to SyslogHandler to provide custom openlog options
- Fixed fatal error in SyslogHandler
1.2.0 (2012-08-18)
- Added AmqpHandler (for use with AMQP servers)
- Added CubeHandler
- Added NativeMailerHandler::addHeader() to send custom headers in mails
- Added the possibility to specify more than one recipient in NativeMailerHandler
- Added the possibility to specify float timeouts in SocketHandler
- Added NOTICE and EMERGENCY levels to conform with RFC 5424
- Fixed the log records to use the php default timezone instead of UTC
- Fixed BufferHandler not being flushed properly on PHP fatal errors
- Fixed normalization of exotic resource types
- Fixed the default format of the SyslogHandler to avoid duplicating datetimes in syslog
1.1.0 (2012-04-23)
- Added Monolog\Logger::isHandling() to check if a handler will
handle the given log level - Added ChromePHPHandler
- Added MongoDBHandler
- Added GelfHandler (for use with Graylog2 servers)
- Added SocketHandler (for use with syslog-ng for example)
- Added NormalizerFormatter
- Added the possibility to change the activation strategy of the FingersCrossedHandler
- Added possibility to show microseconds in logs
- Added
serverandrefererto WebProcessor output
1.0.2 (2011-10-24)
- Fixed bug in IE with large response headers and FirePHPHandler
1.0.1 (2011-08-25)
- Added MemoryPeakUsageProcessor and MemoryUsageProcessor
- Added Monolog\Logger::getName() to get a logger's channel name
1.0.0 (2011-07-06)
- Added IntrospectionProcessor to get info from where the logger was called
- Fixed WebProcessor in CLI
1.0.0-RC1 (2011-07-01)
- Initial release
File: composer.json
{
"name": "monolog/monolog",
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
"keywords": ["log", "logging", "psr-3"],
"homepage": "https://github.com/Seldaek/monolog",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Jordi Boggiano",
"email": "[email protected]",
"homepage": "https://seld.be"
}
],
"require": {
"php": ">=8.1",
"psr/log": "^2.0 || ^3.0"
},
"require-dev": {
"ext-json": "*",
"aws/aws-sdk-php": "^3.0",
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
"graylog2/gelf-php": "^1.4.2 || ^2.0",
"guzzlehttp/guzzle": "^7.4.5",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8 || ^2.0",
"php-amqplib/php-amqplib": "~2.4 || ^3",
"php-console/php-console": "^3.1.8",
"phpstan/phpstan": "^2",
"phpstan/phpstan-deprecation-rules": "^2",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "^10.5.17 || ^11.0.7",
"predis/predis": "^1.1 || ^2",
"psr/clock": "^1.0",
"rollbar/rollbar": "^4.0",
"ruflin/elastica": "^7 || ^8",
"symfony/mailer": "^5.4 || ^6",
"symfony/mime": "^5.4 || ^6"
},
"suggest": {
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
"ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"ext-mbstring": "Allow to work properly with unicode symbols",
"ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
"ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
"ext-openssl": "Required to send log messages using SSL",
"psr/clock": "Required to pass a clock to the Logger and control the timestamp of log records"
},
"autoload": {
"psr-4": {"Monolog\": "src/Monolog"}
},
"autoload-dev": {
"psr-4": {"Monolog\": "tests/Monolog"}
},
"provide": {
"psr/log-implementation": "3.0.0"
},
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"scripts": {
"test": "@php vendor/bin/phpunit",
"phpstan": "@php vendor/bin/phpstan analyse"
},
"config": {
"lock": false,
"sort-packages": true,
"platform-check": false,
"allow-plugins": {
"php-http/discovery": false
}
}
}
File: UPGRADE.md
4.0.0
Overall / notable changes:
- Monolog\DateTimeImmutable has been removed in favor of Monolog\JsonSerializableDateTimeImmutable.
3.0.0
Overall / notable changes:
- The minimum supported PHP version is now
8.1.0. Monolog\Logger::APIcan be used to distinguish between a Monolog3,2or1
install when writing integration code.- Log records have been converted from an array to a
Monolog\LogRecordobject
with public (and mostly readonly) properties. e.g. instead of doing$record['context']use$record->context.
In formatters or handlers if you rather need an array to work with you can use$record->toArray()
to get back a Monolog 1/2 style record array. This will contain the enum values instead of enum cases
in thelevelandlevel_namekeys to be more backwards compatible and use simpler data types. FormatterInterface,HandlerInterface,ProcessorInterface, etc. changed to containLogRecord $record
instead ofarray $recordparameter types. If you want to support multiple Monolog versions this should
be possible by type-hinting nothing, orarray|LogRecordif you support PHP 8.0+. You can then code
against the $record using Monolog 2 style as LogRecord implements ArrayAccess for BC.
The interfaces do not require aLogRecordreturn type even where it would be applicable, but if you only
support Monolog 3 in integration code I would recommend you useLogRecordreturn types wherever fitting
to ensure forward compatibility as it may be added in Monolog 4.- Log levels are now stored as an enum
Monolog\Level - All properties have had types added, which may require you to do so as well if you extended
a Monolog class and declared the same property.
Logger
Logger::DEBUG,Logger::ERROR, etc. are now deprecated in favor of theLevelenum.
e.g. instead ofLogger::WARNINGuseLevel::Warningif you need to pass the enum case
to Monolog or one of its handlers, orLevel::Warning->valueif you need the integer
value equal to whatLogger::WARNINGwas giving you.Logger::$levelshas been removed.Logger::getLevelshas been removed in favor ofMonolog\Level::VALUESorMonolog\Level::cases().setExceptionHandlernow requires aClosureinstance and not just anycallable.
HtmlFormatter
- If you redefined colors in the
$logLevelsproperty you must now override thegetLevelColormethod instead.
NormalizerFormatter
- A new
normalizeRecordmethod is available as an extension point which is called
only when converting the LogRecord to an array. You may need this if you overrodeformatpreviously asparent::formatnow needs to receive a LogRecord still
so you cannot modify it before.
AbstractSyslogHandler
- If you redefined syslog levels in the
$logLevelsproperty you must now override thetoSyslogPrioritymethod instead.
DynamoDbHandler
- Dropped support for AWS SDK v2
FilterHandler
- The factory callable to lazy load the nested handler must now be a
Closureinstance
and not just acallable.
FingersCrossedHandler
- The factory callable to lazy load the nested handler must now be a
Closureinstance
and not just acallable.
GelfHandler
- Dropped support for Gelf <1.1 and added support for graylog2/gelf-php v2.x. File, level
and facility are now passed in as additional fields (#1664)[https://github.com/Seldaek/monolog/pull/1664].
RollbarHandler
- If you redefined rollbar levels in the
$logLevelsproperty you must now override thetoRollbarLevelmethod instead.
SamplingHandler
- The factory callable to lazy load the nested handler must now be a
Closureinstance
and not just acallable.
SwiftMailerHandler
- Removed deprecated SwiftMailer handler, migrate to SymfonyMailerHandler instead.
ZendMonitorHandler
- If you redefined zend monitor levels in the
$levelMapproperty you must now override thetoZendMonitorLevelmethod instead.
ResettableInterface
reset()now requires a void return type.
2.0.0
Monolog\Logger::APIcan be used to distinguish between a Monolog1and2
install of Monolog when writing integration code.Removed non-PSR-3 methods to add records, all the
add*(e.g.addWarning)
methods as well asemerg,crit,errandwarn.DateTime are now formatted with a timezone and microseconds (unless disabled).
Various formatters and log output might be affected, which may mess with log parsing
in some cases.The
datetimein every record array is now a DateTimeImmutable, not that you
should have been modifying these anyway.The timezone is now set per Logger instance and not statically, either
via ->setTimezone or passed in the constructor. Calls to Logger::setTimezone
should be converted.HandlerInterfacehas been split off and two new interfaces now exist for
more granular controls:ProcessableHandlerInterfaceandFormattableHandlerInterface. Handlers not extendingAbstractHandler
should make sure to implement the relevant interfaces.HandlerInterfacenow requires theclosemethod to be implemented. This
only impacts you if you implement the interface yourself, but you can extend
the newMonolog\Handler\Handlerbase class too.There is no more default handler configured on empty Logger instances, if
you were relying on that you will not get any output anymore, make sure to
configure the handler you need.
LogglyFormatter
- The records'
datetimeis not sent anymore. Onlytimestampis sent to Loggly.
AmqpHandler
- Log levels are not shortened to 4 characters anymore. e.g. a warning record
will be sent using thewarning.channelrouting key instead ofwarn.channel
as in 1.x. - The exchange name does not default to 'log' anymore, and it is completely ignored
now for the AMQP extension users. Only PHPAmqpLib uses it if provided.
RotatingFileHandler
- The file name format must now contain
{date}and the date format must be set
to one of the predefined FILE_PER_* constants to avoid issues with file rotation.
SeesetFilenameFormat.
LogstashFormatter
- Removed Logstash V0 support
- Context/extra prefix has been removed in favor of letting users configure the exact key being sent
- Context/extra data are now sent as an object instead of single keys
HipChatHandler
- Removed deprecated HipChat handler, migrate to Slack and use SlackWebhookHandler or SlackHandler instead
SlackbotHandler
- Removed deprecated SlackbotHandler handler, use SlackWebhookHandler or SlackHandler instead
RavenHandler
- Removed deprecated RavenHandler handler, use sentry/sentry 2.x and their Sentry\Monolog\Handler instead
ElasticSearchHandler
- As support for the official Elasticsearch library was added, the former ElasticSearchHandler has been
renamed to ElasticaHandler and the new one added as ElasticsearchHandler.
File: doc/01-usage.md
Using Monolog
- Installation
- Core Concepts
- Log Levels
- Configuring a logger
- Adding extra data in the records
- Leveraging channels
- Customizing the log format
- Long running processes and avoiding memory leaks
Installation
Monolog is available on Packagist (monolog/monolog)
and as such installable via Composer.
composer require monolog/monologCore Concepts
Every Logger instance has a channel (name) and a stack of handlers. Whenever
you add a record to the logger, it traverses the handler
stack from top to bottom. pushHandler() puts a handler on top of the stack, so
the last handler pushed is called first. Handlers passed to the Logger
constructor or to setHandlers() are given in call order instead, i.e. the
first one in the array is called first.
Each handler that is interested in a record handles it, and by default the
record then keeps travelling down to the next handler. Handlers accept a$bubble constructor argument which defaults to true; setting it to false
means that once that handler has handled a record, the handlers below it never
see it. (The name is historical: records travel from the top of the stack
downwards, so a handler that lets records through is said to let them bubble.)
This allows for flexible logging setups, for example adding a StreamHandler
first so that it sits at the bottom of the stack and logs to disk, then adding
a mail handler such as NativeMailerHandler on top of it so that it is called
first and only sends emails when an error message is logged. Note that giving
that mail handler $bubble = false means the error records it handles will be
emailed but will no longer reach the StreamHandler below it.
You can create many Loggers, each defining a channel (e.g.: db, request,
router, ..) and each of them combining various handlers, which can be shared
or not. The channel is reflected in the logs and allows you to easily see or
filter records.
Each Handler also has a Formatter, a default one with settings that make sense
will be created if you don't set one. The formatters normalize and format
incoming records so that they can be used by the handlers to output useful
information.
Custom severity levels are not available. Only the eight
RFC 5424 levels (debug, info, notice,
warning, error, critical, alert, emergency) are present for basic filtering
purposes, but for sorting and other use cases that would require
flexibility, you should add Processors to the Logger that can add extra
information (tags, user ip, ..) to the records before they are handled.
Log Levels
Monolog supports the logging levels described by RFC 5424.
DEBUG (100): Detailed debug information.
INFO (200): Interesting events. Examples: User logs in, SQL logs.
NOTICE (250): Normal but significant events.
WARNING (300): Exceptional occurrences that are not errors. Examples:
Use of deprecated APIs, poor use of an API, undesirable things that are not
necessarily wrong.ERROR (400): Runtime errors that do not require immediate action but
should typically be logged and monitored.CRITICAL (500): Critical conditions. Example: Application component
unavailable, unexpected exception.ALERT (550): Action must be taken immediately. Example: Entire website
down, database unavailable, etc. This should trigger the SMS alerts and wake
you up.EMERGENCY (600): Emergency: system is unusable.
Configuring a logger
Here is a basic setup to log to a file and to firephp on the DEBUG level:
<?php
use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
// Create the logger
$logger = new Logger('my_logger');
// Now add some handlers
$logger->pushHandler(new StreamHandler(__DIR__.'/my_app.log', Level::Debug));
$logger->pushHandler(new FirePHPHandler());
// You can now use your logger
$logger->info('My logger is now ready');Let's explain it. The first step is to create the logger instance which will
be used in your code. The argument is a channel name, which is useful when
you use several loggers (see below for more details about it).
The logger itself does not know how to handle a record. It delegates it to
some handlers. The code above registers two handlers in the stack to allow
handling records in two different ways.
Note that the FirePHPHandler is called first as it is added on top of the
stack. This allows you to temporarily add a handler with bubbling disabled if
you want to override the handlers below it in the stack.
Controlling the timestamp of records
Every record is timestamped with the current time, rendered in the timezone
given to the logger (date_default_timezone_get() by default). If you need to
decide what "now" means, for instance to freeze time in a test, pass any
PSR-20 clock to the logger:
<?php
use Monolog\Logger;
use Symfony\Component\Clock\MockClock;
$clock = new MockClock('2024-03-05 11:22:33');
$logger = new Logger('my_logger', [$handler], [], null, $clock);
// or on an existing logger, pass null to go back to reading the current time
$logger->setClock($clock);The clock only decides which instant is logged, the timezone configured on the
logger still decides how that instant is rendered. Passing a $datetime toLogger::addRecord() keeps taking precedence over the clock.
Adding extra data in the records
Monolog provides two different ways to add extra information along the simple
textual message.
Using the logging context
The first way is the context, allowing to pass an array of data along the
record:
<?php
$logger->info('Adding a new user', ['username' => 'Seldaek']);Simple handlers (like the StreamHandler for instance) will simply format
the array to a string but richer handlers can take advantage of the context
(FirePHP is able to display arrays in a pretty way for instance).
Using processors
The second way is to add extra data for all records by using a processor.
Processors can be any callable. They will get the record as parameter and
must return it after having eventually changed the extra part of it. Let's
write a processor adding some dummy data in the record:
<?php
$logger->pushProcessor(function ($record) {
$record->extra['dummy'] = 'Hello world!';
return $record;
});Monolog provides some built-in processors that can be used in your project.
Look at the dedicated chapter for the list.
Tip: processors can also be registered on a specific handler instead of
the logger to apply only for this handler.
Leveraging channels
Channels are a great way to identify to which part of the application a record
is related. This is useful in big applications (and is leveraged by
MonologBundle in Symfony).
Picture two loggers sharing a handler that writes to a single log file.
Channels would allow you to identify the logger that issued every record.
You can easily grep through the log files filtering this or that channel.
<?php
use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
// Create some handlers
$stream = new StreamHandler(__DIR__.'/my_app.log', Level::Debug);
$firephp = new FirePHPHandler();
// Create the main logger of the app
$logger = new Logger('my_logger');
$logger->pushHandler($stream);
$logger->pushHandler($firephp);
// Create a logger for the security-related stuff with a different channel
$securityLogger = new Logger('security');
$securityLogger->pushHandler($stream);
$securityLogger->pushHandler($firephp);
// Or clone the first one to only change the channel
$securityLogger = $logger->withName('security');Customizing the log format
In Monolog it's easy to customize the format of the logs written into files,
sockets, mails, databases and other handlers; by the use of "Formatters".
As mentioned before, a Formatter is attached to a Handler, and as a general convention, most of the handlers use the
$record->formattedproperty in the log record to store its formatted value.
You can choose between predefined formatter classes or write your own (e.g. a multiline text file for human-readable output).
Note:
A very useful formatter to look at, is the
LineFormatter.This formatter, as its name might indicate, is able to return a lineal string representation of the log record provided.
It is also capable to interpolate values from the log record, into the output format template used by the formatter to generate
the final result, and in order to do it, you need to provide the log record values you are interested in, in the output template
string using the form %value%, e.g: "'%context.foo% => %extra.foo%'" , in this example the values$record->context["foo"]
and$record->extra["foo"]will be rendered as part of the final result.
In the following example, we demonstrate how to:
- Create a
LineFormatterinstance and set a custom output format template. - Create a new Handler.
- Attach the Formatter to the Handler.
- Create a new Logger object.
- Attach the Handler to the Logger object.
<?php
// the default date format is "Y-m-d\TH:i:sP"
$dateFormat = "Y n j, g:i a";
// the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
// we now change the default output format according to our needs.
$output = "%datetime% > %level_name% > %message% %context% %extra%\n";
// finally, create a formatter
$formatter = new LineFormatter($output, $dateFormat);
// Create a handler
$stream = new StreamHandler(__DIR__.'/my_app.log', Level::Debug);
$stream->setFormatter($formatter);
// bind it to a logger object
$securityLogger = new Logger('security');
$securityLogger->pushHandler($stream);You may also reuse the same formatter between multiple handlers and share those
handlers between multiple loggers.
Long running processes and avoiding memory leaks
When logging lots of data or especially when running background workers which
are long-lived processes and do lots of logging over long periods of time, the
memory usage of buffered handlers like FingersCrossedHandler or BufferHandler
can rise quickly.
Monolog provides the ResettableInterface for this use case, allowing you to
end a log cycle and get things back to their initial state.
Calling $logger->reset(); means flushing/cleaning all buffers, resetting internal
state, and getting it back to a state in which it can receive log records again.
This is the conceptual equivalent of ending a web request, and can be done
between every background job you process, or whenever appropriate. It reduces memory
usage and also helps keep logs focused on the task at hand, avoiding log leaks
between different jobs.
Handlers, Formatters and Processors →
File: doc/02-handlers-formatters-processors.md
Handlers, Formatters and Processors
Handlers
Log to files and syslog
- StreamHandler: Logs records into any PHP stream, use this for log files.
- RotatingFileHandler: Logs records to a file and creates one log file per day.
It will also delete files older than$maxFiles. You should use
logrotate for high profile
setups though, this is just meant as a quick and dirty solution. - SyslogHandler: Logs records to the syslog.
- ErrorLogHandler: Logs records to PHP's
error_log()function. - FrankenPhpHandler: Logs records using FrankenPHP's
frankenphp_log()function. Requires running under the FrankenPHP SAPI. - ProcessHandler: Logs records to the STDIN of any process, specified by a command.
Send alerts and emails
- NativeMailerHandler: Sends emails using PHP's
mail()function. - SymfonyMailerHandler: Sends emails using a
symfony/mailerinstance. - PushoverHandler: Sends mobile notifications via the Pushover API.
- SlackWebhookHandler: Logs records to a Slack account using Slack Webhooks.
- SlackHandler: Logs records to a Slack account using the Slack API (complex setup).
- SendGridHandler: Sends emails via the SendGrid API.
- MandrillHandler: Sends emails via the
Mandrill APIusing aSwift_Messageinstance. - FleepHookHandler: Logs records to a Fleep conversation using Webhooks.
- IFTTTHandler: Notifies an IFTTT trigger with the log channel, level name and message.
- TelegramBotHandler: Logs records to a Telegram bot account.
- HipChatHandler: Logs records to a HipChat chat room using its API. Deprecated and removed in Monolog 2.0, use Slack handlers instead, see Atlassian's announcement
- SwiftMailerHandler: Sends emails using a
Swift_Mailerinstance. Deprecated and removed in Monolog 3.0. Use SymfonyMailerHandler instead.
Log specific servers and networked logging
- SocketHandler: Logs records to sockets, use this
for UNIX and TCP sockets. See an example. - AmqpHandler: Logs records to an AMQP compatible
server. Requires the php-amqp extension (1.0+) or
php-amqplib library. - GelfHandler: Logs records to a Graylog2 server.
Requires package graylog2/gelf-php. - ZendMonitorHandler: Logs records to the Zend Monitor present in Zend Server.
- NewRelicHandler: Logs records to a NewRelic application.
- LogglyHandler: Logs records to a Loggly account.
- RollbarHandler: Logs records to a Rollbar account.
- SyslogUdpHandler: Logs records to a remote Syslogd server.
- LogEntriesHandler: Logs records to a LogEntries account.
- InsightOpsHandler: Logs records to an InsightOps account.
- LogmaticHandler: Logs records to a Logmatic account.
- SqsHandler: Logs records to an AWS SQS queue.
- RavenHandler: Logs records to a Sentry server using
raven. Deprecated and removed in Monolog 2.0, use sentry/sentry 2.x and the Sentry\Monolog\Handler class instead.
Logging in development
- FirePHPHandler: Handler for FirePHP, providing
inlineconsolemessages within FireBug. - ChromePHPHandler: Handler for ChromePHP, providing
inlineconsolemessages within Chrome. - BrowserConsoleHandler: Handler to send logs to browser's Javascript
consolewith
no browser extension required. Most browsers supportingconsoleAPI are supported.
Log to databases
- RedisHandler: Logs records to a redis server's key via RPUSH.
- RedisPubSubHandler: Logs records to a redis server's channel via PUBLISH.
- MongoDBHandler: Handler to write records in MongoDB via a
Mongo extension connection. - CouchDBHandler: Logs records to a CouchDB server.
- DoctrineCouchDBHandler: Logs records to a CouchDB server via the Doctrine CouchDB ODM.
- ElasticaHandler: Logs records to an Elasticsearch server using ruflin/elastica.
- ElasticsearchHandler: Logs records to an Elasticsearch server.
- DynamoDbHandler: Logs records to a DynamoDB table with the AWS SDK.
Wrappers / Special Handlers
- FingersCrossedHandler: A very interesting wrapper. It takes a handler as
a parameter and will accumulate log records of all levels until a record
exceeds the defined severity level. At which point it delivers all records,
including those of lower severity, to the handler it wraps. This means that
until an error actually happens you will not see anything in your logs, but
when it happens you will have the full information, including debug and info
records. This provides you with all the information you need, but only when
you need it. - DeduplicationHandler: Useful if you are sending notifications or emails
when critical errors occur. It takes a handler as a parameter and will
accumulate log records of all levels until the end of the request (orflush()is called). At that point it delivers all records to the handler
it wraps, but only if the records are unique over a given time period
(60seconds by default). If the records are duplicates they are simply
discarded. The main use of this is in case of critical failure like if your
database is unreachable for example all your requests will fail and that
can result in a lot of notifications being sent. Adding this handler reduces
the amount of notifications to a manageable level. - WhatFailureGroupHandler: This handler extends the GroupHandler ignoring
exceptions raised by each child handler. This allows you to ignore issues
where a remote tcp connection may have died but you do not want your entire
application to crash and may wish to continue to log to other handlers. - FallbackGroupHandler: This handler extends the GroupHandler ignoring
exceptions raised by each child handler, until one has handled without throwing.
This allows you to ignore issues where a remote tcp connection may have died
but you do not want your entire application to crash and may wish to continue
to attempt logging to other handlers, until one does not throw an exception. - BufferHandler: This handler will buffer all the log records it receives
untilclose()is called at which point it will callhandleBatch()on the
handler it wraps with all the log messages at once. This is very useful to
send an email with all records at once for example instead of having one mail
for every log record. - GroupHandler: This handler groups other handlers. Every record received is
sent to all the handlers it is configured with. - FilterHandler: This handler only lets records of the given levels through
to the wrapped handler. - SamplingHandler: Wraps around another handler and lets you sample records
if you only want to store some of them. - NoopHandler: This handler handles anything by doing nothing. It does not stop
processing the rest of the stack. This can be used for testing, or to disable a handler when overriding a configuration. - NullHandler: Any record it can handle will be thrown away. This can be used
to put on top of an existing handler stack to disable it temporarily. - PsrHandler: Can be used to forward log records to an existing PSR-3 logger
- TestHandler: Used for testing, it records everything that is sent to it and
has accessors to read out the information. - HandlerWrapper: A simple handler wrapper you can inherit from to create
your own wrappers easily. - OverflowHandler: This handler will buffer all the log messages it
receives, up until a configured threshold of number of messages of a certain level is reached, after it will pass all
log messages to the wrapped handler. Useful for applying in batch processing when you're only interested in significant
failures instead of minor, single erroneous events. - LogMonsterHandler: A dead-man's switch wrapper. It watches
log records go by and expects to be fed at least a given number ($hunger) of
them before the process ends. If it stays hungry untilclose()(and was not
manually fed viafeed()), the monster gets angry and emits a complaint record
at the configured$angerLevelto the handler it wraps. This is useful to catch
cron jobs or workers that died before doing their expected work, or to make sure
every code path at least logs some records. Records carrying context can be made
to count as the only "real" food by enabling$wantsContextChips.
Formatters
- LineFormatter: Formats a log record into a one-line string.
- HtmlFormatter: Used to format log records into a human readable html table, mainly suitable for emails.
- NormalizerFormatter: Normalizes objects/resources down to strings so a record can easily be serialized/encoded.
- ScalarFormatter: Used to format log records into an associative array of scalar values.
- JsonFormatter: Encodes a log record into json.
- WildfireFormatter: Used to format log records into the Wildfire/FirePHP protocol, only useful for the FirePHPHandler.
- ChromePHPFormatter: Used to format log records into the ChromePHP format, only useful for the ChromePHPHandler.
- GelfMessageFormatter: Used to format log records into Gelf message instances, only useful for the GelfHandler.
- LogstashFormatter: Used to format log records into logstash event json, useful for any handler listed under inputs here.
- ElasticaFormatter: Used to format log records into an Elastica\Document object, only useful for the ElasticaHandler.
- ElasticsearchFormatter: Used to add index and type keys to log records, only useful for the ElasticsearchHandler.
- LogglyFormatter: Used to format log records into Loggly messages, only useful for the LogglyHandler.
- MongoDBFormatter: Converts \DateTime instances to \MongoDate and objects recursively to arrays, only useful with the MongoDBHandler.
- LogmaticFormatter: Used to format log records to Logmatic messages, only useful for the LogmaticHandler.
- FluentdFormatter: Used to format log records to Fluentd logs, only useful with the SocketHandler.
- GoogleCloudLoggingFormatter: Used to format log records for Google Cloud Logging. It works like a JsonFormatter with some minor tweaks.
- SyslogFormatter: Used to format log records in RFC 5424 / syslog format. This can be used to output a syslog-style file that can then be consumed by tools like lnav.
- RedactingFormatter: Wraps another formatter to mask sensitive data. It masks the value of any context/extra key matching a configured name (e.g.
password,token,authorization), removes the values of properties matching a#[SensitiveParameter]constructor parameter from the output, and runs configurable regex patterns over the wrapped formatter's output. Being a formatter, it runs after all processors, so it always sees the final record. Usage:new RedactingFormatter(new LineFormatter(), patterns: [RedactingFormatter::TOKEN_PATTERN]).
Processors
- PsrLogMessageProcessor: Processes a log record's message according to PSR-3 rules, replacing
{foo}with the value from$context['foo']. - LoadAverageProcessor: Adds the current system load average to a log record.
- ClosureContextProcessor: Allows delaying the creation of context data by setting a Closure in context which is called when the log record is used
- IntrospectionProcessor: Adds the line/file/class/method from which the log call originated.
- WebProcessor: Adds the current request URI, request method and client IP to a log record.
- MemoryUsageProcessor: Adds the current memory usage to a log record.
- MemoryPeakUsageProcessor: Adds the peak memory usage to a log record.
- ProcessIdProcessor: Adds the process id to a log record.
- UidProcessor: Adds a unique identifier to a log record.
- GitProcessor: Adds the current git branch and commit to a log record.
- MercurialProcessor: Adds the current hg branch and commit to a log record.
- TagProcessor: Adds an array of predefined tags to a log record.
- HostnameProcessor: Adds the current hostname to a log record.
Third Party Packages
Third party handlers, formatters and processors are
listed in the wiki. You
can also add your own there if you publish one.
← Usage | Utility classes →
File: doc/03-utilities.md
Utilities
Registry: The
Monolog\Registryclass lets you configure global loggers that you
can then statically access from anywhere. It is not really a best practice but can
help in some older codebases or for ease of use.ErrorHandler: The
Monolog\ErrorHandlerclass allows you to easily register
a Logger instance as an exception handler, error handler or fatal error handler.
PHP does not report where warnings, notices and deprecations come from, so if you
want to know which code triggered them, enable stack trace capturing, and make sure
your formatter outputs them (e.g.LineFormatter::includeStacktraces()):phpMonolog\ErrorHandler::register($logger)->captureStackTraces();SignalHandler: The
Monolog\SignalHandlerclass allows you to easily register
a Logger instance as a POSIX signal handler.ErrorLevelActivationStrategy: Activates a FingersCrossedHandler when a certain log
level is reached.ChannelLevelActivationStrategy: Activates a FingersCrossedHandler when a certain
log level is reached, depending on which channel received the log record.
← Handlers, Formatters and Processors | Extending Monolog →
File: doc/04-extending.md
Extending Monolog
Monolog is fully extensible, allowing you to adapt your logger to your needs.
Understanding log records
See the page about log records to learn what makes up
a log record before going further. This is essential to understand as all
Handlers/Formatters/Processors need to deal with log records in one way or
another.
Writing your own handler
Monolog provides many built-in handlers. But if the one you need does not
exist, you can write it and use it in your logger. The only requirement is
to implement Monolog\Handler\HandlerInterface.
Let's write a PDOHandler to log records to a database. We will extend the
abstract class provided by Monolog to keep things DRY.
<?php
use Monolog\Level;
use Monolog\Logger;
use Monolog\LogRecord;
use Monolog\Handler\AbstractProcessingHandler;
class PDOHandler extends AbstractProcessingHandler
{
private bool $initialized = false;
private PDO $pdo;
private PDOStatement $statement;
public function __construct(PDO $pdo, int|string|Level $level = Level::Debug, bool $bubble = true)
{
$this->pdo = $pdo;
parent::__construct($level, $bubble);
}
protected function write(LogRecord $record): void
{
if (!$this->initialized) {
$this->initialize();
}
$this->statement->execute(array(
'channel' => $record->channel,
'level' => $record->level,
'message' => $record->formatted,
'time' => $record->datetime->format('U'),
));
}
private function initialize()
{
$this->pdo->exec(
'CREATE TABLE IF NOT EXISTS monolog '
.'(channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)'
);
$this->statement = $this->pdo->prepare(
'INSERT INTO monolog (channel, level, message, time) VALUES (:channel, :level, :message, :time)'
);
$this->initialized = true;
}
}You can now use this handler in your logger:
<?php
$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite')));
// You can now use your logger
$logger->info('My logger is now ready');The Monolog\Handler\AbstractProcessingHandler class provides most of the
logic needed for the handler, including the use of processors and the formatting
of the record (which is why we use $record->formatted instead of $record->message).
File: doc/message-structure.md
Log message structure
Within monolog log messages are passed around as Monolog\LogRecord objects,
for example to processors or handlers.
The table below describes the properties available.
| property | type | description |
|---|---|---|
| message | string | The log message. When the PsrLogMessageProcessor is used this string may contain placeholders that will be replaced by variables from the context, e.g., "User {username} logged in" with ['username' => 'John'] as context will be written as "User John logged in". |
| level | Monolog\Level case | Severity of the log message. See log levels described in 01-usage.md. |
| context | array | Arbitrary data passed with the construction of the message. For example the username of the current user or their IP address. |
| channel | string | The channel this message was logged to. This is the name that was passed when the logger was created with new Logger('channel'). |
| datetime | Monolog\JsonSerializableDateTimeImmutable | Date and time when the message was logged. Class extends \DateTimeImmutable. |
| extra | array | A placeholder array where processors can put additional data. Always available, but empty if there are no processors registered. |
At first glance context and extra look very similar, and they are in the sense that they both carry arbitrary data that is related to the log message somehow.
The main difference is that context can be supplied in user land (it is the 3rd parameter to Psr\Log\LoggerInterface methods) whereas extra is internal only
and can be filled by processors. The reason processors write to extra and not to context is to prevent overriding any user-provided data in context.
All properties except extra are read-only.
Note: For BC reasons with Monolog 1 and 2 which used arrays,
LogRecordimplementsArrayAccessso you can access the above properties
using$record['message']for example, with the notable exception oflevel->getName()which must be referred to aslevel_namefor BC.
File: doc/sockets.md
Sockets Handler
This handler allows you to write your logs to sockets using fsockopen
or pfsockopen.
Persistent sockets are mainly useful in web environments where you gain some performance not closing/opening
the connections between requests.
You can use a unix:// prefix to access unix sockets and udp:// to open UDP sockets instead of the default TCP.
Basic Example
<?php
use Monolog\Logger;
use Monolog\Handler\SocketHandler;
// Create the logger
$logger = new Logger('my_logger');
// Create the handler
$handler = new SocketHandler('unix:///var/log/httpd_app_log.socket');
$handler->setPersistent(true);
// Now add the handler
$logger->pushHandler($handler, Level::Debug);
// You can now use your logger
$logger->info('My logger is now ready');In this example, using syslog-ng, you should see the log on the log server:
cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] []File: .github/dependabot.yml
version: 2
updates:
package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
cooldown:
default-days: 7package-ecosystem: "github-actions"
target-branch: "2.x"
directory: "/"
schedule:
interval: "monthly"
cooldown:
default-days: 7
File: .github/FUNDING.yml
github: [Seldaek]
tidelift: "packagist/monolog/monolog"
File: .github/SECURITY.md
Reporting a vulnerability
If you have found any issues that might have security implications,
please send a report privately to [email protected]
Do not report security reports publicly.
File: .github/ISSUE_TEMPLATE/Bug_Report.md
name: Bug Report about: Create a bug report labels: Bug
Monolog version 1|2|3?
Write your bug report here.
File: .github/ISSUE_TEMPLATE/Feature.md
name: Feature about: Suggest a new feature or enhancement labels: Feature
Write your suggestion here.
File: .github/ISSUE_TEMPLATE/Question.md
name: Question about: Ask a question regarding software usage labels: Support
Monolog version 1|2|3?
Write your question here.
File: .github/workflows/continuous-integration.yml
name: "Continuous Integration"
on:
- push
- pull_request
permissions:
contents: read
env:
COMPOSER_ROOT_VERSION: dev-main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
tests:
name: "CI (PHP ${{ matrix.php-version }}, ${{ matrix.dependencies }} deps)"
runs-on: "${{ matrix.operating-system }}"
strategy:
fail-fast: false
matrix:
php-version:
- "8.1"
- "8.2"
- "8.3"
- "8.4"
- "8.5"
dependencies: [highest]
composer-options: [""]
operating-system:
- "ubuntu-latest"
include:
- php-version: "8.1"
dependencies: lowest
operating-system: ubuntu-latest
- php-version: "8.5"
dependencies: highest
operating-system: ubuntu-latest
composer-options: "--ignore-platform-req=php+"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run CouchDB
timeout-minutes: 3
continue-on-error: true
uses: cobot/couchdb-action@716f8ccff36d9ee08e27f094d842ff8955f83c66 # v5.0.1
with:
couchdb-version: '2.3.1'
- name: Run MongoDB
uses: supercharge/mongodb-github-action@315db7fe45ac2880b7758f1933e6e5d59afd5e94 # 1.12.1
with:
mongodb-version: 5.0
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
extensions: mongodb, redis, amqp
tools: "composer:v2"
ini-values: "memory_limit=-1"
- name: Add require for mongodb/mongodb to make tests runnable
run: 'composer require mongodb/mongodb --dev --no-update'
- name: "Change dependencies"
run: |
composer require --no-update --no-interaction --dev elasticsearch/elasticsearch:^7
- uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
with:
dependency-versions: "${{ matrix.dependencies }}"
composer-options: "${{ matrix.composer-options }}"
- name: "Run tests"
if: "matrix.php-version >= '8.2'"
run: "composer exec phpunit -- --exclude-group Elasticsearch --exclude-group Elastica --exclude-group e2e"
- name: "Run tests"
if: "matrix.php-version == '8.1'"
run: "composer exec phpunit -- --exclude-group Elasticsearch,Elastica,e2e" tests-es-7:
name: "CI with ES ${{ matrix.es-version }} on PHP ${{ matrix.php-version }}"
needs: "tests"
runs-on: "${{ matrix.operating-system }}"
strategy:
fail-fast: false
matrix:
operating-system:
- "ubuntu-latest"
php-version:
- "8.1"
dependencies:
- "highest"
- "lowest"
es-version:
- "7.0.0"
- "7.17.0"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# required for elasticsearch
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Run Elasticsearch
timeout-minutes: 3
env:
ES_VERSION: ${{ matrix.es-version }}
run: |
# ES's bundled JDK crashes on the runner's cgroup v2 with a NPE in
# CgroupV2Subsystem (the bundled JDK predates the cgroup v2 fix).
# Run ES against the runner's patched JDK 11 instead, which both
# ES 7.0 and 7.17 support (ES <7.12 only reads JAVA_HOME, not ES_JAVA_HOME).
export JAVA_HOME="$JAVA_HOME_11_X64"
export ES_JAVA_HOME="$JAVA_HOME_11_X64"
curl -sL "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-${ES_VERSION}-linux-x86_64.tar.gz" | tar xz
ES_JAVA_OPTS="-Xms256m -Xmx512m" "elasticsearch-${ES_VERSION}/bin/elasticsearch" \
-E discovery.type=single-node \
-E xpack.security.enabled=false \
-d -p /tmp/es.pid
until curl -s http://127.0.0.1:9200 | grep -q '"tagline"'; do
if [ -f /tmp/es.pid ] && ! kill -0 "$(cat /tmp/es.pid)" 2>/dev/null; then
echo "Elasticsearch process died:"
cat "elasticsearch-${ES_VERSION}"/logs/*.log 2>/dev/null || true
exit 1
fi
echo "Waiting for Elasticsearch..."
sleep 2
done
echo "Elasticsearch is up"
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
extensions: mongodb, redis, amqp
tools: "composer:v2"
ini-values: "memory_limit=-1"
- name: "Change dependencies"
env:
ES_VERSION: ${{ matrix.es-version }}
run: "composer require --no-update --no-interaction --dev elasticsearch/elasticsearch:^$ES_VERSION"
- uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
with:
dependency-versions: "${{ matrix.dependencies }}"
- name: "Run tests"
run: "composer exec phpunit -- --group Elasticsearch,Elastica"
- name: "Run tests with psr/log 3"
if: "contains(matrix.dependencies, 'highest') && matrix.php-version >= '8.0'"
run: |
composer remove --no-update --dev graylog2/gelf-php ruflin/elastica elasticsearch/elasticsearch rollbar/rollbar
composer require --no-update --no-interaction --dev ruflin/elastica:^7 elasticsearch/elasticsearch:^7
composer require --no-update psr/log:^3
composer update
composer exec phpunit -- --group Elasticsearch,Elastica tests-es-8:
name: "CI with ES ${{ matrix.es-version }} on PHP ${{ matrix.php-version }}"
needs: "tests"
runs-on: "${{ matrix.operating-system }}"
strategy:
fail-fast: false
matrix:
operating-system:
- "ubuntu-latest"
php-version:
- "8.1"
dependencies:
- "highest"
- "lowest"
es-version:
- "8.0.0"
- "8.2.0"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# required for elasticsearch
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Run Elasticsearch
timeout-minutes: 3
env:
ES_VERSION: ${{ matrix.es-version }}
run: |
# ES 8's bundled JDK 17 crashes on the runner's cgroup v2 with a NPE
# in CgroupV2Subsystem (predates the cgroup v2 fix). Point ES at the
# runner's patched JDK 17 instead (ES 8 reads ES_JAVA_HOME).
export ES_JAVA_HOME="$JAVA_HOME_17_X64"
curl -sL "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-${ES_VERSION}-linux-x86_64.tar.gz" | tar xz
ES_JAVA_OPTS="-Xms256m -Xmx512m" "elasticsearch-${ES_VERSION}/bin/elasticsearch" \
-E discovery.type=single-node \
-E xpack.security.enabled=false \
-d -p /tmp/es.pid
until curl -s http://127.0.0.1:9200 | grep -q '"tagline"'; do
if [ -f /tmp/es.pid ] && ! kill -0 "$(cat /tmp/es.pid)" 2>/dev/null; then
echo "Elasticsearch process died:"
cat "elasticsearch-${ES_VERSION}"/logs/*.log 2>/dev/null || true
exit 1
fi
echo "Waiting for Elasticsearch..."
sleep 2
done
echo "Elasticsearch is up"
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
extensions: mongodb, redis, amqp
tools: "composer:v2"
ini-values: "memory_limit=-1"
- name: "Change dependencies"
run: |
composer remove --no-update --dev graylog2/gelf-php ruflin/elastica elasticsearch/elasticsearch rollbar/rollbar
composer require --no-update --no-interaction --dev elasticsearch/elasticsearch:^8 ruflin/elastica:^8
- uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
with:
dependency-versions: "${{ matrix.dependencies }}"
- name: "Run tests"
run: "composer exec phpunit -- --group Elasticsearch,Elastica"File: .github/workflows/frankenphp-e2e.yml
name: "FrankenPHP E2E"
on:
- push
- pull_request
permissions:
contents: read
env:
COMPOSER_ROOT_VERSION: dev-main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
e2e:
name: "FrankenPHP e2e"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
coverage: "none"
php-version: "8.4"
tools: "composer:v2"
ini-values: "memory_limit=-1"
- uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
with:
dependency-versions: "highest"
composer-options: "--ignore-platform-req=ext-mongodb"
- name: "Start FrankenPHP"
run: |
docker run -d --name monolog-frankenphp-e2e \
-v "$PWD":/app/source:ro \
-v "$PWD/tests/e2e/frankenphp/public":/app/public:ro \
-e SERVER_NAME=":8099" \
-p 8099:8099 \
dunglas/frankenphp:latest
- name: "Run FrankenPHP e2e test"
env:
MONOLOG_FRANKENPHP_E2E: "1"
run: vendor/bin/phpunit --group e2eFile: .github/workflows/lint.yml
name: "PHP Lint"
on:
- push
- pull_request
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
tests:
name: "Lint"
runs-on: ubuntu-latest
strategy:
matrix:
php-version:
- "8.1"
- "nightly"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: "${{ matrix.php-version }}"
coverage: none
- name: "Lint PHP files"
run: |
hasErrors=0
for f in $(find src/ tests/ -type f -name '*.php' ! -path '*/vendor/*' ! -path '*/Fixtures/*')
do
{ error="$(php -derror_reporting=-1 -ddisplay_errors=1 -l -f $f 2>&1 1>&3 3>&-)"; } 3>&1;
if [ "$error" != "" ]; then
while IFS= read -r line; do echo "::error file=$f::$line"; done <<< "$error"
hasErrors=1
fi
done
if [ $hasErrors -eq 1 ]; then
exit 1
fiFile: .github/workflows/phpstan.yml
name: "PHPStan"
on:
- push
- pull_request
permissions:
contents: read
env:
COMPOSER_ROOT_VERSION: dev-main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
tests:
name: "PHPStan"
runs-on: ubuntu-latest
strategy:
matrix:
php-version:
- "8.1"
- latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: "${{ matrix.php-version }}"
coverage: none
extensions: mongodb, redis, amqp
- name: Add require for mongodb/mongodb to make tests runnable
run: "composer require $COMPOSER_FLAGS mongodb/mongodb --dev --no-update"
- uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
with:
dependency-versions: highest
- name: Run PHPStan
run: composer phpstanFile: .github/workflows/zizmor.yml
name: GitHub Actions Security Analysis with zizmor ๐
on:
push:
branches:
- main
paths:
- '.github/.yml'
pull_request:
paths:
- '.github/.yml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
zizmor:
name: Run zizmor ๐
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run zizmor ๐
uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4
with:
advanced-security: false
annotations: true
persona: 'pedantic'