作者 王智

支付composer

正在显示 84 个修改的文件 包含 1331 行增加1412 行删除

要显示太多修改。

为保证性能只显示 84 of 84+ 个文件。

... ... @@ -27,7 +27,9 @@
"ext-json": "*",
"ext-curl": "*",
"ext-pdo": "*",
"overtrue/wechat": "~3.1"
"overtrue/wechat": "~3.1",
"symfony/event-dispatcher": "4.3",
"monolog/monolog": "1.22"
},
"config": {
"preferred-install": "dist"
... ...
... ... @@ -7,8 +7,8 @@ $baseDir = dirname($vendorDir);
return array(
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
... ...
... ... @@ -13,9 +13,11 @@ return array(
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'),
'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
'Symfony\\Bridge\\PsrHttpMessage\\' => array($vendorDir . '/symfony/psr-http-message-bridge'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
... ...
... ... @@ -8,8 +8,8 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1
{
public static $files = array (
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
... ... @@ -91,9 +91,11 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
'Symfony\\Contracts\\EventDispatcher\\' => 34,
'Symfony\\Component\\VarExporter\\' => 30,
'Symfony\\Component\\HttpFoundation\\' => 33,
'Symfony\\Component\\Finder\\' => 25,
'Symfony\\Component\\EventDispatcher\\' => 34,
'Symfony\\Bridge\\PsrHttpMessage\\' => 30,
),
'P' =>
... ... @@ -162,6 +164,10 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
),
'Symfony\\Contracts\\EventDispatcher\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts',
),
'Symfony\\Component\\VarExporter\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/var-exporter',
... ... @@ -174,6 +180,10 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1
array (
0 => __DIR__ . '/..' . '/symfony/finder',
),
'Symfony\\Component\\EventDispatcher\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/event-dispatcher',
),
'Symfony\\Bridge\\PsrHttpMessage\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/psr-http-message-bridge',
... ...
... ... @@ -531,17 +531,17 @@
},
{
"name": "monolog/monolog",
"version": "1.25.5",
"version_normalized": "1.25.5.0",
"version": "1.22.0",
"version_normalized": "1.22.0.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "1817faadd1846cd08be9a49e905dc68823bc38c0"
"reference": "bad29cb8d18ab0315e6c477751418a82c850d558"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/1817faadd1846cd08be9a49e905dc68823bc38c0",
"reference": "1817faadd1846cd08be9a49e905dc68823bc38c0",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558",
"reference": "bad29cb8d18ab0315e6c477751418a82c850d558",
"shasum": "",
"mirrors": [
{
... ... @@ -561,13 +561,14 @@
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"graylog2/gelf-php": "~1.0",
"jakub-onderka/php-parallel-lint": "0.9",
"php-amqplib/php-amqplib": "~2.4",
"php-console/php-console": "^3.1.3",
"php-parallel-lint/php-parallel-lint": "^1.0",
"phpunit/phpunit": "~4.5",
"phpunit/phpunit-mock-objects": "2.3.0",
"ruflin/elastica": ">=0.90 <3.0",
"sentry/sentry": "^0.13",
"swiftmailer/swiftmailer": "^5.3|^6.0"
"swiftmailer/swiftmailer": "~5.3"
},
"suggest": {
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
... ... @@ -582,7 +583,7 @@
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"sentry/sentry": "Allow sending log messages to a Sentry server"
},
"time": "2020-07-23T08:35:51+00:00",
"time": "2016-11-26T00:15:39+00:00",
"type": "library",
"extra": {
"branch-alias": {
... ... @@ -612,16 +613,6 @@
"log",
"logging",
"psr-3"
],
"funding": [
{
"url": "https://github.com/Seldaek",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
"type": "tidelift"
}
]
},
{
... ... @@ -1432,6 +1423,168 @@
"description": "A polyfill for getallheaders."
},
{
"name": "symfony/event-dispatcher",
"version": "v4.3.0",
"version_normalized": "4.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "c71314cd3b9420b732e1526f33a24eff5430b5b3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c71314cd3b9420b732e1526f33a24eff5430b5b3",
"reference": "c71314cd3b9420b732e1526f33a24eff5430b5b3",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^7.1.3",
"symfony/event-dispatcher-contracts": "^1.1"
},
"conflict": {
"symfony/dependency-injection": "<3.4"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
"symfony/event-dispatcher-implementation": "1.1"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/expression-language": "~3.4|~4.0",
"symfony/http-foundation": "^3.4|^4.0",
"symfony/service-contracts": "^1.1",
"symfony/stopwatch": "~3.4|~4.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"time": "2019-05-28T07:50:59+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.3-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v1.1.9",
"version_normalized": "1.1.9.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/84e23fdcd2517bf37aecbd16967e83f0caee25a7",
"reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1.3"
},
"suggest": {
"psr/event-dispatcher": "",
"symfony/event-dispatcher-implementation": ""
},
"time": "2020-07-06T13:19:58+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Contracts\\EventDispatcher\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to dispatching event",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
]
},
{
"name": "symfony/finder",
"version": "v4.4.14",
"version_normalized": "4.4.14.0",
... ...
<?php
$header = <<<EOF
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.
EOF;
$finder = Symfony\CS\Finder::create()
->files()
->name('*.php')
->exclude('Fixtures')
->in(__DIR__.'/src')
->in(__DIR__.'/tests')
;
return Symfony\CS\Config::create()
->setUsingCache(true)
//->setUsingLinter(false)
->setRiskyAllowed(true)
->setRules(array(
'@PSR2' => true,
'binary_operator_spaces' => true,
'blank_line_before_return' => true,
'header_comment' => array('header' => $header),
'include' => true,
'long_array_syntax' => true,
'method_separation' => true,
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_blank_lines_between_uses' => true,
'no_duplicate_semicolons' => true,
'no_extra_consecutive_blank_lines' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unused_imports' => true,
'object_operator_without_whitespace' => true,
'phpdoc_align' => true,
'phpdoc_indent' => true,
'phpdoc_no_access' => true,
'phpdoc_no_package' => true,
'phpdoc_order' => true,
'phpdoc_scalar' => true,
'phpdoc_trim' => true,
'phpdoc_type_to_var' => true,
'psr0' => true,
'single_blank_line_before_namespace' => true,
'spaces_cast' => true,
'standardize_not_equals' => true,
'ternary_operator_spaces' => true,
'trailing_comma_in_multiline_array' => true,
'whitespacy_lines' => true,
))
->finder($finder)
;
... ...
### 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 NormalizerHandler 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
... ...
... ... @@ -2,6 +2,7 @@
[![Total Downloads](https://img.shields.io/packagist/dt/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
[![Latest Stable Version](https://img.shields.io/packagist/v/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
[![Reference Status](https://www.versioneye.com/php/monolog:monolog/reference_badge.svg)](https://www.versioneye.com/php/monolog:monolog/references)
Monolog sends your logs to files, sockets, inboxes, databases and various
... ... @@ -90,5 +91,5 @@ Monolog is licensed under the MIT License - see the `LICENSE` file for details
### Acknowledgements
This library is heavily inspired by Python's [Logbook](https://logbook.readthedocs.io/en/stable/)
This library is heavily inspired by Python's [Logbook](http://packages.python.org/Logbook/)
library, although most concepts have been adjusted to fit to the PHP world.
... ...
... ... @@ -24,10 +24,12 @@
"doctrine/couchdb": "~1.0@dev",
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"php-amqplib/php-amqplib": "~2.4",
"swiftmailer/swiftmailer": "^5.3|^6.0",
"swiftmailer/swiftmailer": "~5.3",
"php-console/php-console": "^3.1.3",
"php-parallel-lint/php-parallel-lint": "^1.0"
"phpunit/phpunit-mock-objects": "2.3.0",
"jakub-onderka/php-parallel-lint": "0.9"
},
"_": "phpunit/phpunit-mock-objects required in 2.3.0 due to https://github.com/sebastianbergmann/phpunit-mock-objects/issues/223 - needs hhvm 3.8+ on travis",
"suggest": {
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"sentry/sentry": "Allow sending log messages to a Sentry server",
... ... @@ -57,9 +59,8 @@
},
"scripts": {
"test": [
"parallel-lint . --exclude vendor --exclude src/Monolog/Handler/FormattableHandlerInterface.php --exclude src/Monolog/Handler/FormattableHandlerTrait.php --exclude src/Monolog/Handler/ProcessableHandlerInterface.php --exclude src/Monolog/Handler/ProcessableHandlerTrait.php",
"parallel-lint . --exclude vendor",
"phpunit"
]
},
"lock": false
}
}
... ...
# Using Monolog
- [Installation](#installation)
- [Core Concepts](#core-concepts)
- [Log Levels](#log-levels)
- [Configuring a logger](#configuring-a-logger)
- [Adding extra data in the records](#adding-extra-data-in-the-records)
- [Leveraging channels](#leveraging-channels)
- [Customizing the log format](#customizing-the-log-format)
## Installation
Monolog is available on Packagist ([monolog/monolog](http://packagist.org/packages/monolog/monolog))
and as such installable via [Composer](http://getcomposer.org/).
```bash
composer require monolog/monolog
```
If you do not use Composer, you can grab the code from GitHub, and use any
PSR-0 compatible autoloader (e.g. the [Symfony2 ClassLoader component](https://github.com/symfony/ClassLoader))
to load Monolog classes.
## Core Concepts
Every `Logger` instance has a channel (name) and a stack of handlers. Whenever
you add a record to the logger, it traverses the handler stack. Each handler
decides whether it fully handled the record, and if so, the propagation of the
record ends there.
This allows for flexible logging setups, for example having a `StreamHandler` at
the bottom of the stack that will log anything to disk, and on top of that add
a `MailHandler` that will send emails only when an error message is logged.
Handlers also have a `$bubble` property which defines whether they block the
record or not if they handled it. In this example, setting the `MailHandler`'s
`$bubble` argument to false means that records handled by the `MailHandler` will
not propagate to the `StreamHandler` anymore.
You can create many `Logger`s, each defining a channel (e.g.: db, request,
router, ..) and each of them combining various handlers, which can be shared
or not. The channel is reflected in the logs and allows you to easily see or
filter records.
Each Handler also has a Formatter, a default one with settings that make sense
will be created if you don't set one. The formatters normalize and format
incoming records so that they can be used by the handlers to output useful
information.
Custom severity levels are not available. Only the eight
[RFC 5424](http://tools.ietf.org/html/rfc5424) levels (debug, info, notice,
warning, error, critical, alert, emergency) are present for basic filtering
purposes, but for sorting and other use cases that would require
flexibility, you should add Processors to the Logger that can add extra
information (tags, user ip, ..) to the records before they are handled.
## Log Levels
Monolog supports the logging levels described by [RFC 5424](http://tools.ietf.org/html/rfc5424).
- **DEBUG** (100): Detailed debug information.
- **INFO** (200): Interesting events. Examples: User logs in, SQL logs.
- **NOTICE** (250): Normal but significant events.
- **WARNING** (300): Exceptional occurrences that are not errors. Examples:
Use of deprecated APIs, poor use of an API, undesirable things that are not
necessarily wrong.
- **ERROR** (400): Runtime errors that do not require immediate action but
should typically be logged and monitored.
- **CRITICAL** (500): Critical conditions. Example: Application component
unavailable, unexpected exception.
- **ALERT** (550): Action must be taken immediately. Example: Entire website
down, database unavailable, etc. This should trigger the SMS alerts and wake
you up.
- **EMERGENCY** (600): Emergency: system is unusable.
## Configuring a logger
Here is a basic setup to log to a file and to firephp on the DEBUG level:
```php
<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
// Create the logger
$logger = new Logger('my_logger');
// Now add some handlers
$logger->pushHandler(new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG));
$logger->pushHandler(new FirePHPHandler());
// You can now use your logger
$logger->addInfo('My logger is now ready');
```
Let's explain it. The first step is to create the logger instance which will
be used in your code. The argument is a channel name, which is useful when
you use several loggers (see below for more details about it).
The logger itself does not know how to handle a record. It delegates it to
some handlers. The code above registers two handlers in the stack to allow
handling records in two different ways.
Note that the FirePHPHandler is called first as it is added on top of the
stack. This allows you to temporarily add a logger with bubbling disabled if
you want to override other configured loggers.
> If you use Monolog standalone and are looking for an easy way to
> configure many handlers, the [theorchard/monolog-cascade](https://github.com/theorchard/monolog-cascade)
> can help you build complex logging configs via PHP arrays, yaml or json configs.
## Adding extra data in the records
Monolog provides two different ways to add extra informations along the simple
textual message.
### Using the logging context
The first way is the context, allowing to pass an array of data along the
record:
```php
<?php
$logger->addInfo('Adding a new user', array('username' => 'Seldaek'));
```
Simple handlers (like the StreamHandler for instance) will simply format
the array to a string but richer handlers can take advantage of the context
(FirePHP is able to display arrays in pretty way for instance).
### Using processors
The second way is to add extra data for all records by using a processor.
Processors can be any callable. They will get the record as parameter and
must return it after having eventually changed the `extra` part of it. Let's
write a processor adding some dummy data in the record:
```php
<?php
$logger->pushProcessor(function ($record) {
$record['extra']['dummy'] = 'Hello world!';
return $record;
});
```
Monolog provides some built-in processors that can be used in your project.
Look at the [dedicated chapter](https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#processors) for the list.
> Tip: processors can also be registered on a specific handler instead of
the logger to apply only for this handler.
## Leveraging channels
Channels are a great way to identify to which part of the application a record
is related. This is useful in big applications (and is leveraged by
MonologBundle in Symfony2).
Picture two loggers sharing a handler that writes to a single log file.
Channels would allow you to identify the logger that issued every record.
You can easily grep through the log files filtering this or that channel.
```php
<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
// Create some handlers
$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG);
$firephp = new FirePHPHandler();
// Create the main logger of the app
$logger = new Logger('my_logger');
$logger->pushHandler($stream);
$logger->pushHandler($firephp);
// Create a logger for the security-related stuff with a different channel
$securityLogger = new Logger('security');
$securityLogger->pushHandler($stream);
$securityLogger->pushHandler($firephp);
// Or clone the first one to only change the channel
$securityLogger = $logger->withName('security');
```
## Customizing the log format
In Monolog it's easy to customize the format of the logs written into files,
sockets, mails, databases and other handlers. Most of the handlers use the
```php
$record['formatted']
```
value to be automatically put into the log device. This value depends on the
formatter settings. You can choose between predefined formatter classes or
write your own (e.g. a multiline text file for human-readable output).
To configure a predefined formatter class, just set it as the handler's field:
```php
// the default date format is "Y-m-d H:i:s"
$dateFormat = "Y n j, g:i a";
// the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
$output = "%datetime% > %level_name% > %message% %context% %extra%\n";
// finally, create a formatter
$formatter = new LineFormatter($output, $dateFormat);
// Create a handler
$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG);
$stream->setFormatter($formatter);
// bind it to a logger object
$securityLogger = new Logger('security');
$securityLogger->pushHandler($stream);
```
You may also reuse the same formatter between multiple handlers and share those
handlers between multiple loggers.
[Handlers, Formatters and Processors](02-handlers-formatters-processors.md) &rarr;
... ...
# Handlers, Formatters and Processors
- [Handlers](#handlers)
- [Log to files and syslog](#log-to-files-and-syslog)
- [Send alerts and emails](#send-alerts-and-emails)
- [Log specific servers and networked logging](#log-specific-servers-and-networked-logging)
- [Logging in development](#logging-in-development)
- [Log to databases](#log-to-databases)
- [Wrappers / Special Handlers](#wrappers--special-handlers)
- [Formatters](#formatters)
- [Processors](#processors)
- [Third Party Packages](#third-party-packages)
## Handlers
### Log to files and syslog
- _StreamHandler_: Logs records into any PHP stream, use this for log files.
- _RotatingFileHandler_: Logs records to a file and creates one logfile per day.
It will also delete files older than `$maxFiles`. You should use
[logrotate](http://linuxcommand.org/man_pages/logrotate8.html) for high profile
setups though, this is just meant as a quick and dirty solution.
- _SyslogHandler_: Logs records to the syslog.
- _ErrorLogHandler_: Logs records to PHP's
[`error_log()`](http://docs.php.net/manual/en/function.error-log.php) function.
### Send alerts and emails
- _NativeMailerHandler_: Sends emails using PHP's
[`mail()`](http://php.net/manual/en/function.mail.php) function.
- _SwiftMailerHandler_: Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance.
- _PushoverHandler_: Sends mobile notifications via the [Pushover](https://www.pushover.net/) API.
- _HipChatHandler_: Logs records to a [HipChat](http://hipchat.com) chat room using its API.
- _FlowdockHandler_: Logs records to a [Flowdock](https://www.flowdock.com/) account.
- _SlackHandler_: Logs records to a [Slack](https://www.slack.com/) account using the Slack API.
- _SlackbotHandler_: Logs records to a [Slack](https://www.slack.com/) account using the Slackbot incoming hook.
- _SlackWebhookHandler_: Logs records to a [Slack](https://www.slack.com/) account using Slack Webhooks.
- _MandrillHandler_: Sends emails via the Mandrill API using a [`Swift_Message`](http://swiftmailer.org/) instance.
- _FleepHookHandler_: Logs records to a [Fleep](https://fleep.io/) conversation using Webhooks.
- _IFTTTHandler_: Notifies an [IFTTT](https://ifttt.com/maker) trigger with the log channel, level name and message.
### Log specific servers and networked logging
- _SocketHandler_: Logs records to [sockets](http://php.net/fsockopen), use this
for UNIX and TCP sockets. See an [example](sockets.md).
- _AmqpHandler_: Logs records to an [amqp](http://www.amqp.org/) compatible
server. Requires the [php-amqp](http://pecl.php.net/package/amqp) extension (1.0+).
- _GelfHandler_: Logs records to a [Graylog2](http://www.graylog2.org) server.
- _CubeHandler_: Logs records to a [Cube](http://square.github.com/cube/) server.
- _RavenHandler_: Logs records to a [Sentry](http://getsentry.com/) server using
[raven](https://packagist.org/packages/raven/raven).
- _ZendMonitorHandler_: Logs records to the Zend Monitor present in Zend Server.
- _NewRelicHandler_: Logs records to a [NewRelic](http://newrelic.com/) application.
- _LogglyHandler_: Logs records to a [Loggly](http://www.loggly.com/) account.
- _RollbarHandler_: Logs records to a [Rollbar](https://rollbar.com/) account.
- _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server.
- _LogEntriesHandler_: Logs records to a [LogEntries](http://logentries.com/) account.
### Logging in development
- _FirePHPHandler_: Handler for [FirePHP](http://www.firephp.org/), providing
inline `console` messages within [FireBug](http://getfirebug.com/).
- _ChromePHPHandler_: Handler for [ChromePHP](http://www.chromephp.com/), providing
inline `console` messages within Chrome.
- _BrowserConsoleHandler_: Handler to send logs to browser's Javascript `console` with
no browser extension required. Most browsers supporting `console` API are supported.
- _PHPConsoleHandler_: Handler for [PHP Console](https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef), providing
inline `console` and notification popup messages within Chrome.
### Log to databases
- _RedisHandler_: Logs records to a [redis](http://redis.io) server.
- _MongoDBHandler_: Handler to write records in MongoDB via a
[Mongo](http://pecl.php.net/package/mongo) extension connection.
- _CouchDBHandler_: Logs records to a CouchDB server.
- _DoctrineCouchDBHandler_: Logs records to a CouchDB server via the Doctrine CouchDB ODM.
- _ElasticSearchHandler_: Logs records to an Elastic Search server.
- _DynamoDbHandler_: Logs records to a DynamoDB table with the [AWS SDK](https://github.com/aws/aws-sdk-php).
### Wrappers / Special Handlers
- _FingersCrossedHandler_: A very interesting wrapper. It takes a logger as
parameter and will accumulate log records of all levels until a record
exceeds the defined severity level. At which point it delivers all records,
including those of lower severity, to the handler it wraps. This means that
until an error actually happens you will not see anything in your logs, but
when it happens you will have the full information, including debug and info
records. This provides you with all the information you need, but only when
you need it.
- _DeduplicationHandler_: Useful if you are sending notifications or emails
when critical errors occur. It takes a logger as parameter and will
accumulate log records of all levels until the end of the request (or
`flush()` is called). At that point it delivers all records to the handler
it wraps, but only if the records are unique over a given time period
(60seconds by default). If the records are duplicates they are simply
discarded. The main use of this is in case of critical failure like if your
database is unreachable for example all your requests will fail and that
can result in a lot of notifications being sent. Adding this handler reduces
the amount of notifications to a manageable level.
- _WhatFailureGroupHandler_: This handler extends the _GroupHandler_ ignoring
exceptions raised by each child handler. This allows you to ignore issues
where a remote tcp connection may have died but you do not want your entire
application to crash and may wish to continue to log to other handlers.
- _BufferHandler_: This handler will buffer all the log records it receives
until `close()` is called at which point it will call `handleBatch()` on the
handler it wraps with all the log messages at once. This is very useful to
send an email with all records at once for example instead of having one mail
for every log record.
- _GroupHandler_: This handler groups other handlers. Every record received is
sent to all the handlers it is configured with.
- _FilterHandler_: This handler only lets records of the given levels through
to the wrapped handler.
- _SamplingHandler_: Wraps around another handler and lets you sample records
if you only want to store some of them.
- _NullHandler_: Any record it can handle will be thrown away. This can be used
to put on top of an existing handler stack to disable it temporarily.
- _PsrHandler_: Can be used to forward log records to an existing PSR-3 logger
- _TestHandler_: Used for testing, it records everything that is sent to it and
has accessors to read out the information.
- _HandlerWrapper_: A simple handler wrapper you can inherit from to create
your own wrappers easily.
## Formatters
- _LineFormatter_: Formats a log record into a one-line string.
- _HtmlFormatter_: Used to format log records into a human readable html table, mainly suitable for emails.
- _NormalizerFormatter_: Normalizes objects/resources down to strings so a record can easily be serialized/encoded.
- _ScalarFormatter_: Used to format log records into an associative array of scalar values.
- _JsonFormatter_: Encodes a log record into json.
- _WildfireFormatter_: Used to format log records into the Wildfire/FirePHP protocol, only useful for the FirePHPHandler.
- _ChromePHPFormatter_: Used to format log records into the ChromePHP format, only useful for the ChromePHPHandler.
- _GelfMessageFormatter_: Used to format log records into Gelf message instances, only useful for the GelfHandler.
- _LogstashFormatter_: Used to format log records into [logstash](http://logstash.net/) event json, useful for any handler listed under inputs [here](http://logstash.net/docs/latest).
- _ElasticaFormatter_: Used to format log records into an Elastica\Document object, only useful for the ElasticSearchHandler.
- _LogglyFormatter_: Used to format log records into Loggly messages, only useful for the LogglyHandler.
- _FlowdockFormatter_: Used to format log records into Flowdock messages, only useful for the FlowdockHandler.
- _MongoDBFormatter_: Converts \DateTime instances to \MongoDate and objects recursively to arrays, only useful with the MongoDBHandler.
## Processors
- _PsrLogMessageProcessor_: Processes a log record's message according to PSR-3 rules, replacing `{foo}` with the value from `$context['foo']`.
- _IntrospectionProcessor_: Adds the line/file/class/method from which the log call originated.
- _WebProcessor_: Adds the current request URI, request method and client IP to a log record.
- _MemoryUsageProcessor_: Adds the current memory usage to a log record.
- _MemoryPeakUsageProcessor_: Adds the peak memory usage to a log record.
- _ProcessIdProcessor_: Adds the process id to a log record.
- _UidProcessor_: Adds a unique identifier to a log record.
- _GitProcessor_: Adds the current git branch and commit to a log record.
- _TagProcessor_: Adds an array of predefined tags to a log record.
## 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.
&larr; [Usage](01-usage.md) | [Utility classes](03-utilities.md) &rarr;
... ...
# Utilities
- _Registry_: The `Monolog\Registry` class lets you configure global loggers that you
can then statically access from anywhere. It is not really a best practice but can
help in some older codebases or for ease of use.
- _ErrorHandler_: The `Monolog\ErrorHandler` class allows you to easily register
a Logger instance as an exception handler, error handler or fatal error handler.
- _ErrorLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log
level is reached.
- _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain
log level is reached, depending on which channel received the log record.
&larr; [Handlers, Formatters and Processors](02-handlers-formatters-processors.md) | [Extending Monolog](04-extending.md) &rarr;
... ...
# Extending Monolog
Monolog is fully extensible, allowing you to adapt your logger to your needs.
## Writing your own handler
Monolog provides many built-in handlers. But if the one you need does not
exist, you can write it and use it in your logger. The only requirement is
to implement `Monolog\Handler\HandlerInterface`.
Let's write a PDOHandler to log records to a database. We will extend the
abstract class provided by Monolog to keep things DRY.
```php
<?php
use Monolog\Logger;
use Monolog\Handler\AbstractProcessingHandler;
class PDOHandler extends AbstractProcessingHandler
{
private $initialized = false;
private $pdo;
private $statement;
public function __construct(PDO $pdo, $level = Logger::DEBUG, $bubble = true)
{
$this->pdo = $pdo;
parent::__construct($level, $bubble);
}
protected function write(array $record)
{
if (!$this->initialized) {
$this->initialize();
}
$this->statement->execute(array(
'channel' => $record['channel'],
'level' => $record['level'],
'message' => $record['formatted'],
'time' => $record['datetime']->format('U'),
));
}
private function initialize()
{
$this->pdo->exec(
'CREATE TABLE IF NOT EXISTS monolog '
.'(channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)'
);
$this->statement = $this->pdo->prepare(
'INSERT INTO monolog (channel, level, message, time) VALUES (:channel, :level, :message, :time)'
);
$this->initialized = true;
}
}
```
You can now use this handler in your logger:
```php
<?php
$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite')));
// You can now use your logger
$logger->addInfo('My logger is now ready');
```
The `Monolog\Handler\AbstractProcessingHandler` class provides most of the
logic needed for the handler, including the use of processors and the formatting
of the record (which is why we use ``$record['formatted']`` instead of ``$record['message']``).
&larr; [Utility classes](03-utilities.md)
... ...
Sockets Handler
===============
This handler allows you to write your logs to sockets using [fsockopen](http://php.net/fsockopen)
or [pfsockopen](http://php.net/pfsockopen).
Persistent sockets are mainly useful in web environments where you gain some performance not closing/opening
the connections between requests.
You can use a `unix://` prefix to access unix sockets and `udp://` to open UDP sockets instead of the default TCP.
Basic Example
-------------
```php
<?php
use Monolog\Logger;
use Monolog\Handler\SocketHandler;
// Create the logger
$logger = new Logger('my_logger');
// Create the handler
$handler = new SocketHandler('unix:///var/log/httpd_app_log.socket');
$handler->setPersistent(true);
// Now add the handler
$logger->pushHandler($handler, Logger::DEBUG);
// You can now use your logger
$logger->addInfo('My logger is now ready');
```
In this example, using syslog-ng, you should see the log on the log server:
cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] []
... ...
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Monolog Test Suite">
<directory>tests/Monolog/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/Monolog/</directory>
</whitelist>
</filter>
<php>
<ini name="date.timezone" value="UTC"/>
</php>
</phpunit>
... ...
... ... @@ -38,7 +38,6 @@ class ErrorHandler
private $hasFatalErrorHandler;
private $fatalLevel;
private $reservedMemory;
private $lastFatalTrace;
private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);
public function __construct(LoggerInterface $logger)
... ... @@ -59,9 +58,6 @@ class ErrorHandler
*/
public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null)
{
//Forces the autoloader to run for LogLevel. Fixes an autoload issue at compile-time on PHP5.3. See https://github.com/Seldaek/monolog/pull/929
class_exists('\\Psr\\Log\\LogLevel', true);
$handler = new static($logger);
if ($errorLevelMap !== false) {
$handler->registerErrorHandler($errorLevelMap);
... ... @@ -133,7 +129,7 @@ class ErrorHandler
{
$this->logger->log(
$this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel,
sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()),
sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()),
array('exception' => $e)
);
... ... @@ -157,13 +153,6 @@ class ErrorHandler
if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
$level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL;
$this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
} else {
// http://php.net/manual/en/function.debug-backtrace.php
// As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added.
// Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'.
$trace = debug_backtrace((PHP_VERSION_ID < 50306) ? 2 : DEBUG_BACKTRACE_IGNORE_ARGS);
array_shift($trace); // Exclude handleError from trace
$this->lastFatalTrace = $trace;
}
if ($this->previousErrorHandler === true) {
... ... @@ -185,7 +174,7 @@ class ErrorHandler
$this->logger->log(
$this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel,
'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace)
array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'])
);
if ($this->logger instanceof Logger) {
... ...
... ... @@ -11,8 +11,6 @@
namespace Monolog\Formatter;
use Monolog\Utils;
/**
* Class FluentdFormatter
*
... ... @@ -64,7 +62,6 @@ class FluentdFormatter implements FormatterInterface
$message = array(
'message' => $record['message'],
'context' => $record['context'],
'extra' => $record['extra'],
);
... ... @@ -73,7 +70,7 @@ class FluentdFormatter implements FormatterInterface
$message['level_name'] = $record['level_name'];
}
return Utils::jsonEncode(array($tag, $record['datetime']->getTimestamp(), $message));
return json_encode(array($tag, $record['datetime']->getTimestamp(), $message));
}
public function formatBatch(array $records)
... ...
... ... @@ -22,7 +22,7 @@ use Gelf\Message;
*/
class GelfMessageFormatter extends NormalizerFormatter
{
const DEFAULT_MAX_LENGTH = 32766;
const MAX_LENGTH = 32766;
/**
* @var string the name of the system for the Gelf log message
... ... @@ -40,11 +40,6 @@ class GelfMessageFormatter extends NormalizerFormatter
protected $contextPrefix;
/**
* @var int max length per field
*/
protected $maxLength;
/**
* Translates Monolog log levels to Graylog2 log priorities.
*/
private $logLevels = array(
... ... @@ -58,7 +53,7 @@ class GelfMessageFormatter extends NormalizerFormatter
Logger::EMERGENCY => 0,
);
public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $maxLength = null)
public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_')
{
parent::__construct('U.u');
... ... @@ -66,7 +61,6 @@ class GelfMessageFormatter extends NormalizerFormatter
$this->extraPrefix = $extraPrefix;
$this->contextPrefix = $contextPrefix;
$this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength;
}
/**
... ... @@ -87,30 +81,35 @@ class GelfMessageFormatter extends NormalizerFormatter
->setHost($this->systemName)
->setLevel($this->logLevels[$record['level']]);
// message length + system name length + 200 for padding / metadata
// start count with message length + system name length + 200 for padding / metadata
$len = 200 + strlen((string) $record['message']) + strlen($this->systemName);
if ($len > $this->maxLength) {
$message->setShortMessage(substr($record['message'], 0, $this->maxLength));
if ($len > self::MAX_LENGTH) {
$message->setShortMessage(substr($record['message'], 0, self::MAX_LENGTH - 200));
return $message;
}
if (isset($record['channel'])) {
$message->setFacility($record['channel']);
$len += strlen($record['channel']);
}
if (isset($record['extra']['line'])) {
$message->setLine($record['extra']['line']);
$len += 10;
unset($record['extra']['line']);
}
if (isset($record['extra']['file'])) {
$message->setFile($record['extra']['file']);
$len += strlen($record['extra']['file']);
unset($record['extra']['file']);
}
foreach ($record['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, substr($val, 0, $this->maxLength));
$len += strlen($this->extraPrefix . $key . $val);
if ($len > self::MAX_LENGTH) {
$message->setAdditional($this->extraPrefix . $key, substr($val, 0, self::MAX_LENGTH - $len));
break;
}
$message->setAdditional($this->extraPrefix . $key, $val);
... ... @@ -118,9 +117,9 @@ class GelfMessageFormatter extends NormalizerFormatter
foreach ($record['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, substr($val, 0, $this->maxLength));
$len += strlen($this->contextPrefix . $key . $val);
if ($len > self::MAX_LENGTH) {
$message->setAdditional($this->contextPrefix . $key, substr($val, 0, self::MAX_LENGTH - $len));
break;
}
$message->setAdditional($this->contextPrefix . $key, $val);
... ...
... ... @@ -11,7 +11,6 @@
namespace Monolog\Formatter;
use Monolog\Logger;
use Monolog\Utils;
/**
* Formats incoming records into an HTML table
... ... @@ -59,7 +58,7 @@ class HtmlFormatter extends NormalizerFormatter
$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>";
return "<tr style=\"padding: 4px;spacing: 0;text-align: left;\">\n<th style=\"background: #cccccc\" width=\"100px\">$th:</th>\n<td style=\"padding: 4px;spacing: 0;text-align: left;background: #eeeeee\">".$td."</td>\n</tr>";
}
/**
... ... @@ -134,9 +133,9 @@ class HtmlFormatter extends NormalizerFormatter
$data = $this->normalize($data);
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
return Utils::jsonEncode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, true);
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
return str_replace('\\/', '/', Utils::jsonEncode($data, null, true));
return str_replace('\\/', '/', json_encode($data));
}
}
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Formatter;
use Exception;
use Monolog\Utils;
use Throwable;
/**
... ... @@ -29,7 +28,6 @@ class JsonFormatter extends NormalizerFormatter
protected $batchMode;
protected $appendNewline;
/**
* @var bool
*/
... ... @@ -37,7 +35,6 @@ class JsonFormatter extends NormalizerFormatter
/**
* @param int $batchMode
* @param bool $appendNewline
*/
public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = true)
{
... ... @@ -139,23 +136,18 @@ class JsonFormatter extends NormalizerFormatter
*
* @return mixed
*/
protected function normalize($data, $depth = 0)
protected function normalize($data)
{
if ($depth > 9) {
return 'Over 9 levels deep, aborting normalization';
}
if (is_array($data)) {
if (is_array($data) || $data instanceof \Traversable) {
$normalized = array();
$count = 1;
foreach ($data as $key => $value) {
if ($count++ > 1000) {
$normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
if ($count++ >= 1000) {
$normalized['...'] = 'Over 1000 items, aborting normalization';
break;
}
$normalized[$key] = $this->normalize($value, $depth+1);
$normalized[$key] = $this->normalize($value);
}
return $normalized;
... ... @@ -165,10 +157,6 @@ class JsonFormatter extends NormalizerFormatter
return $this->normalizeException($data);
}
if (is_resource($data)) {
return parent::normalize($data);
}
return $data;
}
... ... @@ -184,13 +172,13 @@ class JsonFormatter extends NormalizerFormatter
{
// TODO 2.0 only check for Throwable
if (!$e instanceof Exception && !$e instanceof Throwable) {
throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
}
$data = array(
'class' => Utils::getClass($e),
'class' => get_class($e),
'message' => $e->getMessage(),
'code' => (int) $e->getCode(),
'code' => $e->getCode(),
'file' => $e->getFile().':'.$e->getLine(),
);
... ... @@ -199,6 +187,12 @@ class JsonFormatter extends NormalizerFormatter
foreach ($trace as $frame) {
if (isset($frame['file'])) {
$data['trace'][] = $frame['file'].':'.$frame['line'];
} elseif (isset($frame['function']) && $frame['function'] === '{closure}') {
// We should again normalize the frames, because it might contain invalid items
$data['trace'][] = $frame['function'];
} else {
// We should again normalize the frames, because it might contain invalid items
$data['trace'][] = $this->normalize($frame);
}
}
}
... ...
... ... @@ -11,8 +11,6 @@
namespace Monolog\Formatter;
use Monolog\Utils;
/**
* Formats incoming records into a one-line string
*
... ... @@ -131,19 +129,19 @@ class LineFormatter extends NormalizerFormatter
{
// TODO 2.0 only check for Throwable
if (!$e instanceof \Exception && !$e instanceof \Throwable) {
throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
}
$previousText = '';
if ($previous = $e->getPrevious()) {
do {
$previousText .= ', '.Utils::getClass($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
$previousText .= ', '.get_class($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
} while ($previous = $previous->getPrevious());
}
$str = '[object] ('.Utils::getClass($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')';
$str = '[object] ('.get_class($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')';
if ($this->includeStacktraces) {
$str .= "\n[stacktrace]\n".$e->getTraceAsString()."\n";
$str .= "\n[stacktrace]\n".$e->getTraceAsString();
}
return $str;
... ... @@ -163,16 +161,12 @@ class LineFormatter extends NormalizerFormatter
return $this->toJson($data, true);
}
return str_replace('\\/', '/', $this->toJson($data, true));
return str_replace('\\/', '/', @json_encode($data));
}
protected function replaceNewlines($str)
{
if ($this->allowInlineLineBreaks) {
if (0 === strpos($str, '{')) {
return str_replace(array('\r', '\n'), array("\r", "\n"), $str);
}
return $str;
}
... ...
... ... @@ -11,8 +11,6 @@
namespace Monolog\Formatter;
use Monolog\Utils;
/**
* Formats a record for use with the MongoDBHandler.
*
... ... @@ -77,7 +75,7 @@ class MongoDBFormatter implements FormatterInterface
protected function formatObject($value, $nestingLevel)
{
$objectVars = get_object_vars($value);
$objectVars['class'] = Utils::getClass($value);
$objectVars['class'] = get_class($value);
return $this->formatArray($objectVars, $nestingLevel);
}
... ... @@ -85,9 +83,9 @@ class MongoDBFormatter implements FormatterInterface
protected function formatException(\Exception $exception, $nestingLevel)
{
$formattedException = array(
'class' => Utils::getClass($exception),
'class' => get_class($exception),
'message' => $exception->getMessage(),
'code' => (int) $exception->getCode(),
'code' => $exception->getCode(),
'file' => $exception->getFile() . ':' . $exception->getLine(),
);
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Formatter;
use Exception;
use Monolog\Utils;
/**
* Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
... ... @@ -56,12 +55,8 @@ class NormalizerFormatter implements FormatterInterface
return $records;
}
protected function normalize($data, $depth = 0)
protected function normalize($data)
{
if ($depth > 9) {
return 'Over 9 levels deep, aborting normalization';
}
if (null === $data || is_scalar($data)) {
if (is_float($data)) {
if (is_infinite($data)) {
... ... @@ -80,12 +75,11 @@ class NormalizerFormatter implements FormatterInterface
$count = 1;
foreach ($data as $key => $value) {
if ($count++ > 1000) {
if ($count++ >= 1000) {
$normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
break;
}
$normalized[$key] = $this->normalize($value, $depth+1);
$normalized[$key] = $this->normalize($value);
}
return $normalized;
... ... @@ -109,7 +103,7 @@ class NormalizerFormatter implements FormatterInterface
$value = $this->toJson($data, true);
}
return sprintf("[object] (%s: %s)", Utils::getClass($data), $value);
return sprintf("[object] (%s: %s)", get_class($data), $value);
}
if (is_resource($data)) {
... ... @@ -123,13 +117,13 @@ class NormalizerFormatter implements FormatterInterface
{
// TODO 2.0 only check for Throwable
if (!$e instanceof Exception && !$e instanceof \Throwable) {
throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
}
$data = array(
'class' => Utils::getClass($e),
'class' => get_class($e),
'message' => $e->getMessage(),
'code' => (int) $e->getCode(),
'code' => $e->getCode(),
'file' => $e->getFile().':'.$e->getLine(),
);
... ... @@ -143,11 +137,7 @@ class NormalizerFormatter implements FormatterInterface
}
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);
}
$data['detail'] = $e->detail;
}
}
... ... @@ -155,6 +145,12 @@ class NormalizerFormatter implements FormatterInterface
foreach ($trace as $frame) {
if (isset($frame['file'])) {
$data['trace'][] = $frame['file'].':'.$frame['line'];
} elseif (isset($frame['function']) && $frame['function'] === '{closure}') {
// We should again normalize the frames, because it might contain invalid items
$data['trace'][] = $frame['function'];
} else {
// We should again normalize the frames, because it might contain invalid items
$data['trace'][] = $this->toJson($this->normalize($frame), true);
}
}
... ... @@ -175,6 +171,127 @@ class NormalizerFormatter implements FormatterInterface
*/
protected function toJson($data, $ignoreErrors = false)
{
return Utils::jsonEncode($data, null, $ignoreErrors);
// suppress json_encode errors since it's twitchy with some inputs
if ($ignoreErrors) {
return @$this->jsonEncode($data);
}
$json = $this->jsonEncode($data);
if ($json === false) {
$json = $this->handleJsonError(json_last_error(), $data);
}
return $json;
}
/**
* @param mixed $data
* @return string JSON encoded data or null on failure
*/
private function jsonEncode($data)
{
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
return json_encode($data);
}
/**
* Handle a json_encode failure.
*
* If the failure is due to invalid string encoding, try to clean the
* input and encode again. If the second encoding attempt fails, the
* inital error is not encoding related or the input can't be cleaned then
* raise a descriptive exception.
*
* @param int $code return code of json_last_error function
* @param mixed $data data that was meant to be encoded
* @throws \RuntimeException if failure can't be corrected
* @return string JSON encoded data after error correction
*/
private function handleJsonError($code, $data)
{
if ($code !== JSON_ERROR_UTF8) {
$this->throwEncodeError($code, $data);
}
if (is_string($data)) {
$this->detectAndCleanUtf8($data);
} elseif (is_array($data)) {
array_walk_recursive($data, array($this, 'detectAndCleanUtf8'));
} else {
$this->throwEncodeError($code, $data);
}
$json = $this->jsonEncode($data);
if ($json === false) {
$this->throwEncodeError(json_last_error(), $data);
}
return $json;
}
/**
* Throws an exception according to a given code with a customized message
*
* @param int $code return code of json_last_error function
* @param mixed $data data that was meant to be encoded
* @throws \RuntimeException
*/
private function throwEncodeError($code, $data)
{
switch ($code) {
case JSON_ERROR_DEPTH:
$msg = 'Maximum stack depth exceeded';
break;
case JSON_ERROR_STATE_MISMATCH:
$msg = 'Underflow or the modes mismatch';
break;
case JSON_ERROR_CTRL_CHAR:
$msg = 'Unexpected control character found';
break;
case JSON_ERROR_UTF8:
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
break;
default:
$msg = 'Unknown error';
}
throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true));
}
/**
* Detect invalid UTF-8 string characters and convert to valid UTF-8.
*
* Valid UTF-8 input will be left unmodified, but strings containing
* invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed
* original encoding of ISO-8859-15. This conversion may result in
* incorrect output if the actual encoding was not ISO-8859-15, but it
* will be clean UTF-8 output and will not rely on expensive and fragile
* detection algorithms.
*
* Function converts the input in place in the passed variable so that it
* can be used as a callback for array_walk_recursive.
*
* @param mixed &$data Input to check and convert if needed
* @private
*/
public function detectAndCleanUtf8(&$data)
{
if (is_string($data) && !preg_match('//u', $data)) {
$data = preg_replace_callback(
'/[\x80-\xFF]+/',
function ($m) { return utf8_encode($m[0]); },
$data
);
$data = str_replace(
array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'),
array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'),
$data
);
}
}
}
... ...
... ... @@ -102,12 +102,12 @@ class WildfireFormatter extends NormalizerFormatter
throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
}
protected function normalize($data, $depth = 0)
protected function normalize($data)
{
if (is_object($data) && !$data instanceof \DateTime) {
return $data;
}
return parent::normalize($data, $depth);
return parent::normalize($data);
}
}
... ...
... ... @@ -11,17 +11,16 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
use Monolog\ResettableInterface;
/**
* Base Handler class providing the Handler structure
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
abstract class AbstractHandler implements HandlerInterface, ResettableInterface
abstract class AbstractHandler implements HandlerInterface
{
protected $level = Logger::DEBUG;
protected $bubble = true;
... ... @@ -33,8 +32,8 @@ abstract class AbstractHandler implements HandlerInterface, ResettableInterface
protected $processors = array();
/**
* @param int|string $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = Logger::DEBUG, $bubble = true)
{
... ... @@ -142,8 +141,8 @@ abstract class AbstractHandler implements HandlerInterface, ResettableInterface
/**
* Sets the bubbling behavior.
*
* @param bool $bubble true means that this handler allows bubbling.
* false means that bubbling is not permitted.
* @param Boolean $bubble true means that this handler allows bubbling.
* false means that bubbling is not permitted.
* @return self
*/
public function setBubble($bubble)
... ... @@ -156,8 +155,8 @@ abstract class AbstractHandler implements HandlerInterface, ResettableInterface
/**
* Gets the bubbling behavior.
*
* @return bool true means that this handler allows bubbling.
* false means that bubbling is not permitted.
* @return Boolean true means that this handler allows bubbling.
* false means that bubbling is not permitted.
*/
public function getBubble()
{
... ... @@ -175,15 +174,6 @@ abstract class AbstractHandler implements HandlerInterface, ResettableInterface
}
}
public function reset()
{
foreach ($this->processors as $processor) {
if ($processor instanceof ResettableInterface) {
$processor->reset();
}
}
}
/**
* Gets the default formatter.
*
... ...
... ... @@ -11,8 +11,6 @@
namespace Monolog\Handler;
use Monolog\ResettableInterface;
/**
* Base Handler class providing the Handler structure
*
... ...
... ... @@ -53,9 +53,9 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
);
/**
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true)
{
... ...
... ... @@ -43,11 +43,11 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
protected function write(array $record)
{
// Accumulate records
static::$records[] = $record;
self::$records[] = $record;
// Register shutdown handler if not already done
if (!static::$initialized) {
static::$initialized = true;
if (!self::$initialized) {
self::$initialized = true;
$this->registerShutdownFunction();
}
}
... ... @@ -58,37 +58,27 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
*/
public static function send()
{
$format = static::getResponseFormat();
$format = self::getResponseFormat();
if ($format === 'unknown') {
return;
}
if (count(static::$records)) {
if (count(self::$records)) {
if ($format === 'html') {
static::writeOutput('<script>' . static::generateScript() . '</script>');
self::writeOutput('<script>' . self::generateScript() . '</script>');
} elseif ($format === 'js') {
static::writeOutput(static::generateScript());
self::writeOutput(self::generateScript());
}
static::resetStatic();
self::reset();
}
}
public function close()
{
self::resetStatic();
}
public function reset()
{
self::resetStatic();
}
/**
* Forget all logged records
*/
public static function resetStatic()
public static function reset()
{
static::$records = array();
self::$records = array();
}
/**
... ... @@ -143,18 +133,18 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function generateScript()
{
$script = array();
foreach (static::$records as $record) {
$context = static::dump('Context', $record['context']);
$extra = static::dump('Extra', $record['extra']);
foreach (self::$records as $record) {
$context = self::dump('Context', $record['context']);
$extra = self::dump('Extra', $record['extra']);
if (empty($context) && empty($extra)) {
$script[] = static::call_array('log', static::handleStyles($record['formatted']));
$script[] = self::call_array('log', self::handleStyles($record['formatted']));
} else {
$script = array_merge($script,
array(static::call_array('groupCollapsed', static::handleStyles($record['formatted']))),
array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))),
$context,
$extra,
array(static::call('groupEnd'))
array(self::call('groupEnd'))
);
}
}
... ... @@ -164,22 +154,21 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function handleStyles($formatted)
{
$args = array();
$args = array(self::quote('font-weight: normal'));
$format = '%c' . $formatted;
preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach (array_reverse($matches) as $match) {
$args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0]));
$args[] = '"font-weight: normal"';
$args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
$pos = $match[0][1];
$format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
}
$args[] = static::quote('font-weight: normal');
$args[] = static::quote($format);
array_unshift($args, self::quote($format));
return array_reverse($args);
return $args;
}
private static function handleCustomStyles($style, $string)
... ... @@ -209,13 +198,13 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
if (empty($dict)) {
return $script;
}
$script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title));
$script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));
foreach ($dict as $key => $value) {
$value = json_encode($value);
if (empty($value)) {
$value = static::quote('');
$value = self::quote('');
}
$script[] = static::call('log', static::quote('%s: %o'), static::quote($key), $value);
$script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value);
}
return $script;
... ... @@ -231,7 +220,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
$args = func_get_args();
$method = array_shift($args);
return static::call_array($method, $args);
return self::call_array($method, $args);
}
private static function call_array($method, array $args)
... ...
... ... @@ -12,8 +12,6 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
/**
* Buffers all records until closing the handler and then pass them as batch.
... ... @@ -36,8 +34,8 @@ class BufferHandler extends AbstractHandler
* @param HandlerInterface $handler Handler.
* @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
*/
public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false)
{
... ... @@ -116,33 +114,4 @@ class BufferHandler extends AbstractHandler
$this->bufferSize = 0;
$this->buffer = array();
}
public function reset()
{
$this->flush();
parent::reset();
if ($this->handler instanceof ResettableInterface) {
$this->handler->reset();
}
}
/**
* {@inheritdoc}
*/
public function setFormatter(FormatterInterface $formatter)
{
$this->handler->setFormatter($formatter);
return $this;
}
/**
* {@inheritdoc}
*/
public function getFormatter()
{
return $this->handler->getFormatter();
}
}
... ...
... ... @@ -13,7 +13,6 @@ namespace Monolog\Handler;
use Monolog\Formatter\ChromePHPFormatter;
use Monolog\Logger;
use Monolog\Utils;
/**
* Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
... ... @@ -33,20 +32,20 @@ class ChromePHPHandler extends AbstractProcessingHandler
* Header name
*/
const HEADER_NAME = 'X-ChromeLogger-Data';
/**
* Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
*/
const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}';
const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}';
protected static $initialized = false;
/**
* Tracks whether we sent too much data
*
* Chrome limits the headers to 4KB, so when we sent 3KB we stop sending
* Chrome limits the headers to 256KB, so when we sent 240KB we stop sending
*
* @var bool
* @var Boolean
*/
protected static $overflowed = false;
... ... @@ -59,8 +58,8 @@ class ChromePHPHandler extends AbstractProcessingHandler
protected static $sendHeaders = true;
/**
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = Logger::DEBUG, $bubble = true)
{
... ... @@ -135,9 +134,9 @@ class ChromePHPHandler extends AbstractProcessingHandler
self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
}
$json = Utils::jsonEncode(self::$json, null, true);
$json = @json_encode(self::$json);
$data = base64_encode(utf8_encode($json));
if (strlen($data) > 3 * 1024) {
if (strlen($data) > 240 * 1024) {
self::$overflowed = true;
$record = array(
... ... @@ -150,7 +149,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
'extra' => array(),
);
self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
$json = Utils::jsonEncode(self::$json, null, true);
$json = @json_encode(self::$json);
$data = base64_encode(utf8_encode($json));
}
... ... @@ -175,7 +174,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
/**
* Verifies if the headers are accepted by the current user agent
*
* @return bool
* @return Boolean
*/
protected function headersAccepted()
{
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Utils;
/**
* Logs to Cube.
... ... @@ -120,9 +119,9 @@ class CubeHandler extends AbstractProcessingHandler
$data['data']['level'] = $record['level'];
if ($this->scheme === 'http') {
$this->writeHttp(Utils::jsonEncode($data));
$this->writeHttp(json_encode($data));
} else {
$this->writeUdp(Utils::jsonEncode($data));
$this->writeUdp(json_encode($data));
}
}
... ...
... ... @@ -60,7 +60,7 @@ class DeduplicationHandler extends BufferHandler
* @param string $deduplicationStore The file/path where the deduplication log should be kept
* @param int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
* @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(HandlerInterface $handler, $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, $time = 60, $bubble = true)
{
... ...
... ... @@ -11,7 +11,7 @@
namespace Monolog\Handler;
use Aws\Sdk;
use Aws\Common\Aws;
use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Marshaler;
use Monolog\Formatter\ScalarFormatter;
... ... @@ -55,7 +55,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
*/
public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true)
{
if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) {
if (defined('Aws\Common\Aws::VERSION') && version_compare(Aws::VERSION, '3.0', '>=')) {
$this->version = 3;
$this->marshaler = new Marshaler;
} else {
... ...
... ... @@ -46,10 +46,10 @@ class ElasticSearchHandler extends AbstractProcessingHandler
protected $options = array();
/**
* @param Client $client Elastica Client object
* @param array $options Handler configuration
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Client $client Elastica Client object
* @param array $options Handler configuration
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true)
{
... ...
... ... @@ -28,10 +28,10 @@ class ErrorLogHandler extends AbstractProcessingHandler
protected $expandNewlines;
/**
* @param int $messageType Says where the error should go.
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
* @param int $messageType Says where the error should go.
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
*/
public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false)
{
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
/**
* Simple handler wrapper that filters records based on a list of levels
... ... @@ -41,15 +40,15 @@ class FilterHandler extends AbstractHandler
/**
* Whether the messages that are handled can bubble up the stack or not
*
* @var bool
* @var Boolean
*/
protected $bubble;
/**
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler).
* @param callable|HandlerInterface $handler Handler or factory callable($record, $this).
* @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
* @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true)
{
... ... @@ -105,13 +104,21 @@ class FilterHandler extends AbstractHandler
return false;
}
// The same logic as in FingersCrossedHandler
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
}
$this->getHandler($record)->handle($record);
$this->handler->handle($record);
return false === $this->bubble;
}
... ... @@ -128,45 +135,6 @@ class FilterHandler extends AbstractHandler
}
}
if (count($filtered) > 0) {
$this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered);
}
}
/**
* Return the nested handler
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*/
public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}
return $this->handler;
}
/**
* {@inheritdoc}
*/
public function setFormatter(FormatterInterface $formatter)
{
$this->getHandler()->setFormatter($formatter);
return $this;
}
/**
* {@inheritdoc}
*/
public function getFormatter()
{
return $this->getHandler()->getFormatter();
$this->handler->handleBatch($filtered);
}
}
... ...
... ... @@ -22,7 +22,7 @@ interface ActivationStrategyInterface
* Returns whether the given record activates the handler.
*
* @param array $record
* @return bool
* @return Boolean
*/
public function isHandlerActivated(array $record);
}
... ...
... ... @@ -14,8 +14,6 @@ namespace Monolog\Handler;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
/**
* Buffers all records until a certain level is reached
... ... @@ -40,11 +38,11 @@ class FingersCrossedHandler extends AbstractHandler
protected $passthruLevel;
/**
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler).
* @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
* @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
* @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $stopBuffering Whether the handler should stop buffering after being triggered (default true)
* @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
*/
public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null)
... ... @@ -89,7 +87,15 @@ class FingersCrossedHandler extends AbstractHandler
if ($this->stopBuffering) {
$this->buffering = false;
}
$this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
if (!$this->handler instanceof HandlerInterface) {
$record = end($this->buffer) ?: null;
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}
$this->handler->handleBatch($this->buffer);
$this->buffer = array();
}
... ... @@ -113,7 +119,7 @@ class FingersCrossedHandler extends AbstractHandler
$this->activate();
}
} else {
$this->getHandler($record)->handle($record);
$this->handler->handle($record);
}
return false === $this->bubble;
... ... @@ -124,84 +130,34 @@ class FingersCrossedHandler extends AbstractHandler
*/
public function close()
{
$this->flushBuffer();
}
public function reset()
{
$this->flushBuffer();
parent::reset();
if ($this->getHandler() instanceof ResettableInterface) {
$this->getHandler()->reset();
}
}
/**
* Clears the buffer without flushing any messages down to the wrapped handler.
*
* It also resets the handler to its initial buffering state.
*/
public function clear()
{
$this->buffer = array();
$this->reset();
}
/**
* Resets the state of the handler. Stops forwarding records to the wrapped handler.
*/
private function flushBuffer()
{
if (null !== $this->passthruLevel) {
$level = $this->passthruLevel;
$this->buffer = array_filter($this->buffer, function ($record) use ($level) {
return $record['level'] >= $level;
});
if (count($this->buffer) > 0) {
$this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
}
}
$this->buffer = array();
$this->buffering = true;
}
/**
* Return the nested handler
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*/
public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
$this->handler->handleBatch($this->buffer);
$this->buffer = array();
}
}
return $this->handler;
}
/**
* {@inheritdoc}
* Resets the state of the handler. Stops forwarding records to the wrapped handler.
*/
public function setFormatter(FormatterInterface $formatter)
public function reset()
{
$this->getHandler()->setFormatter($formatter);
return $this;
$this->buffering = true;
}
/**
* {@inheritdoc}
* Clears the buffer without flushing any messages down to the wrapped handler.
*
* It also resets the handler to its initial buffering state.
*/
public function getFormatter()
public function clear()
{
return $this->getHandler()->getFormatter();
$this->buffer = array();
$this->reset();
}
}
... ...
... ... @@ -158,7 +158,7 @@ class FirePHPHandler extends AbstractProcessingHandler
/**
* Verifies if the headers are accepted by the current user agent
*
* @return bool
* @return Boolean
*/
protected function headersAccepted()
{
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\FlowdockFormatter;
use Monolog\Formatter\FormatterInterface;
... ... @@ -106,7 +105,7 @@ class FlowdockHandler extends SocketHandler
*/
private function buildContent($record)
{
return Utils::jsonEncode($record['formatted']['flowdock']);
return json_encode($record['formatted']['flowdock']);
}
/**
... ...
<?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\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
/**
* Helper trait for implementing FormattableInterface
*
* This trait is present in monolog 1.x to ease forward compatibility.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
trait FormattableHandlerTrait
{
/**
* @var FormatterInterface
*/
protected $formatter;
/**
* {@inheritdoc}
* @suppress PhanTypeMismatchReturn
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
$this->formatter = $formatter;
return $this;
}
/**
* {@inheritdoc}
*/
public function getFormatter(): FormatterInterface
{
if (!$this->formatter) {
$this->formatter = $this->getDefaultFormatter();
}
return $this->formatter;
}
/**
* Gets the default formatter.
*
* Overwrite this if the LineFormatter is not a good default for your handler.
*/
protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter();
}
}
... ... @@ -50,6 +50,14 @@ class GelfHandler extends AbstractProcessingHandler
/**
* {@inheritdoc}
*/
public function close()
{
$this->publisher = null;
}
/**
* {@inheritdoc}
*/
protected function write(array $record)
{
$this->publisher->publish($record['formatted']);
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\ResettableInterface;
/**
* Forwards records to multiple handlers
... ... @@ -24,8 +23,8 @@ class GroupHandler extends AbstractHandler
protected $handlers;
/**
* @param array $handlers Array of Handlers.
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param array $handlers Array of Handlers.
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(array $handlers, $bubble = true)
{
... ... @@ -80,9 +79,8 @@ class GroupHandler extends AbstractHandler
$processed = array();
foreach ($records as $record) {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
$processed[] = call_user_func($processor, $record);
}
$processed[] = $record;
}
$records = $processed;
}
... ... @@ -92,17 +90,6 @@ class GroupHandler extends AbstractHandler
}
}
public function reset()
{
parent::reset();
foreach ($this->handlers as $handler) {
if ($handler instanceof ResettableInterface) {
$handler->reset();
}
}
}
/**
* {@inheritdoc}
*/
... ...
... ... @@ -31,7 +31,7 @@ interface HandlerInterface
*
* @param array $record Partial log record containing only a level key
*
* @return bool
* @return Boolean
*/
public function isHandling(array $record);
... ... @@ -46,7 +46,7 @@ interface HandlerInterface
* calling further handlers in the stack with a given log record.
*
* @param array $record The record to handle
* @return bool true means that this handler handled the record, and that bubbling is not permitted.
* @return Boolean true means that this handler handled the record, and that bubbling is not permitted.
* false means the record was either not processed or that this handler allows bubbling.
*/
public function handle(array $record);
... ...
... ... @@ -11,27 +11,24 @@
namespace Monolog\Handler;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
/**
* This simple wrapper class can be used to extend handlers functionality.
*
* Example: A custom filtering that can be applied to any handler.
* Example: A filtering handle. Inherit from this class, override isHandling() like this
*
* Inherit from this class and override handle() like this:
*
* public function handle(array $record)
* {
* if ($record meets certain conditions) {
* return false;
* }
* return $this->handler->handle($record);
* }
* public function isHandling(array $record)
* {
* if ($record meets certain conditions) {
* return false;
* }
* return $this->handler->isHandling($record);
* }
*
* @author Alexey Karapetov <alexey@karapetov.com>
*/
class HandlerWrapper implements HandlerInterface, ResettableInterface
class HandlerWrapper implements HandlerInterface
{
/**
* @var HandlerInterface
... ... @@ -106,11 +103,4 @@ class HandlerWrapper implements HandlerInterface, ResettableInterface
{
return $this->handler->getFormatter();
}
public function reset()
{
if ($this->handler instanceof ResettableInterface) {
return $this->handler->reset();
}
}
}
... ...
... ... @@ -97,8 +97,6 @@ class HipChatHandler extends SocketHandler
*/
public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com', $version = self::API_V1)
{
@trigger_error('The Monolog\Handler\HipChatHandler class is deprecated. You should migrate to Slack and the SlackWebhookHandler / SlackbotHandler, see https://www.atlassian.com/partnerships/slack', E_USER_DEPRECATED);
if ($version == self::API_V1 && !$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) {
throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.');
}
... ... @@ -221,21 +219,6 @@ class HipChatHandler extends SocketHandler
protected function write(array $record)
{
parent::write($record);
$this->finalizeWrite();
}
/**
* Finalizes the request by reading some bytes and then closing the socket
*
* If we do not read some but close the socket too early, hipchat sometimes
* drops the request entirely.
*/
protected function finalizeWrite()
{
$res = $this->getResource();
if (is_resource($res)) {
@fread($res, 2048);
}
$this->closeSocket();
}
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Utils;
/**
* IFTTTHandler uses cURL to trigger IFTTT Maker actions
... ... @@ -31,10 +30,10 @@ class IFTTTHandler extends AbstractProcessingHandler
private $secretKey;
/**
* @param string $eventName The name of the IFTTT Maker event that should be triggered
* @param string $secretKey A valid IFTTT secret key
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string $eventName The name of the IFTTT Maker event that should be triggered
* @param string $secretKey A valid IFTTT secret key
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($eventName, $secretKey, $level = Logger::ERROR, $bubble = true)
{
... ... @@ -54,7 +53,7 @@ class IFTTTHandler extends AbstractProcessingHandler
"value2" => $record["level_name"],
"value3" => $record["message"],
);
$postString = Utils::jsonEncode($postData);
$postString = json_encode($postData);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
... ...
<?php
/*
* 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\Handler;
use Monolog\Logger;
/**
* Inspired on LogEntriesHandler.
*
* @author Robert Kaufmann III <rok3@rok3.me>
* @author Gabriel Machado <gabriel.ms1@hotmail.com>
*/
class InsightOpsHandler extends SocketHandler
{
/**
* @var string
*/
protected $logToken;
/**
* @param string $token Log token supplied by InsightOps
* @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
* @param bool $useSSL Whether or not SSL encryption should be used
* @param int $level The minimum logging level to trigger this handler
* @param bool $bubble Whether or not messages that are handled should bubble up the stack.
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
public function __construct($token, $region = 'us', $useSSL = true, $level = Logger::DEBUG, $bubble = true)
{
if ($useSSL && !extension_loaded('openssl')) {
throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler');
}
$endpoint = $useSSL
? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443'
: $region . '.data.logs.insight.rapid7.com:80';
parent::__construct($endpoint, $level, $bubble);
$this->logToken = $token;
}
/**
* {@inheritdoc}
*
* @param array $record
* @return string
*/
protected function generateDataStream($record)
{
return $this->logToken . ' ' . $record['formatted'];
}
}
... ... @@ -31,13 +31,13 @@ class LogEntriesHandler extends SocketHandler
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true, $host = 'data.logentries.com')
public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true)
{
if ($useSSL && !extension_loaded('openssl')) {
throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
}
$endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
$endpoint = $useSSL ? 'ssl://data.logentries.com:443' : 'data.logentries.com:80';
parent::__construct($endpoint, $level, $bubble);
$this->logToken = $token;
}
... ...
... ... @@ -27,7 +27,7 @@ class MandrillHandler extends MailHandler
* @param string $apiKey A valid Mandrill API key
* @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true)
{
... ...
... ... @@ -12,15 +12,12 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
/**
* Class to record a log on a NewRelic application.
* Enabling New Relic High Security mode may prevent capture of useful information.
*
* This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
*
* @see https://docs.newrelic.com/docs/agents/php-agent
* @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
*/
... ... @@ -87,7 +84,7 @@ class NewRelicHandler extends AbstractProcessingHandler
unset($record['formatted']['context']['transaction_name']);
}
if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
newrelic_notice_error($record['message'], $record['context']['exception']);
unset($record['formatted']['context']['exception']);
} else {
... ... @@ -191,7 +188,7 @@ class NewRelicHandler extends AbstractProcessingHandler
if (null === $value || is_scalar($value)) {
newrelic_add_custom_parameter($key, $value);
} else {
newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true));
newrelic_add_custom_parameter($key, @json_encode($value));
}
}
... ...
... ... @@ -14,7 +14,6 @@ namespace Monolog\Handler;
use Exception;
use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
use Monolog\Utils;
use PhpConsole\Connector;
use PhpConsole\Handler;
use PhpConsole\Helper;
... ... @@ -189,7 +188,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
$tags = $this->getRecordTags($record);
$message = $record['message'];
if ($record['context']) {
$message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true);
$message .= ' ' . json_encode($this->connector->getDumper()->dump(array_filter($record['context'])));
}
$this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
}
... ...
<?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\Handler;
use Monolog\Processor\ProcessorInterface;
/**
* Interface to describe loggers that have processors
*
* This interface is present in monolog 1.x to ease forward compatibility.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
interface ProcessableHandlerInterface
{
/**
* Adds a processor in the stack.
*
* @param ProcessorInterface|callable $callback
* @return HandlerInterface self
*/
public function pushProcessor($callback): HandlerInterface;
/**
* Removes the processor on top of the stack and returns it.
*
* @throws \LogicException In case the processor stack is empty
* @return callable
*/
public function popProcessor(): callable;
}
<?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\Handler;
use Monolog\ResettableInterface;
/**
* Helper trait for implementing ProcessableInterface
*
* This trait is present in monolog 1.x to ease forward compatibility.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
trait ProcessableHandlerTrait
{
/**
* @var callable[]
*/
protected $processors = [];
/**
* {@inheritdoc}
* @suppress PhanTypeMismatchReturn
*/
public function pushProcessor($callback): HandlerInterface
{
array_unshift($this->processors, $callback);
return $this;
}
/**
* {@inheritdoc}
*/
public function popProcessor(): callable
{
if (!$this->processors) {
throw new \LogicException('You tried to pop from an empty processor stack.');
}
return array_shift($this->processors);
}
/**
* Processes a record.
*/
protected function processRecord(array $record): array
{
foreach ($this->processors as $processor) {
$record = $processor($record);
}
return $record;
}
protected function resetProcessors(): void
{
foreach ($this->processors as $processor) {
if ($processor instanceof ResettableInterface) {
$processor->reset();
}
}
}
}
... ... @@ -31,7 +31,7 @@ class PsrHandler extends AbstractHandler
/**
* @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true)
{
... ...
... ... @@ -69,8 +69,8 @@ class PushoverHandler extends SocketHandler
* @param string|array $users Pushover user id or array of ids the message will be sent to
* @param string $title Title sent to the Pushover API
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
* the pushover.net app owner. OpenSSL is required for this option.
* @param int $highPriorityLevel The minimum logging level at which this handler will start
* sending "high priority" requests to the Pushover API
... ... @@ -180,6 +180,6 @@ class PushoverHandler extends SocketHandler
*/
public function useFormattedMessage($value)
{
$this->useFormattedMessage = (bool) $value;
$this->useFormattedMessage = (boolean) $value;
}
}
... ...
... ... @@ -18,7 +18,7 @@ use Raven_Client;
/**
* Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server
* using sentry-php (https://github.com/getsentry/sentry-php)
* using raven-php (https://github.com/getsentry/raven-php)
*
* @author Marc Abramowitz <marc@marc-abramowitz.com>
*/
... ... @@ -27,7 +27,7 @@ class RavenHandler extends AbstractProcessingHandler
/**
* Translates Monolog log levels to Raven log levels.
*/
protected $logLevels = array(
private $logLevels = array(
Logger::DEBUG => Raven_Client::DEBUG,
Logger::INFO => Raven_Client::INFO,
Logger::NOTICE => Raven_Client::INFO,
... ... @@ -42,7 +42,7 @@ class RavenHandler extends AbstractProcessingHandler
* @var string should represent the current version of the calling
* software. Can be any string (git commit, version number)
*/
protected $release;
private $release;
/**
* @var Raven_Client the client object that sends the message to the server
... ... @@ -57,12 +57,10 @@ class RavenHandler extends AbstractProcessingHandler
/**
* @param Raven_Client $ravenClient
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
{
@trigger_error('The Monolog\Handler\RavenHandler class is deprecated. You should rather upgrade to the sentry/sentry 2.x and use Sentry\Monolog\Handler, see https://github.com/getsentry/sentry-php/blob/master/src/Monolog/Handler.php', E_USER_DEPRECATED);
parent::__construct($level, $bubble);
$this->ravenClient = $ravenClient;
... ... @@ -86,7 +84,7 @@ class RavenHandler extends AbstractProcessingHandler
// the record with the highest severity is the "main" one
$record = array_reduce($records, function ($highest, $record) {
if (null === $highest || $record['level'] > $highest['level']) {
if ($record['level'] > $highest['level']) {
return $record;
}
... ... @@ -182,7 +180,7 @@ class RavenHandler extends AbstractProcessingHandler
}
if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
$options['message'] = $record['formatted'];
$options['extra']['message'] = $record['formatted'];
$this->ravenClient->captureException($record['context']['exception'], $options);
} else {
$this->ravenClient->captureMessage($record['formatted'], array(), $options);
... ... @@ -218,12 +216,11 @@ class RavenHandler extends AbstractProcessingHandler
*/
protected function getExtraParameters()
{
return array('contexts', 'checksum', 'release', 'event_id');
return array('checksum', 'release');
}
/**
* @param string $value
* @return self
*/
public function setRelease($value)
{
... ...
... ... @@ -73,8 +73,7 @@ class RedisHandler extends AbstractProcessingHandler
protected function writeCapped(array $record)
{
if ($this->redisClient instanceof \Redis) {
$mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1;
$this->redisClient->multi($mode)
$this->redisClient->multi()
->rpush($this->redisKey, $record["formatted"])
->ltrim($this->redisKey, -$this->capSize, -1)
->exec();
... ...
... ... @@ -97,7 +97,6 @@ class RollbarHandler extends AbstractProcessingHandler
));
if (isset($context['exception']) && $context['exception'] instanceof Exception) {
$payload['level'] = $context['level'];
$exception = $context['exception'];
unset($context['exception']);
... ... @@ -129,16 +128,4 @@ class RollbarHandler extends AbstractProcessingHandler
{
$this->flush();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->flush();
parent::reset();
}
}
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Utils;
/**
* Stores logs to files that are rotated every day and a limited number of files are kept.
... ... @@ -40,13 +39,13 @@ class RotatingFileHandler extends StreamHandler
* @param string $filename
* @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
* @param Boolean $useLocking Try to lock log file before doing any writes
*/
public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
{
$this->filename = Utils::canonicalizePath($filename);
$this->filename = $filename;
$this->maxFiles = (int) $maxFiles;
$this->nextRotation = new \DateTime('tomorrow');
$this->filenameFormat = '{filename}-{date}';
... ... @@ -67,18 +66,6 @@ class RotatingFileHandler extends StreamHandler
}
}
/**
* {@inheritdoc}
*/
public function reset()
{
parent::reset();
if (true === $this->mustRotate) {
$this->rotate();
}
}
public function setFilenameFormat($filenameFormat, $dateFormat)
{
if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
... ... @@ -179,7 +166,7 @@ class RotatingFileHandler extends StreamHandler
$fileInfo = pathinfo($this->filename);
$glob = str_replace(
array('{filename}', '{date}'),
array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'),
array($fileInfo['filename'], '*'),
$fileInfo['dirname'] . '/' . $this->filenameFormat
);
if (!empty($fileInfo['extension'])) {
... ...
... ... @@ -11,8 +11,6 @@
namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
/**
* Sampling handler
*
... ... @@ -40,7 +38,7 @@ class SamplingHandler extends AbstractHandler
protected $factor;
/**
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler).
* @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
* @param int $factor Sample factor
*/
public function __construct($handler, $factor)
... ... @@ -56,58 +54,29 @@ class SamplingHandler extends AbstractHandler
public function isHandling(array $record)
{
return $this->getHandler($record)->isHandling($record);
return $this->handler->isHandling($record);
}
public function handle(array $record)
{
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
// The same logic as in FingersCrossedHandler
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
}
$this->getHandler($record)->handle($record);
$this->handler->handle($record);
}
return false === $this->bubble;
}
/**
* Return the nested handler
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*/
public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}
return $this->handler;
}
/**
* {@inheritdoc}
*/
public function setFormatter(FormatterInterface $formatter)
{
$this->getHandler()->setFormatter($formatter);
return $this;
}
/**
* {@inheritdoc}
*/
public function getFormatter()
{
return $this->getHandler()->getFormatter();
}
}
... ...
... ... @@ -12,8 +12,7 @@
namespace Monolog\Handler\Slack;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
/**
... ... @@ -42,15 +41,15 @@ class SlackRecord
/**
* Name of a bot
* @var string|null
* @var string
*/
private $username;
/**
* User icon e.g. 'ghost', 'http://example.com/user.png'
* Emoji icon name
* @var string
*/
private $userIcon;
private $iconEmoji;
/**
* Whether the message should be added to Slack as attachment (plain text otherwise)
... ... @@ -71,51 +70,42 @@ class SlackRecord
private $includeContextAndExtra;
/**
* Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
* @var array
*/
private $excludeFields;
/**
* @var FormatterInterface
*/
private $formatter;
/**
* @var NormalizerFormatter
* @var LineFormatter
*/
private $normalizerFormatter;
private $lineFormatter;
public function __construct($channel = null, $username = null, $useAttachment = true, $userIcon = null, $useShortAttachment = false, $includeContextAndExtra = false, array $excludeFields = array(), FormatterInterface $formatter = null)
public function __construct($channel = null, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeContextAndExtra = false, FormatterInterface $formatter = null)
{
$this->channel = $channel;
$this->username = $username;
$this->userIcon = trim($userIcon, ':');
$this->iconEmoji = trim($iconEmoji, ':');
$this->useAttachment = $useAttachment;
$this->useShortAttachment = $useShortAttachment;
$this->includeContextAndExtra = $includeContextAndExtra;
$this->excludeFields = $excludeFields;
$this->formatter = $formatter;
if ($this->includeContextAndExtra) {
$this->normalizerFormatter = new NormalizerFormatter();
$this->lineFormatter = new LineFormatter();
}
}
public function getSlackData(array $record)
{
$dataArray = array();
$record = $this->excludeFields($record);
if ($this->username) {
$dataArray['username'] = $this->username;
}
$dataArray = array(
'username' => $this->username,
'text' => '',
);
if ($this->channel) {
$dataArray['channel'] = $this->channel;
}
if ($this->formatter && !$this->useAttachment) {
if ($this->formatter) {
$message = $this->formatter->format($record);
} else {
$message = $record['message'];
... ... @@ -123,22 +113,19 @@ class SlackRecord
if ($this->useAttachment) {
$attachment = array(
'fallback' => $message,
'text' => $message,
'color' => $this->getAttachmentColor($record['level']),
'fields' => array(),
'mrkdwn_in' => array('fields'),
'ts' => $record['datetime']->getTimestamp()
'fallback' => $message,
'text' => $message,
'color' => $this->getAttachmentColor($record['level']),
'fields' => array(),
);
if ($this->useShortAttachment) {
$attachment['title'] = $record['level_name'];
} else {
$attachment['title'] = 'Message';
$attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']);
$attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name'], true);
}
if ($this->includeContextAndExtra) {
foreach (array('extra', 'context') as $key) {
if (empty($record[$key])) {
... ... @@ -147,8 +134,9 @@ class SlackRecord
if ($this->useShortAttachment) {
$attachment['fields'][] = $this->generateAttachmentField(
$key,
$record[$key]
ucfirst($key),
$this->stringify($record[$key]),
true
);
} else {
// Add all extra fields as individual fields in attachment
... ... @@ -165,12 +153,8 @@ class SlackRecord
$dataArray['text'] = $message;
}
if ($this->userIcon) {
if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) {
$dataArray['icon_url'] = $this->userIcon;
} else {
$dataArray['icon_emoji'] = ":{$this->userIcon}:";
}
if ($this->iconEmoji) {
$dataArray['icon_emoji'] = ":{$this->iconEmoji}:";
}
return $dataArray;
... ... @@ -200,25 +184,23 @@ class SlackRecord
/**
* Stringifies an array of key/value pairs to be used in attachment fields
*
* @param array $fields
*
* @return string
* @param array $fields
* @return string|null
*/
public function stringify($fields)
{
$normalized = $this->normalizerFormatter->format($fields);
$prettyPrintFlag = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 128;
$flags = 0;
if (PHP_VERSION_ID >= 50400) {
$flags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
if (!$this->lineFormatter) {
return null;
}
$string = '';
foreach ($fields as $var => $val) {
$string .= $var.': '.$this->lineFormatter->stringify($val)." | ";
}
$hasSecondDimension = count(array_filter($normalized, 'is_array'));
$hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
$string = rtrim($string, " |");
return $hasSecondDimension || $hasNonNumericKeys
? Utils::jsonEncode($normalized, $prettyPrintFlag | $flags)
: Utils::jsonEncode($normalized, $flags);
return $string;
}
/**
... ... @@ -234,21 +216,17 @@ class SlackRecord
/**
* Generates attachment field
*
* @param string $title
* @param string $title
* @param string|array $value
*
* @param bool $short
* @return array
*/
private function generateAttachmentField($title, $value)
private function generateAttachmentField($title, $value, $short)
{
$value = is_array($value)
? sprintf('```%s```', $this->stringify($value))
: $value;
return array(
'title' => ucfirst($title),
'value' => $value,
'short' => false
'title' => $title,
'value' => is_array($value) ? $this->lineFormatter->stringify($value) : $value,
'short' => $short
);
}
... ... @@ -256,44 +234,15 @@ class SlackRecord
* Generates a collection of attachment fields from array
*
* @param array $data
*
* @return array
*/
private function generateAttachmentFields(array $data)
{
$fields = array();
foreach ($this->normalizerFormatter->format($data) as $key => $value) {
$fields[] = $this->generateAttachmentField($key, $value);
foreach ($data as $key => $value) {
$fields[] = $this->generateAttachmentField($key, $value, false);
}
return $fields;
}
/**
* Get a copy of record with fields excluded according to $this->excludeFields
*
* @param array $record
*
* @return array
*/
private function excludeFields(array $record)
{
foreach ($this->excludeFields as $field) {
$keys = explode('.', $field);
$node = &$record;
$lastKey = end($keys);
foreach ($keys as $key) {
if (!isset($node[$key])) {
break;
}
if ($lastKey === $key) {
unset($node[$key]);
break;
}
$node = &$node[$key];
}
}
return $record;
}
}
... ...
... ... @@ -13,7 +13,6 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord;
/**
... ... @@ -39,17 +38,16 @@ class SlackHandler extends SocketHandler
/**
* @param string $token Slack API token
* @param string $channel Slack channel (encoded ID or name)
* @param string|null $username Name of a bot
* @param string $username Name of a bot
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
* @param string|null $iconEmoji The emoji name to use (or null)
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
* @param array $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
* @throws MissingExtensionException If no OpenSSL PHP extension configured
*/
public function __construct($token, $channel, $username = null, $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false, array $excludeFields = array())
public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false)
{
if (!extension_loaded('openssl')) {
throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
... ... @@ -64,7 +62,6 @@ class SlackHandler extends SocketHandler
$iconEmoji,
$useShortAttachment,
$includeContextAndExtra,
$excludeFields,
$this->formatter
);
... ... @@ -76,11 +73,6 @@ class SlackHandler extends SocketHandler
return $this->slackRecord;
}
public function getToken()
{
return $this->token;
}
/**
* {@inheritdoc}
*
... ... @@ -119,7 +111,7 @@ class SlackHandler extends SocketHandler
$dataArray['token'] = $this->token;
if (!empty($dataArray['attachments'])) {
$dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']);
$dataArray['attachments'] = json_encode($dataArray['attachments']);
}
return $dataArray;
... ... @@ -150,17 +142,6 @@ class SlackHandler extends SocketHandler
protected function write(array $record)
{
parent::write($record);
$this->finalizeWrite();
}
/**
* Finalizes the request by reading some bytes and then closing the socket
*
* If we do not read some but close the socket too early, slack sometimes
* drops the request entirely.
*/
protected function finalizeWrite()
{
$res = $this->getResource();
if (is_resource($res)) {
@fread($res, 2048);
... ...
... ... @@ -13,7 +13,6 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord;
/**
... ... @@ -39,16 +38,15 @@ class SlackWebhookHandler extends AbstractProcessingHandler
/**
* @param string $webhookUrl Slack Webhook URL
* @param string|null $channel Slack channel (encoded ID or name)
* @param string|null $username Name of a bot
* @param string $username Name of a bot
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
* @param string|null $iconEmoji The emoji name to use (or null)
* @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param array $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
*/
public function __construct($webhookUrl, $channel = null, $username = null, $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeContextAndExtra = false, $level = Logger::CRITICAL, $bubble = true, array $excludeFields = array())
public function __construct($webhookUrl, $channel = null, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeContextAndExtra = false, $level = Logger::CRITICAL, $bubble = true)
{
parent::__construct($level, $bubble);
... ... @@ -61,7 +59,6 @@ class SlackWebhookHandler extends AbstractProcessingHandler
$iconEmoji,
$useShortAttachment,
$includeContextAndExtra,
$excludeFields,
$this->formatter
);
}
... ... @@ -71,11 +68,6 @@ class SlackWebhookHandler extends AbstractProcessingHandler
return $this->slackRecord;
}
public function getWebhookUrl()
{
return $this->webhookUrl;
}
/**
* {@inheritdoc}
*
... ... @@ -84,21 +76,16 @@ class SlackWebhookHandler extends AbstractProcessingHandler
protected function write(array $record)
{
$postData = $this->slackRecord->getSlackData($record);
$postString = Utils::jsonEncode($postData);
$postString = json_encode($postData);
$ch = curl_init();
$options = array(
CURLOPT_URL => $this->webhookUrl,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json'),
CURLOPT_POSTFIELDS => $postString
);
curl_setopt($ch, CURLOPT_URL, $this->webhookUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if (defined('CURLOPT_SAFE_UPLOAD')) {
$options[CURLOPT_SAFE_UPLOAD] = true;
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
}
curl_setopt_array($ch, $options);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('payload' => $postString));
Curl\Util::execute($ch);
}
... ...
... ... @@ -16,11 +16,8 @@ use Monolog\Logger;
/**
* Sends notifications through Slack's Slackbot
*
* @author Haralan Dobrev <hkdobrev@gmail.com>
* @see https://slack.com/apps/A0F81R8ET-slackbot
* @deprecated According to Slack the API used on this handler it is deprecated.
* Therefore this handler will be removed on 2.x
* Slack suggests to use webhooks instead. Please contact slack for more information.
* @author Haralan Dobrev <hkdobrev@gmail.com>
* @see https://slack.com/apps/A0F81R8ET-slackbot
*/
class SlackbotHandler extends AbstractProcessingHandler
{
... ... @@ -51,7 +48,6 @@ class SlackbotHandler extends AbstractProcessingHandler
*/
public function __construct($slackTeam, $token, $channel, $level = Logger::CRITICAL, $bubble = true)
{
@trigger_error('SlackbotHandler is deprecated and will be removed on 2.x', E_USER_DEPRECATED);
parent::__construct($level, $bubble);
$this->slackTeam = $slackTeam;
... ...
... ... @@ -27,16 +27,15 @@ class SocketHandler extends AbstractProcessingHandler
private $timeout = 0;
private $writingTimeout = 10;
private $lastSentBytes = null;
private $chunkSize = null;
private $persistent = false;
private $errno;
private $errstr;
private $lastWritingAt;
/**
* @param string $connectionString Socket connection string
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string $connectionString Socket connection string
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true)
{
... ... @@ -88,7 +87,7 @@ class SocketHandler extends AbstractProcessingHandler
*/
public function setPersistent($persistent)
{
$this->persistent = (bool) $persistent;
$this->persistent = (boolean) $persistent;
}
/**
... ... @@ -129,16 +128,6 @@ class SocketHandler extends AbstractProcessingHandler
}
/**
* Set chunk size. Only has effect during connection in the writing cycle.
*
* @param float $bytes
*/
public function setChunkSize($bytes)
{
$this->chunkSize = $bytes;
}
/**
* Get current connection string
*
* @return string
... ... @@ -189,16 +178,6 @@ class SocketHandler extends AbstractProcessingHandler
}
/**
* Get current chunk size
*
* @return float
*/
public function getChunkSize()
{
return $this->chunkSize;
}
/**
* Check to see if the socket is currently available.
*
* UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details.
... ... @@ -242,16 +221,6 @@ class SocketHandler extends AbstractProcessingHandler
/**
* Wrapper to allow mocking
*
* @see http://php.net/manual/en/function.stream-set-chunk-size.php
*/
protected function streamSetChunkSize()
{
return stream_set_chunk_size($this->resource, $this->chunkSize);
}
/**
* Wrapper to allow mocking
*/
protected function fwrite($data)
{
... ... @@ -299,7 +268,6 @@ class SocketHandler extends AbstractProcessingHandler
{
$this->createSocketResource();
$this->setSocketTimeout();
$this->setStreamChunkSize();
}
private function createSocketResource()
... ... @@ -322,13 +290,6 @@ class SocketHandler extends AbstractProcessingHandler
}
}
private function setStreamChunkSize()
{
if ($this->chunkSize && !$this->streamSetChunkSize()) {
throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
}
}
private function writeToSocket($data)
{
$length = strlen($data);
... ...
... ... @@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Utils;
/**
* Stores to any stream resource
... ... @@ -33,9 +32,9 @@ class StreamHandler extends AbstractProcessingHandler
/**
* @param resource|string $stream
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
* @param Boolean $useLocking Try to lock log file before doing any writes
*
* @throws \Exception If a missing directory is not buildable
* @throws \InvalidArgumentException If stream is not a resource or string
... ... @@ -46,7 +45,7 @@ class StreamHandler extends AbstractProcessingHandler
if (is_resource($stream)) {
$this->stream = $stream;
} elseif (is_string($stream)) {
$this->url = Utils::canonicalizePath($stream);
$this->url = $stream;
} else {
throw new \InvalidArgumentException('A stream must either be a resource or a string.');
}
... ... @@ -64,7 +63,6 @@ class StreamHandler extends AbstractProcessingHandler
fclose($this->stream);
}
$this->stream = null;
$this->dirCreated = null;
}
/**
... ... @@ -106,8 +104,7 @@ class StreamHandler extends AbstractProcessingHandler
restore_error_handler();
if (!is_resource($this->stream)) {
$this->stream = null;
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $this->url));
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url));
}
}
... ... @@ -170,7 +167,7 @@ class StreamHandler extends AbstractProcessingHandler
set_error_handler(array($this, 'customErrorHandler'));
$status = mkdir($dir, 0777, true);
restore_error_handler();
if (false === $status && !is_dir($dir)) {
if (false === $status) {
throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir));
}
}
... ...
... ... @@ -12,9 +12,7 @@
namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Swift;
/**
* SwiftMailerHandler uses Swift_Mailer to send the emails
... ... @@ -30,7 +28,7 @@ class SwiftMailerHandler extends MailHandler
* @param \Swift_Mailer $mailer The mailer to use
* @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true)
{
... ... @@ -49,17 +47,6 @@ class SwiftMailerHandler extends MailHandler
}
/**
* Gets the formatter for the Swift_Message subject.
*
* @param string $format The format of the subject
* @return FormatterInterface
*/
protected function getSubjectFormatter($format)
{
return new LineFormatter($format);
}
/**
* Creates instance of Swift_Message to be sent
*
* @param string $content formatted email body to be sent
... ... @@ -81,16 +68,12 @@ class SwiftMailerHandler extends MailHandler
}
if ($records) {
$subjectFormatter = $this->getSubjectFormatter($message->getSubject());
$subjectFormatter = new LineFormatter($message->getSubject());
$message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
}
$message->setBody($content);
if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
$message->setDate(new \DateTimeImmutable());
} else {
$message->setDate(time());
}
$message->setDate(time());
return $message;
}
... ...
... ... @@ -32,11 +32,11 @@ class SyslogHandler extends AbstractSyslogHandler
protected $logopts;
/**
* @param string $ident
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
* @param string $ident
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
* @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
*/
public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID)
{
... ...
... ... @@ -18,38 +18,22 @@ use Monolog\Handler\SyslogUdp\UdpSocket;
* A Handler for logging to a remote syslogd server.
*
* @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com>
* @author Dominik Kukacka <dominik.kukacka@gmail.com>
*/
class SyslogUdpHandler extends AbstractSyslogHandler
{
const RFC3164 = 0;
const RFC5424 = 1;
private $dateFormats = array(
self::RFC3164 => 'M d H:i:s',
self::RFC5424 => \DateTime::RFC3339,
);
protected $socket;
protected $ident;
protected $rfc;
/**
* @param string $host
* @param int $port
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string $ident Program name or tag for each log message.
* @param int $rfc RFC to format the message for.
* @param string $host
* @param int $port
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $ident = 'php', $rfc = self::RFC5424)
public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true)
{
parent::__construct($facility, $level, $bubble);
$this->ident = $ident;
$this->rfc = $rfc;
$this->socket = new UdpSocket($host, $port ?: 514);
}
... ... @@ -79,39 +63,13 @@ class SyslogUdpHandler extends AbstractSyslogHandler
}
/**
* Make common syslog header (see rfc5424 or rfc3164)
* Make common syslog header (see rfc5424)
*/
protected function makeCommonSyslogHeader($severity)
{
$priority = $severity + $this->facility;
if (!$pid = getmypid()) {
$pid = '-';
}
if (!$hostname = gethostname()) {
$hostname = '-';
}
$date = $this->getDateTime();
if ($this->rfc === self::RFC3164) {
return "<$priority>" .
$date . " " .
$hostname . " " .
$this->ident . "[" . $pid . "]: ";
} else {
return "<$priority>1 " .
$date . " " .
$hostname . " " .
$this->ident . " " .
$pid . " - - ";
}
}
protected function getDateTime()
{
return date($this->dateFormats[$this->rfc]);
return "<$priority>1 ";
}
/**
... ...
... ... @@ -67,7 +67,6 @@ class TestHandler extends AbstractProcessingHandler
{
protected $records = array();
protected $recordsByLevel = array();
private $skipReset = false;
public function getRecords()
{
... ... @@ -80,41 +79,19 @@ class TestHandler extends AbstractProcessingHandler
$this->recordsByLevel = array();
}
public function reset()
{
if (!$this->skipReset) {
$this->clear();
}
}
public function setSkipReset($skipReset)
{
$this->skipReset = $skipReset;
}
public function hasRecords($level)
{
return isset($this->recordsByLevel[$level]);
}
/**
* @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records
* @param int $level Logger::LEVEL constant value
*/
public function hasRecord($record, $level)
{
if (is_string($record)) {
$record = array('message' => $record);
if (is_array($record)) {
$record = $record['message'];
}
return $this->hasRecordThatPasses(function ($rec) use ($record) {
if ($rec['message'] !== $record['message']) {
return false;
}
if (isset($record['context']) && $rec['context'] !== $record['context']) {
return false;
}
return true;
return $rec['message'] === $record;
}, $level);
}
... ...
... ... @@ -48,17 +48,6 @@ class WhatFailureGroupHandler extends GroupHandler
*/
public function handleBatch(array $records)
{
if ($this->processors) {
$processed = array();
foreach ($records as $record) {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
$processed[] = $record;
}
$records = $processed;
}
foreach ($this->handlers as $handler) {
try {
$handler->handleBatch($records);
... ...
... ... @@ -17,7 +17,6 @@ use Monolog\Logger;
* Handler sending logs to Zend Monitor
*
* @author Christian Bergau <cbergau86@gmail.com>
* @author Jason Davis <happydude@jasondavis.net>
*/
class ZendMonitorHandler extends AbstractProcessingHandler
{
... ... @@ -26,7 +25,16 @@ class ZendMonitorHandler extends AbstractProcessingHandler
*
* @var array
*/
protected $levelMap = array();
protected $levelMap = array(
Logger::DEBUG => 1,
Logger::INFO => 2,
Logger::NOTICE => 3,
Logger::WARNING => 4,
Logger::ERROR => 5,
Logger::CRITICAL => 6,
Logger::ALERT => 7,
Logger::EMERGENCY => 0,
);
/**
* Construct
... ... @@ -38,21 +46,8 @@ class ZendMonitorHandler extends AbstractProcessingHandler
public function __construct($level = Logger::DEBUG, $bubble = true)
{
if (!function_exists('zend_monitor_custom_event')) {
throw new MissingExtensionException(
'You must have Zend Server installed with Zend Monitor enabled in order to use this handler'
);
throw new MissingExtensionException('You must have Zend Server installed in order to use this handler');
}
//zend monitor constants are not defined if zend monitor is not enabled.
$this->levelMap = array(
Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
Logger::WARNING => \ZEND_MONITOR_EVENT_SEVERITY_WARNING,
Logger::ERROR => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
);
parent::__construct($level, $bubble);
}
... ... @@ -62,23 +57,22 @@ class ZendMonitorHandler extends AbstractProcessingHandler
protected function write(array $record)
{
$this->writeZendMonitorCustomEvent(
Logger::getLevelName($record['level']),
$this->levelMap[$record['level']],
$record['message'],
$record['formatted'],
$this->levelMap[$record['level']]
$record['formatted']
);
}
/**
* Write to Zend Monitor Events
* @param string $type Text displayed in "Class Name (custom)" field
* @param string $message Text displayed in "Error String"
* @param mixed $formatted Displayed in Custom Variables tab
* @param int $severity Set the event severity level (-1,0,1)
* Write a record to Zend Monitor
*
* @param int $level
* @param string $message
* @param array $formatted
*/
protected function writeZendMonitorCustomEvent($type, $message, $formatted, $severity)
protected function writeZendMonitorCustomEvent($level, $message, $formatted)
{
zend_monitor_custom_event($type, $message, $formatted, $severity);
zend_monitor_custom_event($level, $message, $formatted);
}
/**
... ...
... ... @@ -15,7 +15,6 @@ use Monolog\Handler\HandlerInterface;
use Monolog\Handler\StreamHandler;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;
use Exception;
/**
* Monolog log channel
... ... @@ -25,7 +24,7 @@ use Exception;
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class Logger implements LoggerInterface, ResettableInterface
class Logger implements LoggerInterface
{
/**
* Detailed debug information
... ... @@ -135,11 +134,6 @@ class Logger implements LoggerInterface, ResettableInterface
protected $microsecondTimestamps = true;
/**
* @var callable
*/
protected $exceptionHandler;
/**
* @param string $name The logging channel
* @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
* @param callable[] $processors Optional array of processors
... ... @@ -147,7 +141,7 @@ class Logger implements LoggerInterface, ResettableInterface
public function __construct($name, array $handlers = array(), array $processors = array())
{
$this->name = $name;
$this->setHandlers($handlers);
$this->handlers = $handlers;
$this->processors = $processors;
}
... ... @@ -287,7 +281,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param int $level The logging level
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @return Boolean Whether the record has been processed
*/
public function addRecord($level, $message, array $context = array())
{
... ... @@ -335,75 +329,27 @@ class Logger implements LoggerInterface, ResettableInterface
'extra' => array(),
);
try {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
while ($handler = current($this->handlers)) {
if (true === $handler->handle($record)) {
break;
}
next($this->handlers);
}
} catch (Exception $e) {
$this->handleException($e, $record);
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
return true;
}
/**
* Ends a log cycle and frees all resources used by handlers.
*
* Closing a Handler means flushing all buffers and freeing any open resources/handles.
* Handlers that have been closed should be able to accept log records again and re-open
* themselves on demand, but this may not always be possible depending on implementation.
*
* This is useful at the end of a request and will be called automatically on every handler
* when they get destructed.
*/
public function close()
{
foreach ($this->handlers as $handler) {
if (method_exists($handler, 'close')) {
$handler->close();
while ($handler = current($this->handlers)) {
if (true === $handler->handle($record)) {
break;
}
}
}
/**
* Ends a log cycle and resets all handlers and processors to their initial state.
*
* Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
* state, and getting it back to a state in which it can receive log records again.
*
* This is useful in case you want to avoid logs leaking between two requests or jobs when you
* have a long running process like a worker or an application server serving multiple requests
* in one process.
*/
public function reset()
{
foreach ($this->handlers as $handler) {
if ($handler instanceof ResettableInterface) {
$handler->reset();
}
next($this->handlers);
}
foreach ($this->processors as $processor) {
if ($processor instanceof ResettableInterface) {
$processor->reset();
}
}
return true;
}
/**
* Adds a log record at the DEBUG level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addDebug($message, array $context = array())
{
... ... @@ -413,9 +359,9 @@ class Logger implements LoggerInterface, ResettableInterface
/**
* Adds a log record at the INFO level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addInfo($message, array $context = array())
{
... ... @@ -425,9 +371,9 @@ class Logger implements LoggerInterface, ResettableInterface
/**
* Adds a log record at the NOTICE level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addNotice($message, array $context = array())
{
... ... @@ -437,9 +383,9 @@ class Logger implements LoggerInterface, ResettableInterface
/**
* Adds a log record at the WARNING level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addWarning($message, array $context = array())
{
... ... @@ -449,9 +395,9 @@ class Logger implements LoggerInterface, ResettableInterface
/**
* Adds a log record at the ERROR level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addError($message, array $context = array())
{
... ... @@ -461,9 +407,9 @@ class Logger implements LoggerInterface, ResettableInterface
/**
* Adds a log record at the CRITICAL level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addCritical($message, array $context = array())
{
... ... @@ -473,9 +419,9 @@ class Logger implements LoggerInterface, ResettableInterface
/**
* Adds a log record at the ALERT level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addAlert($message, array $context = array())
{
... ... @@ -485,9 +431,9 @@ class Logger implements LoggerInterface, ResettableInterface
/**
* Adds a log record at the EMERGENCY level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function addEmergency($message, array $context = array())
{
... ... @@ -527,13 +473,8 @@ class Logger implements LoggerInterface, ResettableInterface
*/
public static function toMonologLevel($level)
{
if (is_string($level)) {
// Contains chars of all log levels and avoids using strtoupper() which may have
// strange results depending on locale (for example, "i" will become "İ")
$upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY');
if (defined(__CLASS__.'::'.$upper)) {
return constant(__CLASS__ . '::' . $upper);
}
if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) {
return constant(__CLASS__.'::'.strtoupper($level));
}
return $level;
... ... @@ -543,7 +484,7 @@ class Logger implements LoggerInterface, ResettableInterface
* Checks whether the Logger has a handler that listens on the given level
*
* @param int $level
* @return bool
* @return Boolean
*/
public function isHandling($level)
{
... ... @@ -561,51 +502,14 @@ class Logger implements LoggerInterface, ResettableInterface
}
/**
* Set a custom exception handler
*
* @param callable $callback
* @return $this
*/
public function setExceptionHandler($callback)
{
if (!is_callable($callback)) {
throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callback, true).' given');
}
$this->exceptionHandler = $callback;
return $this;
}
/**
* @return callable
*/
public function getExceptionHandler()
{
return $this->exceptionHandler;
}
/**
* Delegates exception management to the custom exception handler,
* or throws the exception if no custom handler is set.
*/
protected function handleException(Exception $e, array $record)
{
if (!$this->exceptionHandler) {
throw $e;
}
call_user_func($this->exceptionHandler, $e, $record);
}
/**
* Adds a log record at an arbitrary level.
*
* This method allows for compatibility with common interfaces.
*
* @param mixed $level The log level
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function log($level, $message, array $context = array())
{
... ... @@ -619,9 +523,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function debug($message, array $context = array())
{
... ... @@ -633,9 +537,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function info($message, array $context = array())
{
... ... @@ -647,9 +551,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function notice($message, array $context = array())
{
... ... @@ -661,9 +565,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function warn($message, array $context = array())
{
... ... @@ -675,9 +579,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function warning($message, array $context = array())
{
... ... @@ -689,9 +593,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function err($message, array $context = array())
{
... ... @@ -703,9 +607,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function error($message, array $context = array())
{
... ... @@ -717,9 +621,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function crit($message, array $context = array())
{
... ... @@ -731,9 +635,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function critical($message, array $context = array())
{
... ... @@ -745,9 +649,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function alert($message, array $context = array())
{
... ... @@ -759,9 +663,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function emerg($message, array $context = array())
{
... ... @@ -773,9 +677,9 @@ class Logger implements LoggerInterface, ResettableInterface
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string $message The log message
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
public function emergency($message, array $context = array())
{
... ...
... ... @@ -19,7 +19,7 @@ use Monolog\Logger;
* @author Nick Otter
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class GitProcessor implements ProcessorInterface
class GitProcessor
{
private $level;
private static $cache;
... ... @@ -52,7 +52,7 @@ class GitProcessor implements ProcessorInterface
}
$branches = `git branch -v --no-abbrev`;
if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
return self::$cache = array(
'branch' => $matches[1],
'commit' => $matches[2],
... ...
... ... @@ -24,7 +24,7 @@ use Monolog\Logger;
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class IntrospectionProcessor implements ProcessorInterface
class IntrospectionProcessor
{
private $level;
... ... @@ -55,12 +55,7 @@ class IntrospectionProcessor implements ProcessorInterface
return $record;
}
/*
* http://php.net/manual/en/function.debug-backtrace.php
* As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added.
* Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'.
*/
$trace = debug_backtrace((PHP_VERSION_ID < 50306) ? 2 : DEBUG_BACKTRACE_IGNORE_ARGS);
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// skip first since it's always the current method
array_shift($trace);
... ...
... ... @@ -16,7 +16,7 @@ namespace Monolog\Processor;
*
* @author Rob Jensen
*/
abstract class MemoryProcessor implements ProcessorInterface
abstract class MemoryProcessor
{
/**
* @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported.
... ... @@ -34,8 +34,8 @@ abstract class MemoryProcessor implements ProcessorInterface
*/
public function __construct($realUsage = true, $useFormatting = true)
{
$this->realUsage = (bool) $realUsage;
$this->useFormatting = (bool) $useFormatting;
$this->realUsage = (boolean) $realUsage;
$this->useFormatting = (boolean) $useFormatting;
}
/**
... ...
... ... @@ -18,7 +18,7 @@ use Monolog\Logger;
*
* @author Jonathan A. Schweder <jonathanschweder@gmail.com>
*/
class MercurialProcessor implements ProcessorInterface
class MercurialProcessor
{
private $level;
private static $cache;
... ...
... ... @@ -16,7 +16,7 @@ namespace Monolog\Processor;
*
* @author Andreas Hörnicke
*/
class ProcessIdProcessor implements ProcessorInterface
class ProcessIdProcessor
{
/**
* @param array $record
... ...
... ... @@ -11,8 +11,6 @@
namespace Monolog\Processor;
use Monolog\Utils;
/**
* Processes a record's message according to PSR-3 rules
*
... ... @@ -20,7 +18,7 @@ use Monolog\Utils;
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class PsrLogMessageProcessor implements ProcessorInterface
class PsrLogMessageProcessor
{
/**
* @param array $record
... ... @@ -37,7 +35,7 @@ class PsrLogMessageProcessor implements ProcessorInterface
if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
$replacements['{'.$key.'}'] = $val;
} elseif (is_object($val)) {
$replacements['{'.$key.'}'] = '[object '.Utils::getClass($val).']';
$replacements['{'.$key.'}'] = '[object '.get_class($val).']';
} else {
$replacements['{'.$key.'}'] = '['.gettype($val).']';
}
... ...
... ... @@ -16,7 +16,7 @@ namespace Monolog\Processor;
*
* @author Martijn Riemers
*/
class TagProcessor implements ProcessorInterface
class TagProcessor
{
private $tags;
... ...
... ... @@ -11,14 +11,12 @@
namespace Monolog\Processor;
use Monolog\ResettableInterface;
/**
* Adds a unique identifier into records
*
* @author Simon Mönch <sm@webfactory.de>
*/
class UidProcessor implements ProcessorInterface, ResettableInterface
class UidProcessor
{
private $uid;
... ... @@ -28,8 +26,7 @@ class UidProcessor implements ProcessorInterface, ResettableInterface
throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
}
$this->uid = $this->generateUid($length);
$this->uid = substr(hash('md5', uniqid('', true)), 0, $length);
}
public function __invoke(array $record)
... ... @@ -46,14 +43,4 @@ class UidProcessor implements ProcessorInterface, ResettableInterface
{
return $this->uid;
}
public function reset()
{
$this->uid = $this->generateUid(strlen($this->uid));
}
private function generateUid($length)
{
return substr(hash('md5', uniqid('', true)), 0, $length);
}
}
... ...
... ... @@ -16,7 +16,7 @@ namespace Monolog\Processor;
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class WebProcessor implements ProcessorInterface
class WebProcessor
{
/**
* @var array|\ArrayAccess
... ... @@ -52,10 +52,6 @@ class WebProcessor implements ProcessorInterface
throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.');
}
if (isset($this->serverData['UNIQUE_ID'])) {
$this->extraFields['unique_id'] = 'UNIQUE_ID';
}
if (null !== $extraFields) {
if (isset($extraFields[0])) {
foreach (array_keys($this->extraFields) as $fieldName) {
... ... @@ -108,6 +104,10 @@ class WebProcessor implements ProcessorInterface
$extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null;
}
if (isset($this->serverData['UNIQUE_ID'])) {
$extra['unique_id'] = $this->serverData['UNIQUE_ID'];
}
return $extra;
}
}
... ...
<?php
/*
* 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;
/**
* Handler or Processor implementing this interface will be reset when Logger::reset() is called.
*
* Resetting ends a log cycle gets them back to their initial state.
*
* Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
* state, and getting it back to a state in which it can receive log records again.
*
* This is useful in case you want to avoid logs leaking between two requests or jobs when you
* have a long running process like a worker or an application server serving multiple requests
* in one process.
*
* @author Grégoire Pineau <lyrixx@lyrixx.info>
*/
interface ResettableInterface
{
public function reset();
}