Yanz Mini Shell
[_]
[-]
[X]
[
HomeShell 1
] [
HomeShell 2
] [
Upload
] [
Command Shell
] [
Scripting
] [
About
]
[ Directory ] =>
/
home
admin
web
uyoxpress.com
public_html
Action
[*]
New File
[*]
New Folder
Sensitive File
[*]
/etc/passwd
[*]
/etc/shadow
[*]
/etc/resolv.conf
[
Delete
] [
Edit
] [
Rename
] [
Back
]
PK ! 1��d� � monolog/composer.jsonnu �[��� { "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": "j.boggiano@seld.be", "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", "php-amqplib/php-amqplib": "~2.4 || ^3", "phpstan/phpstan": "^1.9", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.4", "phpunit/phpunit": "^10.5.17", "predis/predis": "^1.1 || ^2", "ruflin/elastica": "^7", "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" }, "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 } } PK ! ��' ' monolog/LICENSEnu �[��� Copyright (c) 2011-2020 Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK ! S5 >� >� monolog/CHANGELOG.mdnu �[��� ### 3.6.0 (2024-04-12) * Added `LineFormatter->setBasePath(...)` that allows removing the project's path from the stack trace output (#1873) * Added `$includeExtra` option in `PsrHandler` to 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 `GelfMessageFormatter` together with the `AmqpHandler` (#1869) * Added ability to extend `GoogleCloudLoggingFormatter` (#1859) * Fixed `__toString` failures 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 `WithMonologChannel` attribute for integrators to use to configure autowiring (#1847) * Fixed log record `extra` data 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 `LoadAverageProcessor` to track one of the 1, 5 or 15min load averages (#1803) * Added support for priority to the `AsMonologProcessor` attribute (#1797) * Added `TelegramBotHandler` `topic`/`message_thread_id` support (#1802) * Fixed `FingersCrossedHandler` passthruLevel checking (#1801) * Fixed support of yearly and monthly rotation log file to rotate only once a month/year (#1805) * Fixed `TestHandler` method docs (#1794) * Fixed handling of falsey `display_errors` string 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 `ClosureContextProcessor` to 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_type` to `create` instead of the default `index` (#1766) * Added support for enum context values in PsrLogMessageProcessor (#1773) * Added graylog2/gelf-php 2.x support (#1747) * Improved `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739) * Fixed GitProcessor not filtering correctly based on Level (#1749) * Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791) * Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758) * Fixed infinite loop detection within Fibers (#1753) * Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781) ### 3.2.0 (2022-07-24) * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734) * Marked `Logger` `@final` as it should not be extended, prefer composition or talk to us if you are missing something * Added RFC 5424 level (`7` to `0`) support to `Logger::log` and `Logger::addRecord` to increase interoperability (#1723) * Added `SyslogFormatter` to output syslog-like files which can be consumed by tools like [lnav](https://lnav.org/) (#1689) * Added support for `__toString` for objects which are not json serializable in `JsonFormatter` (#1733) * Added `GoogleCloudLoggingFormatter` (#1719) * Added support for Predis 2.x (#1732) * Added `AmqpHandler->setExtraAttributes` to 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 `\n` or `\r` sequences (#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 `$datetime` parameter to `Logger::addRecord` as low level API to allow logging into the past or future (#1682) * Added `Logger::useLoggingLoopDetection` to 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\TestCase` class as `@internal` to 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\LevelName` enum does not exist anymore, use `Monolog\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](UPGRADE.md#300) 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\LogRecord` object](src/Monolog/LogRecord.php) 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 the `level` and `level_name` keys to be more backwards compatible and use simpler data types. - `FormatterInterface`, `HandlerInterface`, `ProcessorInterface`, etc. changed to contain `LogRecord $record` instead of `array $record` parameter types. If you want to support multiple Monolog versions this should be possible by type-hinting nothing, or `array|LogRecord` if 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 a `LogRecord` return type even where it would be applicable, but if you only support Monolog 3 in integration code I would recommend you use `LogRecord` return types wherever fitting to ensure forward compatibility as it may be added in Monolog 4. - Log levels are now enums [`Monolog\Level`](src/Monolog/Level.php) and [`Monolog\LevelName`](src/Monolog/LevelName.php) - 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 the `Monolog\Level` enum. e.g. instead of `Logger::WARNING` use `Level::Warning` if you need to pass the enum case to Monolog or one of its handlers, or `Level::Warning->value` if you need the integer value equal to what `Logger::WARNING` was giving you. - `Logger::getLevelName()` is now deprecated. ### 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 `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739) * Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791) * Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758) * Fixed infinite loop detection within Fibers (#1753) * Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781) ### 2.8.0 (2022-07-24) * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734) * Added RFC 5424 level (`7` to `0`) support to `Logger::log` and `Logger::addRecord` to increase interoperability (#1723) * Added support for `__toString` for objects which are not json serializable in `JsonFormatter` (#1733) * Added `GoogleCloudLoggingFormatter` (#1719) * Added support for Predis 2.x (#1732) * Added `AmqpHandler->setExtraAttributes` to 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 `\n` or `\r` sequences (#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 `$datetime` parameter to `Logger::addRecord` as low level API to allow logging into the past or future (#1682) * Added `Logger::useLoggingLoopDetection` to 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\TestCase` class as `@internal` to 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`, use `SymfonyMailerHandler` instead * 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 `callType` to IntrospectionProcessor (#1612) * Fixed AsMonologProcessor syntax to be compatible with PHP 7.2 (#1651) ### 2.4.0 (2022-03-14) * Added [`Monolog\LogRecord`](src/Monolog/LogRecord.php) interface that can be used to type-hint records like `array|\Monolog\LogRecord $record` to be forward compatible with the upcoming Monolog 3 changes * Added `includeStacktraces` constructor params to LineFormatter & JsonFormatter (#1603) * Added `persistent`, `timeout`, `writingTimeout`, `connectionTimeout`, `chunkSize` constructor params to SocketHandler and derivatives (#1600) * Added `AsMonologProcessor` PHP 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_agent` key 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 `@inheritDoc` annotations 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_SUBSTITUTE` to default json flags, so that invalid UTF8 characters now get converted to [�](https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character) instead of being converted from ISO-8859-15 to UTF8 as it was before, which was hardly a comprehensive solution * Added `$ignoreEmptyContextAndExtra` option to JsonFormatter to skip empty context/extra entirely from the output * Added `$parseMode`, `$disableWebPagePreview` and `$disableNotification` options 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](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](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](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](https://core.telegram.org/bots/api) 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](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 as `emerg`, `crit`, `err` and `warn` * 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](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 `$dateFormat` option to the PsrLogMessageProcessor which lets you format DateTime instances nicely * Added support for the PHP 7.x `mongodb` extension 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' `normalize` method, make sure you add the new `$depth = 0` argument to your function signature to avoid strict PHP warnings. * Added a `ResettableInterface` in order to reset/reset/clear/flush handlers and processors * Added a `ProcessorInterface` as 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 `contexts` context 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 `$ident` argument * 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->withName` to 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 `payload` context value in RollbarHandler * Added setRelease to RavenHandler to describe the application version, sent with every log * Added support for `fingerprint` context 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 `checksum` and `release` context/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 `$useSSL` option 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\Logger` class is now an instance of `Psr\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 `$flushOnOverflow` param 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 `server` and `referer` to 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 PK ! ,*C � � monolog/README.mdnu �[���  # Monolog - Logging for PHP [](https://github.com/Seldaek/monolog/actions) [](https://packagist.org/packages/monolog/monolog) [](https://packagist.org/packages/monolog/monolog) >**Note** This is the **documentation for Monolog 3.x**, if you are using older releases >see the documentation for [Monolog 2.x](https://github.com/Seldaek/monolog/blob/2.x/README.md) or [Monolog 1.x](https://github.com/Seldaek/monolog/blob/1.x/README.md) 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](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) 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. <div align="center"> <hr> <sup><b>Sponsored by:</b></sup> <br> <a href="https://betterstack.com"> <div> <img src="https://github.com/Seldaek/monolog/assets/183678/7de58ce0-2fa2-45c0-b3e8-e60cebb3c4cf" width="200" alt="Better Stack"> </div> <div> Better Stack lets you centralize, search, and visualize your logs. </div> </a> <br> <hr> </div> ## Installation Install the latest version with ```bash composer require monolog/monolog ``` ## Basic Usage ```php <?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](doc/01-usage.md) - [Handlers, Formatters and Processors](doc/02-handlers-formatters-processors.md) - [Utility Classes](doc/03-utilities.md) - [Extending Monolog](doc/04-extending.md) - [Log Record Structure](doc/message-structure.md) ## Support Monolog Financially Get supported Monolog and help fund the project with the [Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-monolog-monolog?utm_source=packagist-monolog-monolog&utm_medium=referral&utm_campaign=enterprise) or via [GitHub sponsorship](https://github.com/sponsors/Seldaek). 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](https://github.com/Seldaek/monolog/wiki/Third-Party-Packages). You can also add your own there if you publish one. ## About ### Requirements - Monolog `^3.0` works with PHP 8.1 or above. - Monolog `^2.5` works with PHP 7.2 or above. - Monolog `^1.25` works 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](https://github.com/Seldaek/monolog/issues) ### Framework Integrations - Frameworks and libraries using [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) can be used very easily with Monolog since it implements the interface. - [Symfony](http://symfony.com) comes out of the box with Monolog. - [Laravel](http://laravel.com/) comes out of the box with Monolog. - [Lumen](http://lumen.laravel.com/) comes out of the box with Monolog. - [PPI](https://github.com/ppi/framework) comes out of the box with Monolog. - [CakePHP](http://cakephp.org/) is usable with Monolog via the [cakephp-monolog](https://github.com/jadb/cakephp-monolog) plugin. - [Slim](http://www.slimframework.com/) is usable with Monolog via the [Slim-Monolog](https://github.com/Flynsarmy/Slim-Monolog) log writer. - [XOOPS 2.6](http://xoops.org/) comes out of the box with Monolog. - [Aura.Web_Project](https://github.com/auraphp/Aura.Web_Project) comes out of the box with Monolog. - [Nette Framework](http://nette.org/en/) is usable with Monolog via the [contributte/monolog](https://github.com/contributte/monolog) or [orisai/nette-monolog](https://github.com/orisai/nette-monolog) extensions. - [Proton Micro Framework](https://github.com/alexbilbie/Proton) comes out of the box with Monolog. - [FuelPHP](http://fuelphp.com/) comes out of the box with Monolog. - [Equip Framework](https://github.com/equip/framework) comes out of the box with Monolog. - [Yii 2](http://www.yiiframework.com/) is usable with Monolog via the [yii2-monolog](https://github.com/merorafael/yii2-monolog) or [yii2-psr-log-target](https://github.com/samdark/yii2-psr-log-target) plugins. - [Hawkbit Micro Framework](https://github.com/HawkBitPhp/hawkbit) comes out of the box with Monolog. - [SilverStripe 4](https://www.silverstripe.org/) comes out of the box with Monolog. - [Drupal](https://www.drupal.org/) is usable with Monolog via the [monolog](https://www.drupal.org/project/monolog) module. - [Aimeos ecommerce framework](https://aimeos.org/) is usable with Monolog via the [ai-monolog](https://github.com/aimeos/ai-monolog) extension. - [Magento](https://magento.com/) comes out of the box with Monolog. - [Spiral Framework](https://spiral.dev) comes out of the box with Monolog bridge. ### Author Jordi Boggiano - <j.boggiano@seld.be> - <http://twitter.com/seldaek><br /> See also the list of [contributors](https://github.com/Seldaek/monolog/contributors) who participated in this project. ### License Monolog is licensed under the MIT License - see the [LICENSE](LICENSE) file for details ### Acknowledgements This library is heavily inspired by Python's [Logbook](https://logbook.readthedocs.io/en/stable/) library, although most concepts have been adjusted to fit to the PHP world. PK ! ��a�| | 6 monolog/src/Monolog/Formatter/GelfMessageFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Level; use Gelf\Message; use Monolog\Utils; use Monolog\LogRecord; /** * Serializes a log message to GELF * @see http://docs.graylog.org/en/latest/pages/gelf.html * * @author Matt Lehner <mlehner@gmail.com> */ class GelfMessageFormatter extends NormalizerFormatter { protected const DEFAULT_MAX_LENGTH = 32766; /** * @var string the name of the system for the Gelf log message */ protected string $systemName; /** * @var string a prefix for 'extra' fields from the Monolog record (optional) */ protected string $extraPrefix; /** * @var string a prefix for 'context' fields from the Monolog record (optional) */ protected string $contextPrefix; /** * @var int max length per field */ protected int $maxLength; /** * Translates Monolog log levels to Graylog2 log priorities. */ private function getGraylog2Priority(Level $level): int { return match ($level) { Level::Debug => 7, Level::Info => 6, Level::Notice => 5, Level::Warning => 4, Level::Error => 3, Level::Critical => 2, Level::Alert => 1, Level::Emergency => 0, }; } /** * @throws \RuntimeException */ public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null) { if (!class_exists(Message::class)) { throw new \RuntimeException('Composer package graylog2/gelf-php is required to use Monolog\'s GelfMessageFormatter'); } parent::__construct('U.u'); $this->systemName = (null === $systemName || $systemName === '') ? (string) gethostname() : $systemName; $this->extraPrefix = null === $extraPrefix ? '' : $extraPrefix; $this->contextPrefix = $contextPrefix; $this->maxLength = null === $maxLength ? self::DEFAULT_MAX_LENGTH : $maxLength; } /** * @inheritDoc */ public function format(LogRecord $record): Message { $context = $extra = []; if (isset($record->context)) { /** @var mixed[] $context */ $context = parent::normalize($record->context); } if (isset($record->extra)) { /** @var mixed[] $extra */ $extra = parent::normalize($record->extra); } $message = new Message(); $message ->setTimestamp($record->datetime) ->setShortMessage($record->message) ->setHost($this->systemName) ->setLevel($this->getGraylog2Priority($record->level)); // message length + system name length + 200 for padding / metadata $len = 200 + strlen($record->message) + strlen($this->systemName); if ($len > $this->maxLength) { $message->setShortMessage(Utils::substr($record->message, 0, $this->maxLength)); } if (isset($record->channel)) { $message->setAdditional('facility', $record->channel); } foreach ($extra as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); $len = strlen($this->extraPrefix . $key . $val); if ($len > $this->maxLength) { $message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength)); continue; } $message->setAdditional($this->extraPrefix . $key, $val); } foreach ($context as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); $len = strlen($this->contextPrefix . $key . $val); if ($len > $this->maxLength) { $message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength)); continue; } $message->setAdditional($this->contextPrefix . $key, $val); } if (!$message->hasAdditional('file') && isset($context['exception']['file'])) { if (1 === preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { $message->setAdditional('file', $matches[1]); $message->setAdditional('line', $matches[2]); } } return $message; } } PK ! �- / monolog/src/Monolog/Formatter/HtmlFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Level; use Monolog\Utils; use Monolog\LogRecord; /** * Formats incoming records into an HTML table * * This is especially useful for html email logging * * @author Tiago Brito <tlfbrito@gmail.com> */ class HtmlFormatter extends NormalizerFormatter { /** * Translates Monolog log levels to html color priorities. */ protected function getLevelColor(Level $level): string { return match ($level) { Level::Debug => '#CCCCCC', Level::Info => '#28A745', Level::Notice => '#17A2B8', Level::Warning => '#FFC107', Level::Error => '#FD7E14', Level::Critical => '#DC3545', Level::Alert => '#821722', Level::Emergency => '#000000', }; } /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(?string $dateFormat = null) { parent::__construct($dateFormat); } /** * Creates an HTML table row * * @param string $th Row header content * @param string $td Row standard cell content * @param bool $escapeTd false if td content must not be html escaped */ protected function addRow(string $th, string $td = ' ', bool $escapeTd = true): string { $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8'); if ($escapeTd) { $td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>'; } return "<tr style=\"padding: 4px;text-align: left;\">\n<th style=\"vertical-align: top;background: #ccc;color: #000\" width=\"100\">$th:</th>\n<td style=\"padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000\">".$td."</td>\n</tr>"; } /** * Create a HTML h1 tag * * @param string $title Text to be in the h1 */ protected function addTitle(string $title, Level $level): string { $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8'); return '<h1 style="background: '.$this->getLevelColor($level).';color: #ffffff;padding: 5px;" class="monolog-output">'.$title.'</h1>'; } /** * Formats a log record. * * @return string The formatted record */ public function format(LogRecord $record): string { $output = $this->addTitle($record->level->getName(), $record->level); $output .= '<table cellspacing="1" width="100%" class="monolog-output">'; $output .= $this->addRow('Message', $record->message); $output .= $this->addRow('Time', $this->formatDate($record->datetime)); $output .= $this->addRow('Channel', $record->channel); if (\count($record->context) > 0) { $embeddedTable = '<table cellspacing="1" width="100%">'; foreach ($record->context as $key => $value) { $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value)); } $embeddedTable .= '</table>'; $output .= $this->addRow('Context', $embeddedTable, false); } if (\count($record->extra) > 0) { $embeddedTable = '<table cellspacing="1" width="100%">'; foreach ($record->extra as $key => $value) { $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value)); } $embeddedTable .= '</table>'; $output .= $this->addRow('Extra', $embeddedTable, false); } return $output.'</table>'; } /** * Formats a set of log records. * * @return string The formatted set of records */ public function formatBatch(array $records): string { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } /** * @param mixed $data */ protected function convertToString($data): string { if (null === $data || is_scalar($data)) { return (string) $data; } $data = $this->normalize($data); return Utils::jsonEncode($data, JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS, true); } } PK ! �[b� � 1 monolog/src/Monolog/Formatter/SyslogFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Level; use Monolog\LogRecord; /** * Serializes a log message according to RFC 5424 * * @author Dalibor Karlović <dalibor.karlovic@sigwin.hr> * @author Renat Gabdullin <renatobyj@gmail.com> */ class SyslogFormatter extends LineFormatter { private const SYSLOG_FACILITY_USER = 1; private const FORMAT = "<%extra.priority%>1 %datetime% %extra.hostname% %extra.app-name% %extra.procid% %channel% %extra.structured-data% %level_name%: %message% %context% %extra%\n"; private const NILVALUE = '-'; private string $hostname; private int $procid; public function __construct(private string $applicationName = self::NILVALUE) { parent::__construct(self::FORMAT, 'Y-m-d\TH:i:s.uP', true, true); $this->hostname = (string) gethostname(); $this->procid = (int) getmypid(); } public function format(LogRecord $record): string { $record->extra = $this->formatExtra($record); return parent::format($record); } /** * @param LogRecord $record * @return array<string, mixed> */ private function formatExtra(LogRecord $record): array { $extra = $record->extra; $extra['app-name'] = $this->applicationName; $extra['hostname'] = $this->hostname; $extra['procid'] = $this->procid; $extra['priority'] = self::calculatePriority($record->level); $extra['structured-data'] = self::NILVALUE; return $extra; } private static function calculatePriority(Level $level): int { return (self::SYSLOG_FACILITY_USER * 8) + $level->toRFC5424Level(); } } PK ! ˵�e% % 3 monolog/src/Monolog/Formatter/LogmaticFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\LogRecord; /** * Encodes message information into JSON in a format compatible with Logmatic. * * @author Julien Breux <julien.breux@gmail.com> */ class LogmaticFormatter extends JsonFormatter { protected const MARKERS = ["sourcecode", "php"]; protected string $hostname = ''; protected string $appName = ''; /** * @return $this */ public function setHostname(string $hostname): self { $this->hostname = $hostname; return $this; } /** * @return $this */ public function setAppName(string $appName): self { $this->appName = $appName; return $this; } /** * Appends the 'hostname' and 'appname' parameter for indexing by Logmatic. * * @see http://doc.logmatic.io/docs/basics-to-send-data * @see \Monolog\Formatter\JsonFormatter::format() */ public function normalizeRecord(LogRecord $record): array { $record = parent::normalizeRecord($record); if ($this->hostname !== '') { $record["hostname"] = $this->hostname; } if ($this->appName !== '') { $record["appname"] = $this->appName; } $record["@marker"] = static::MARKERS; return $record; } } PK ! ��� 1 monolog/src/Monolog/Formatter/LogglyFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\LogRecord; /** * Encodes message information into JSON in a format compatible with Loggly. * * @author Adam Pancutt <adam@pancutt.com> */ class LogglyFormatter extends JsonFormatter { /** * Overrides the default batch mode to new lines for compatibility with the * Loggly bulk API. */ public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = false) { parent::__construct($batchMode, $appendNewline); } /** * Appends the 'timestamp' parameter for indexing by Loggly. * * @see https://www.loggly.com/docs/automated-parsing/#json * @see \Monolog\Formatter\JsonFormatter::format() */ protected function normalizeRecord(LogRecord $record): array { $recordData = parent::normalizeRecord($record); $recordData["timestamp"] = $record->datetime->format("Y-m-d\TH:i:s.uO"); unset($recordData["datetime"]); return $recordData; } } PK ! R���6% 6% 5 monolog/src/Monolog/Formatter/NormalizerFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\DateTimeImmutable; use Monolog\Utils; use Throwable; use Monolog\LogRecord; /** * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets * * @author Jordi Boggiano <j.boggiano@seld.be> */ class NormalizerFormatter implements FormatterInterface { public const SIMPLE_DATE = "Y-m-d\TH:i:sP"; protected string $dateFormat; protected int $maxNormalizeDepth = 9; protected int $maxNormalizeItemCount = 1000; private int $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(?string $dateFormat = null) { $this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat; if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter'); } } /** * @inheritDoc */ public function format(LogRecord $record) { return $this->normalizeRecord($record); } /** * Normalize an arbitrary value to a scalar|array|null * * @return null|scalar|array<mixed[]|scalar|null> */ public function normalizeValue(mixed $data): mixed { return $this->normalize($data); } /** * @inheritDoc */ public function formatBatch(array $records) { foreach ($records as $key => $record) { $records[$key] = $this->format($record); } return $records; } public function getDateFormat(): string { return $this->dateFormat; } /** * @return $this */ public function setDateFormat(string $dateFormat): self { $this->dateFormat = $dateFormat; return $this; } /** * The maximum number of normalization levels to go through */ public function getMaxNormalizeDepth(): int { return $this->maxNormalizeDepth; } /** * @return $this */ public function setMaxNormalizeDepth(int $maxNormalizeDepth): self { $this->maxNormalizeDepth = $maxNormalizeDepth; return $this; } /** * The maximum number of items to normalize per level */ public function getMaxNormalizeItemCount(): int { return $this->maxNormalizeItemCount; } /** * @return $this */ public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): self { $this->maxNormalizeItemCount = $maxNormalizeItemCount; return $this; } /** * Enables `json_encode` pretty print. * * @return $this */ public function setJsonPrettyPrint(bool $enable): self { if ($enable) { $this->jsonEncodeOptions |= JSON_PRETTY_PRINT; } else { $this->jsonEncodeOptions &= ~JSON_PRETTY_PRINT; } return $this; } /** * Provided as extension point * * Because normalize is called with sub-values of context data etc, normalizeRecord can be * extended when data needs to be appended on the record array but not to other normalized data. * * @return array<mixed[]|scalar|null> */ protected function normalizeRecord(LogRecord $record): array { /** @var array<mixed> $normalized */ $normalized = $this->normalize($record->toArray()); return $normalized; } /** * @return null|scalar|array<mixed[]|scalar|null> */ protected function normalize(mixed $data, int $depth = 0): mixed { if ($depth > $this->maxNormalizeDepth) { return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'; } if (null === $data || is_scalar($data)) { if (is_float($data)) { if (is_infinite($data)) { return ($data > 0 ? '' : '-') . 'INF'; } if (is_nan($data)) { return 'NaN'; } } return $data; } if (is_array($data)) { $normalized = []; $count = 1; foreach ($data as $key => $value) { if ($count++ > $this->maxNormalizeItemCount) { $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items ('.count($data).' total), aborting normalization'; break; } $normalized[$key] = $this->normalize($value, $depth + 1); } return $normalized; } if ($data instanceof \DateTimeInterface) { return $this->formatDate($data); } if (is_object($data)) { if ($data instanceof Throwable) { return $this->normalizeException($data, $depth); } if ($data instanceof \JsonSerializable) { /** @var null|scalar|array<mixed[]|scalar|null> $value */ $value = $data->jsonSerialize(); } elseif (\get_class($data) === '__PHP_Incomplete_Class') { $accessor = new \ArrayObject($data); $value = (string) $accessor['__PHP_Incomplete_Class_Name']; } elseif (method_exists($data, '__toString')) { try { /** @var string $value */ $value = $data->__toString(); } catch (\Throwable) { // if the toString method is failing, use the default behavior /** @var null|scalar|array<mixed[]|scalar|null> $value */ $value = json_decode($this->toJson($data, true), true); } } else { // the rest is normalized by json encoding and decoding it /** @var null|scalar|array<mixed[]|scalar|null> $value */ $value = json_decode($this->toJson($data, true), true); } return [Utils::getClass($data) => $value]; } if (is_resource($data)) { return sprintf('[resource(%s)]', get_resource_type($data)); } return '[unknown('.gettype($data).')]'; } /** * @return mixed[] */ protected function normalizeException(Throwable $e, int $depth = 0) { if ($depth > $this->maxNormalizeDepth) { return ['Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization']; } if ($e instanceof \JsonSerializable) { return (array) $e->jsonSerialize(); } $data = [ 'class' => Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $e->getFile().':'.$e->getLine(), ]; if ($e instanceof \SoapFault) { if (isset($e->faultcode)) { $data['faultcode'] = $e->faultcode; } if (isset($e->faultactor)) { $data['faultactor'] = $e->faultactor; } if (isset($e->detail)) { if (is_string($e->detail)) { $data['detail'] = $e->detail; } elseif (is_object($e->detail) || is_array($e->detail)) { $data['detail'] = $this->toJson($e->detail, true); } } } $trace = $e->getTrace(); foreach ($trace as $frame) { if (isset($frame['file'], $frame['line'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; } } if (($previous = $e->getPrevious()) instanceof \Throwable) { $data['previous'] = $this->normalizeException($previous, $depth + 1); } return $data; } /** * Return the JSON representation of a value * * @param mixed $data * @throws \RuntimeException if encoding fails and errors are not ignored * @return string if encoding fails and ignoreErrors is true 'null' is returned */ protected function toJson($data, bool $ignoreErrors = false): string { return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors); } protected function formatDate(\DateTimeInterface $date): string { // in case the date format isn't custom then we defer to the custom DateTimeImmutable // formatting logic, which will pick the right format based on whether useMicroseconds is on if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof DateTimeImmutable) { return (string) $date; } return $date->format($this->dateFormat); } /** * @return $this */ public function addJsonEncodeOption(int $option): self { $this->jsonEncodeOptions |= $option; return $this; } /** * @return $this */ public function removeJsonEncodeOption(int $option): self { $this->jsonEncodeOptions &= ~$option; return $this; } } PK ! �|�� � 3 monolog/src/Monolog/Formatter/LogstashFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\LogRecord; /** * Serializes a log message to Logstash Event Format * * @see https://www.elastic.co/products/logstash * @see https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/Event.java * * @author Tim Mower <timothy.mower@gmail.com> */ class LogstashFormatter extends NormalizerFormatter { /** * @var string the name of the system for the Logstash log message, used to fill the @source field */ protected string $systemName; /** * @var string an application name for the Logstash log message, used to fill the @type field */ protected string $applicationName; /** * @var string the key for 'extra' fields from the Monolog record */ protected string $extraKey; /** * @var string the key for 'context' fields from the Monolog record */ protected string $contextKey; /** * @param string $applicationName The application that sends the data, used as the "type" field of logstash * @param string|null $systemName The system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine * @param string $extraKey The key for extra keys inside logstash "fields", defaults to extra * @param string $contextKey The key for context keys inside logstash "fields", defaults to context * * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(string $applicationName, ?string $systemName = null, string $extraKey = 'extra', string $contextKey = 'context') { // logstash requires a ISO 8601 format date with optional millisecond precision. parent::__construct('Y-m-d\TH:i:s.uP'); $this->systemName = $systemName === null ? (string) gethostname() : $systemName; $this->applicationName = $applicationName; $this->extraKey = $extraKey; $this->contextKey = $contextKey; } /** * @inheritDoc */ public function format(LogRecord $record): string { $recordData = parent::format($record); $message = [ '@timestamp' => $recordData['datetime'], '@version' => 1, 'host' => $this->systemName, ]; if (isset($recordData['message'])) { $message['message'] = $recordData['message']; } if (isset($recordData['channel'])) { $message['type'] = $recordData['channel']; $message['channel'] = $recordData['channel']; } if (isset($recordData['level_name'])) { $message['level'] = $recordData['level_name']; } if (isset($recordData['level'])) { $message['monolog_level'] = $recordData['level']; } if ('' !== $this->applicationName) { $message['type'] = $this->applicationName; } if (\count($recordData['extra']) > 0) { $message[$this->extraKey] = $recordData['extra']; } if (\count($recordData['context']) > 0) { $message[$this->contextKey] = $recordData['context']; } return $this->toJson($message) . "\n"; } } PK ! ��? f f 4 monolog/src/Monolog/Formatter/FormatterInterface.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\LogRecord; /** * Interface for formatters * * @author Jordi Boggiano <j.boggiano@seld.be> */ interface FormatterInterface { /** * Formats a log record. * * @param LogRecord $record A record to format * @return mixed The formatted record */ public function format(LogRecord $record); /** * Formats a set of log records. * * @param array<LogRecord> $records A set of records to format * @return mixed The formatted set of records */ public function formatBatch(array $records); } PK ! "�t�0 0 3 monolog/src/Monolog/Formatter/ElasticaFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Elastica\Document; use Monolog\LogRecord; /** * Format a log message into an Elastica Document * * @author Jelle Vink <jelle.vink@gmail.com> */ class ElasticaFormatter extends NormalizerFormatter { /** * @var string Elastic search index name */ protected string $index; /** * @var string|null Elastic search document type */ protected string|null $type; /** * @param string $index Elastic Search index name * @param ?string $type Elastic Search document type, deprecated as of Elastica 7 * * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(string $index, ?string $type) { // elasticsearch requires a ISO 8601 format date with optional millisecond precision. parent::__construct('Y-m-d\TH:i:s.uP'); $this->index = $index; $this->type = $type; } /** * @inheritDoc */ public function format(LogRecord $record) { $record = parent::format($record); return $this->getDocument($record); } public function getIndex(): string { return $this->index; } /** * @deprecated since Elastica 7 type has no effect */ public function getType(): string { /** @phpstan-ignore-next-line */ return $this->type; } /** * Convert a log message into an Elastica Document * * @param mixed[] $record */ protected function getDocument(array $record): Document { $document = new Document(); $document->setData($record); if (method_exists($document, 'setType')) { $document->setType($this->type); } $document->setIndex($this->index); return $document; } } PK ! ��T) ) 2 monolog/src/Monolog/Formatter/FluentdFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Utils; use Monolog\LogRecord; /** * Class FluentdFormatter * * Serializes a log message to Fluentd unix socket protocol * * Fluentd config: * * <source> * type unix * path /var/run/td-agent/td-agent.sock * </source> * * Monolog setup: * * $logger = new Monolog\Logger('fluent.tag'); * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock'); * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter()); * $logger->pushHandler($fluentHandler); * * @author Andrius Putna <fordnox@gmail.com> */ class FluentdFormatter implements FormatterInterface { /** * @var bool $levelTag should message level be a part of the fluentd tag */ protected bool $levelTag = false; /** * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(bool $levelTag = false) { if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter'); } $this->levelTag = $levelTag; } public function isUsingLevelsInTag(): bool { return $this->levelTag; } public function format(LogRecord $record): string { $tag = $record->channel; if ($this->levelTag) { $tag .= '.' . $record->level->toPsrLogLevel(); } $message = [ 'message' => $record->message, 'context' => $record->context, 'extra' => $record->extra, ]; if (!$this->levelTag) { $message['level'] = $record->level->value; $message['level_name'] = $record->level->getName(); } return Utils::jsonEncode([$tag, $record->datetime->getTimestamp(), $message]); } public function formatBatch(array $records): string { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } } PK ! uU� � / monolog/src/Monolog/Formatter/JsonFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Stringable; use Throwable; use Monolog\LogRecord; /** * Encodes whatever record data is passed to it as json * * This can be useful to log to databases or remote APIs * * @author Jordi Boggiano <j.boggiano@seld.be> */ class JsonFormatter extends NormalizerFormatter { public const BATCH_MODE_JSON = 1; public const BATCH_MODE_NEWLINES = 2; /** @var self::BATCH_MODE_* */ protected int $batchMode; protected bool $appendNewline; protected bool $ignoreEmptyContextAndExtra; protected bool $includeStacktraces = false; /** * @param self::BATCH_MODE_* $batchMode * * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = true, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = false) { $this->batchMode = $batchMode; $this->appendNewline = $appendNewline; $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra; $this->includeStacktraces = $includeStacktraces; parent::__construct(); } /** * The batch mode option configures the formatting style for * multiple records. By default, multiple records will be * formatted as a JSON-encoded array. However, for * compatibility with some API endpoints, alternative styles * are available. */ public function getBatchMode(): int { return $this->batchMode; } /** * True if newlines are appended to every formatted record */ public function isAppendingNewlines(): bool { return $this->appendNewline; } /** * @inheritDoc */ public function format(LogRecord $record): string { $normalized = parent::format($record); if (isset($normalized['context']) && $normalized['context'] === []) { if ($this->ignoreEmptyContextAndExtra) { unset($normalized['context']); } else { $normalized['context'] = new \stdClass; } } if (isset($normalized['extra']) && $normalized['extra'] === []) { if ($this->ignoreEmptyContextAndExtra) { unset($normalized['extra']); } else { $normalized['extra'] = new \stdClass; } } return $this->toJson($normalized, true) . ($this->appendNewline ? "\n" : ''); } /** * @inheritDoc */ public function formatBatch(array $records): string { return match ($this->batchMode) { static::BATCH_MODE_NEWLINES => $this->formatBatchNewlines($records), default => $this->formatBatchJson($records), }; } /** * @return $this */ public function includeStacktraces(bool $include = true): self { $this->includeStacktraces = $include; return $this; } /** * Return a JSON-encoded array of records. * * @phpstan-param LogRecord[] $records */ protected function formatBatchJson(array $records): string { return $this->toJson($this->normalize($records), true); } /** * Use new lines to separate records instead of a * JSON-encoded array. * * @phpstan-param LogRecord[] $records */ protected function formatBatchNewlines(array $records): string { $oldNewline = $this->appendNewline; $this->appendNewline = false; $formatted = array_map(fn (LogRecord $record) => $this->format($record), $records); $this->appendNewline = $oldNewline; return implode("\n", $formatted); } /** * Normalizes given $data. * * @return null|scalar|array<mixed[]|scalar|null|object>|object */ protected function normalize(mixed $data, int $depth = 0): mixed { if ($depth > $this->maxNormalizeDepth) { return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization'; } if (is_array($data)) { $normalized = []; $count = 1; foreach ($data as $key => $value) { if ($count++ > $this->maxNormalizeItemCount) { $normalized['...'] = 'Over '.$this->maxNormalizeItemCount.' items ('.count($data).' total), aborting normalization'; break; } $normalized[$key] = $this->normalize($value, $depth + 1); } return $normalized; } if (is_object($data)) { if ($data instanceof \DateTimeInterface) { return $this->formatDate($data); } if ($data instanceof Throwable) { return $this->normalizeException($data, $depth); } // if the object has specific json serializability we want to make sure we skip the __toString treatment below if ($data instanceof \JsonSerializable) { return $data; } if ($data instanceof Stringable) { return $data->__toString(); } return $data; } if (is_resource($data)) { return parent::normalize($data); } return $data; } /** * Normalizes given exception with or without its own stack trace based on * `includeStacktraces` property. * * @inheritDoc */ protected function normalizeException(Throwable $e, int $depth = 0): array { $data = parent::normalizeException($e, $depth); if (!$this->includeStacktraces) { unset($data['trace']); } return $data; } } PK ! wS��� � = monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use DateTimeInterface; use Monolog\LogRecord; /** * Encodes message information into JSON in a format compatible with Cloud logging. * * @see https://cloud.google.com/logging/docs/structured-logging * @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry * * @author Luís Cobucci <lcobucci@gmail.com> */ class GoogleCloudLoggingFormatter extends JsonFormatter { protected function normalizeRecord(LogRecord $record): array { $normalized = parent::normalizeRecord($record); // Re-key level for GCP logging $normalized['severity'] = $normalized['level_name']; $normalized['time'] = $record->datetime->format(DateTimeInterface::RFC3339_EXTENDED); // Remove keys that are not used by GCP unset($normalized['level'], $normalized['level_name'], $normalized['datetime']); return $normalized; } } PK ! D�7 7 2 monolog/src/Monolog/Formatter/MongoDBFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use MongoDB\BSON\Type; use MongoDB\BSON\UTCDateTime; use Monolog\Utils; use Monolog\LogRecord; /** * Formats a record for use with the MongoDBHandler. * * @author Florian Plattner <me@florianplattner.de> */ class MongoDBFormatter implements FormatterInterface { private bool $exceptionTraceAsString; private int $maxNestingLevel; private bool $isLegacyMongoExt; /** * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record->context is 2 * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings */ public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true) { $this->maxNestingLevel = max($maxNestingLevel, 0); $this->exceptionTraceAsString = $exceptionTraceAsString; $this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare((string) phpversion('mongodb'), '1.1.9', '<='); } /** * @inheritDoc * * @return mixed[] */ public function format(LogRecord $record): array { /** @var mixed[] $res */ $res = $this->formatArray($record->toArray()); return $res; } /** * @inheritDoc * * @return array<mixed[]> */ public function formatBatch(array $records): array { $formatted = []; foreach ($records as $key => $record) { $formatted[$key] = $this->format($record); } return $formatted; } /** * @param mixed[] $array * @return mixed[]|string Array except when max nesting level is reached then a string "[...]" */ protected function formatArray(array $array, int $nestingLevel = 0) { if ($this->maxNestingLevel > 0 && $nestingLevel > $this->maxNestingLevel) { return '[...]'; } foreach ($array as $name => $value) { if ($value instanceof \DateTimeInterface) { $array[$name] = $this->formatDate($value, $nestingLevel + 1); } elseif ($value instanceof \Throwable) { $array[$name] = $this->formatException($value, $nestingLevel + 1); } elseif (is_array($value)) { $array[$name] = $this->formatArray($value, $nestingLevel + 1); } elseif (is_object($value) && !$value instanceof Type) { $array[$name] = $this->formatObject($value, $nestingLevel + 1); } } return $array; } /** * @param mixed $value * @return mixed[]|string */ protected function formatObject($value, int $nestingLevel) { $objectVars = get_object_vars($value); $objectVars['class'] = Utils::getClass($value); return $this->formatArray($objectVars, $nestingLevel); } /** * @return mixed[]|string */ protected function formatException(\Throwable $exception, int $nestingLevel) { $formattedException = [ 'class' => Utils::getClass($exception), 'message' => $exception->getMessage(), 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine(), ]; if ($this->exceptionTraceAsString === true) { $formattedException['trace'] = $exception->getTraceAsString(); } else { $formattedException['trace'] = $exception->getTrace(); } return $this->formatArray($formattedException, $nestingLevel); } protected function formatDate(\DateTimeInterface $value, int $nestingLevel): UTCDateTime { if ($this->isLegacyMongoExt) { return $this->legacyGetMongoDbDateTime($value); } return $this->getMongoDbDateTime($value); } private function getMongoDbDateTime(\DateTimeInterface $value): UTCDateTime { return new UTCDateTime((int) floor(((float) $value->format('U.u')) * 1000)); } /** * This is needed to support MongoDB Driver v1.19 and below * * See https://github.com/mongodb/mongo-php-driver/issues/426 * * It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted */ private function legacyGetMongoDbDateTime(\DateTimeInterface $value): UTCDateTime { $milliseconds = floor(((float) $value->format('U.u')) * 1000); $milliseconds = (PHP_INT_SIZE == 8) //64-bit OS? ? (int) $milliseconds : (string) $milliseconds; return new UTCDateTime($milliseconds); } } PK ! ��e� � 3 monolog/src/Monolog/Formatter/WildfireFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Level; use Monolog\LogRecord; /** * Serializes a log message according to Wildfire's header requirements * * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> * @author Christophe Coevoet <stof@notk.org> * @author Kirill chEbba Chebunin <iam@chebba.org> */ class WildfireFormatter extends NormalizerFormatter { /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format * * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(?string $dateFormat = null) { parent::__construct($dateFormat); // http headers do not like non-ISO-8559-1 characters $this->removeJsonEncodeOption(JSON_UNESCAPED_UNICODE); } /** * Translates Monolog log levels to Wildfire levels. * * @return 'LOG'|'INFO'|'WARN'|'ERROR' */ private function toWildfireLevel(Level $level): string { return match ($level) { Level::Debug => 'LOG', Level::Info => 'INFO', Level::Notice => 'INFO', Level::Warning => 'WARN', Level::Error => 'ERROR', Level::Critical => 'ERROR', Level::Alert => 'ERROR', Level::Emergency => 'ERROR', }; } /** * @inheritDoc */ public function format(LogRecord $record): string { // Retrieve the line and file if set and remove them from the formatted extra $file = $line = ''; if (isset($record->extra['file'])) { $file = $record->extra['file']; unset($record->extra['file']); } if (isset($record->extra['line'])) { $line = $record->extra['line']; unset($record->extra['line']); } $message = ['message' => $record->message]; $handleError = false; if (count($record->context) > 0) { $message['context'] = $this->normalize($record->context); $handleError = true; } if (count($record->extra) > 0) { $message['extra'] = $this->normalize($record->extra); $handleError = true; } if (count($message) === 1) { $message = reset($message); } if (is_array($message) && isset($message['context']['table'])) { $type = 'TABLE'; $label = $record->channel .': '. $record->message; $message = $message['context']['table']; } else { $type = $this->toWildfireLevel($record->level); $label = $record->channel; } // Create JSON object describing the appearance of the message in the console $json = $this->toJson([ [ 'Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label, ], $message, ], $handleError); // The message itself is a serialization of the above JSON object + it's length return sprintf( '%d|%s|', strlen($json), $json ); } /** * @inheritDoc * * @phpstan-return never */ public function formatBatch(array $records) { throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); } /** * @inheritDoc * * @return null|scalar|array<mixed[]|scalar|null>|object */ protected function normalize(mixed $data, int $depth = 0): mixed { if (is_object($data) && !$data instanceof \DateTimeInterface) { return $data; } return parent::normalize($data, $depth); } } PK ! Rb�u� � 8 monolog/src/Monolog/Formatter/ElasticsearchFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use DateTimeInterface; use Monolog\LogRecord; /** * Format a log message into an Elasticsearch record * * @author Avtandil Kikabidze <akalongman@gmail.com> */ class ElasticsearchFormatter extends NormalizerFormatter { /** * @var string Elasticsearch index name */ protected string $index; /** * @var string Elasticsearch record type */ protected string $type; /** * @param string $index Elasticsearch index name * @param string $type Elasticsearch record type * * @throws \RuntimeException If the function json_encode does not exist */ public function __construct(string $index, string $type) { // Elasticsearch requires an ISO 8601 format date with optional millisecond precision. parent::__construct(DateTimeInterface::ISO8601); $this->index = $index; $this->type = $type; } /** * @inheritDoc */ public function format(LogRecord $record) { $record = parent::format($record); return $this->getDocument($record); } /** * Getter index */ public function getIndex(): string { return $this->index; } /** * Getter type */ public function getType(): string { return $this->type; } /** * Convert a log message into an Elasticsearch record * * @param mixed[] $record Log message * @return mixed[] */ protected function getDocument(array $record): array { $record['_index'] = $this->index; $record['_type'] = $this->type; return $record; } } PK ! � y�� � 3 monolog/src/Monolog/Formatter/FlowdockFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\LogRecord; /** * formats the record to be used in the FlowdockHandler * * @author Dominik Liebler <liebler.dominik@gmail.com> * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockFormatter implements FormatterInterface { private string $source; private string $sourceEmail; public function __construct(string $source, string $sourceEmail) { $this->source = $source; $this->sourceEmail = $sourceEmail; } /** * @inheritDoc * * @return mixed[] */ public function format(LogRecord $record): array { $tags = [ '#logs', '#' . $record->level->toPsrLogLevel(), '#' . $record->channel, ]; foreach ($record->extra as $value) { $tags[] = '#' . $value; } $subject = sprintf( 'in %s: %s - %s', $this->source, $record->level->getName(), $this->getShortMessage($record->message) ); return [ 'source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record->message, 'tags' => $tags, 'project' => $this->source, ]; } /** * @inheritDoc * * @return mixed[][] */ public function formatBatch(array $records): array { $formatted = []; foreach ($records as $record) { $formatted[] = $this->format($record); } return $formatted; } public function getShortMessage(string $message): string { static $hasMbString; if (null === $hasMbString) { $hasMbString = function_exists('mb_strlen'); } $maxLength = 45; if ($hasMbString) { if (mb_strlen($message, 'UTF-8') > $maxLength) { $message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...'; } } else { if (strlen($message) > $maxLength) { $message = substr($message, 0, $maxLength - 4) . ' ...'; } } return $message; } } PK ! ����� � 4 monolog/src/Monolog/Formatter/ChromePHPFormatter.phpnu �[��� <?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Level; use Monolog\LogRecord; /** * Formats a log message according to the ChromePHP array format * * @author Christophe Coevoet <stof@notk.org> */ class ChromePHPFormatter implements FormatterInterface { /** * Translates Monolog log levels to Wildfire levels. * * @return 'log'|'info'|'warn'|'error' */ private function toWildfireLevel(Level $level): string { return match ($level) { Level::Debug => 'log', Level::Info => 'info', Level::Notice => 'info', Level::Warning => 'warn', Level::Error => 'error', Level::Critical => 'error', Level::Alert => 'error', Level::Emergency => 'error', }; } /** * @inheritDoc */ public function format(LogRecord $record) { // Retrieve the line and file if set and remove them from the formatted extra $backtrace = 'unknown'; if (isset($record->extra['file'], $record->extra['line'])) { $backtrace = $record->extra['file'].' : '.$record->extra['line']; unset($record->extra['file'], $record->extra['line']); } $message = ['message' => $record->message]; if (\count($record->context) > 0) { $message['context'] = $record->context; } if (\count($record->extra) > 0) { $message['extra'] = $record->extra; } if (count($message) === 1) { $message = reset($message); } return [ $record->channel, $message, $backtrace, $this->toWildfireLevel($record->level), ]; } /** * @inheritDoc */ public function formatBatch(array $records) { $formatted = []; foreach ($records as $record) { $formatted[] = $this->format($record); } return $formatted; } } PK ! �Ot&