1
0
mirror of https://github.com/Seldaek/monolog.git synced 2025-07-30 18:00:17 +02:00

Remove RavenHandler as it is deprecated in 1.x

This commit is contained in:
Jordi Boggiano
2019-07-06 13:23:58 +02:00
parent aa7416cbe8
commit 0c3811c8b1
6 changed files with 6 additions and 639 deletions

View File

@@ -29,12 +29,10 @@
"predis/predis": "^1.1",
"rollbar/rollbar": "^1.3",
"ruflin/elastica": ">=0.90 <3.0",
"sentry/sentry": "^1.9",
"swiftmailer/swiftmailer": "^5.3|^6.0"
},
"suggest": {
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"sentry/sentry": "Allow sending log messages to a Sentry server",
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",

View File

@@ -45,13 +45,11 @@
- [_SocketHandler_](../src/Monolog/Handler/SocketHandler.php): Logs records to [sockets](http://php.net/fsockopen), use this
for UNIX and TCP sockets. See an [example](sockets.md).
- [_AmqpHandler_](../src/Monolog/Handler/AmqpHandler.php): Logs records to an [AMQP](http://www.amqp.org/) compatible
server. Requires the [php-amqp](http://pecl.php.net/package/amqp) extension (1.0+) or
server. Requires the [php-amqp](http://pecl.php.net/package/amqp) extension (1.0+) or
[php-amqplib](https://github.com/php-amqplib/php-amqplib) library.
- [_GelfHandler_](../src/Monolog/Handler/GelfHandler.php): Logs records to a [Graylog2](http://www.graylog2.org) server.
Requires package [graylog2/gelf-php](https://github.com/bzikarsky/gelf-php).
- [_CubeHandler_](../src/Monolog/Handler/CubeHandler.php): Logs records to a [Cube](http://square.github.com/cube/) server.
- [_RavenHandler_](../src/Monolog/Handler/RavenHandler.php): Logs records to a [Sentry](http://getsentry.com/) server using
[raven](https://packagist.org/packages/raven/raven).
- [_ZendMonitorHandler_](../src/Monolog/Handler/ZendMonitorHandler.php): Logs records to the Zend Monitor present in Zend Server.
- [_NewRelicHandler_](../src/Monolog/Handler/NewRelicHandler.php): Logs records to a [NewRelic](http://newrelic.com/) application.
- [_LogglyHandler_](../src/Monolog/Handler/LogglyHandler.php): Logs records to a [Loggly](http://www.loggly.com/) account.
@@ -61,6 +59,8 @@
- [_InsightOpsHandler_](../src/Monolog/Handler/InsightOpsHandler.php): Logs records to an [InsightOps](https://www.rapid7.com/products/insightops/) account.
- [_LogmaticHandler_](../src/Monolog/Handler/LogmaticHandler.php): Logs records to a [Logmatic](http://logmatic.io/) account.
- [_SqsHandler_](../src/Monolog/Handler/SqsHandler.php): Logs records to an [AWS SQS](http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-sqs.html) queue.
- [_RavenHandler_](../src/Monolog/Handler/RavenHandler.php): Logs records to a [Sentry](http://getsentry.com/) server using
[raven](https://packagist.org/packages/raven/raven). **Deprecated** and removed in Monolog 2.0, use sentry/sentry 2.x and the [Sentry\Monolog\Handler](https://github.com/getsentry/sentry-php/blob/master/src/Monolog/Handler.php) class instead.
### Logging in development
@@ -128,9 +128,9 @@
- [_HandlerWrapper_](../src/Monolog/Handler/HandlerWrapper.php): A simple handler wrapper you can inherit from to create
your own wrappers easily.
- [_OverflowHandler_](../src/Monolog/Handler/OverflowHandler.php): This handler will buffer all the log messages it
receives, up until a configured threshold of number of messages of a certain lever is reached, after it will pass all
log messages to the wrapped handler. Useful for applying in batch processing when you're only interested in significant
failures instead of minor, single erroneous events.
receives, up until a configured threshold of number of messages of a certain lever is reached, after it will pass all
log messages to the wrapped handler. Useful for applying in batch processing when you're only interested in significant
failures instead of minor, single erroneous events.
## Formatters

View File

@@ -1,270 +0,0 @@
<?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\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
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)
*
* @author Marc Abramowitz <marc@marc-abramowitz.com>
*/
class RavenHandler extends AbstractProcessingHandler
{
/**
* Translates Monolog log levels to Raven log levels.
*/
protected $logLevels = [
Logger::DEBUG => Raven_Client::DEBUG,
Logger::INFO => Raven_Client::INFO,
Logger::NOTICE => Raven_Client::INFO,
Logger::WARNING => Raven_Client::WARNING,
Logger::ERROR => Raven_Client::ERROR,
Logger::CRITICAL => Raven_Client::FATAL,
Logger::ALERT => Raven_Client::FATAL,
Logger::EMERGENCY => Raven_Client::FATAL,
];
/**
* @var string the current application environment (staging|preprod|prod)
*/
protected $environment;
/**
* @var string should represent the current version of the calling
* software. Can be any string (git commit, version number)
*/
protected $release;
/**
* @var Raven_Client the client object that sends the message to the server
*/
protected $ravenClient;
/**
* @var FormatterInterface The formatter to use for the logs generated via handleBatch()
*/
protected $batchFormatter;
/**
* @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
*/
public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, bool $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;
}
/**
* {@inheritdoc}
*/
public function handleBatch(array $records): void
{
$level = $this->level;
// filter records based on their level
$records = array_filter($records, function ($record) use ($level) {
return $record['level'] >= $level;
});
if (!$records) {
return;
}
// the record with the highest severity is the "main" one
$record = array_reduce($records, function ($highest, $record) {
if ($record['level'] > $highest['level']) {
return $record;
}
return $highest;
});
// the other ones are added as a context item
$logs = [];
foreach ($records as $r) {
$logs[] = $this->processRecord($r);
}
if ($logs) {
$record['context']['logs'] = (string) $this->getBatchFormatter()->formatBatch($logs);
}
$this->handle($record);
}
/**
* Sets the formatter for the logs generated by handleBatch().
*
* @param FormatterInterface $formatter
*/
public function setBatchFormatter(FormatterInterface $formatter): self
{
$this->batchFormatter = $formatter;
return $this;
}
/**
* Gets the formatter for the logs generated by handleBatch().
*/
public function getBatchFormatter(): FormatterInterface
{
if (!$this->batchFormatter) {
$this->batchFormatter = $this->getDefaultBatchFormatter();
}
return $this->batchFormatter;
}
/**
* {@inheritdoc}
* @suppress PhanTypeMismatchArgument
*/
protected function write(array $record): void
{
/** @var bool|null|array This is false, unless set below to null or an array of data, when we read the current user context */
$previousUserContext = false;
$options = [];
$options['level'] = $this->logLevels[$record['level']];
$options['tags'] = [];
if (!empty($record['extra']['tags'])) {
$options['tags'] = array_merge($options['tags'], $record['extra']['tags']);
unset($record['extra']['tags']);
}
if (!empty($record['context']['tags'])) {
$options['tags'] = array_merge($options['tags'], $record['context']['tags']);
unset($record['context']['tags']);
}
if (!empty($record['context']['fingerprint'])) {
$options['fingerprint'] = $record['context']['fingerprint'];
unset($record['context']['fingerprint']);
}
if (!empty($record['context']['logger'])) {
$options['logger'] = $record['context']['logger'];
unset($record['context']['logger']);
} else {
$options['logger'] = $record['channel'];
}
foreach ($this->getExtraParameters() as $key) {
foreach (['extra', 'context'] as $source) {
if (!empty($record[$source][$key])) {
$options[$key] = $record[$source][$key];
unset($record[$source][$key]);
}
}
}
if (!empty($record['context'])) {
$options['extra']['context'] = $record['context'];
if (!empty($record['context']['user'])) {
$previousUserContext = $this->ravenClient->context->user;
$this->ravenClient->user_context($record['context']['user']);
unset($options['extra']['context']['user']);
}
}
if (!empty($record['extra'])) {
$options['extra']['extra'] = $record['extra'];
}
if (!empty($this->environment) && !isset($options['environment'])) {
$options['environment'] = $this->environment;
}
if (!empty($this->release) && !isset($options['release'])) {
$options['release'] = $this->release;
}
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
$options['message'] = $record['formatted'];
$this->ravenClient->captureException($record['context']['exception'], $options);
} else {
$this->ravenClient->captureMessage($record['formatted'], [], $options);
}
// restore the user context if it was modified
if (!is_bool($previousUserContext)) {
$this->ravenClient->user_context($previousUserContext, false);
}
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter('[%channel%] %message%');
}
/**
* Gets the default formatter for the logs generated by handleBatch().
*
* @return FormatterInterface
*/
protected function getDefaultBatchFormatter(): FormatterInterface
{
return new LineFormatter();
}
/**
* Gets extra parameters supported by Raven that can be found in "extra" and "context"
*
* @return array
*/
protected function getExtraParameters(): array
{
return ['contexts', 'checksum', 'release', 'environment', 'event_id'];
}
/**
* @param string $value
* @return self
*/
public function setRelease($value): self
{
$this->release = $value;
return $this;
}
public function setEnvironment($value): self
{
$this->environment = $value;
return $this;
}
/**
* @link https://docs.sentry.io/learn/breadcrumbs/
*/
public function addBreadcrumb(array $crumb): self
{
$this->ravenClient->breadcrumbs->record($crumb);
return $this;
}
public function resetBreadcrumbs(): self
{
$this->ravenClient->breadcrumbs->reset();
return $this;
}
}

View File

@@ -1,27 +0,0 @@
<?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 Raven_Client;
class MockRavenClient extends Raven_Client
{
public function capture($data, $stack = null, $vars = null)
{
$data = array_merge($this->get_user_data(), $data);
$this->lastData = $data;
$this->lastStack = $stack;
}
public $lastData;
public $lastStack;
}

View File

@@ -1,27 +0,0 @@
<?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 Raven_Client;
class MockRavenClient extends Raven_Client
{
public function capture($data, $stack = null, $vars = null)
{
$data = array_merge($this->get_user_data(), $data);
$this->lastData = $data;
$this->lastStack = $stack;
}
public $lastData;
public $lastStack;
}

View File

@@ -1,307 +0,0 @@
<?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\Test\TestCase;
use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
use Raven_Client;
class RavenHandlerTest extends TestCase
{
public function setUp()
{
if (!class_exists('Raven_Client')) {
$this->markTestSkipped('sentry/sentry not installed');
}
if (version_compare(Raven_Client::VERSION, '0.16.0', '>=')) {
require_once __DIR__ . '/MockRavenClient-gte-0-16-0.php';
} else {
require_once __DIR__ . '/MockRavenClient.php';
}
}
/**
* @covers Monolog\Handler\RavenHandler::__construct
*/
public function testConstruct()
{
$handler = new RavenHandler($this->getRavenClient());
$this->assertInstanceOf('Monolog\Handler\RavenHandler', $handler);
}
protected function getHandler($ravenClient)
{
return new RavenHandler($ravenClient);
}
protected function getRavenClient()
{
$dsn = 'http://43f6017361224d098402974103bfc53d:a6a0538fc2934ba2bed32e08741b2cd3@marca.python.live.cheggnet.com:9000/1';
return new MockRavenClient($dsn);
}
public function testDebug()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$record = $this->getRecord(Logger::DEBUG, 'A test debug message');
$handler->handle($record);
$this->assertEquals($ravenClient::DEBUG, $ravenClient->lastData['level']);
$this->assertContains($record['message'], $ravenClient->lastData['message']);
}
public function testWarning()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$record = $this->getRecord(Logger::WARNING, 'A test warning message');
$handler->handle($record);
$this->assertEquals($ravenClient::WARNING, $ravenClient->lastData['level']);
$this->assertContains($record['message'], $ravenClient->lastData['message']);
}
public function testTag()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$tags = [1, 2, 'foo'];
$record = $this->getRecord(Logger::INFO, 'test', ['tags' => $tags]);
$handler->handle($record);
$this->assertEquals($tags, $ravenClient->lastData['tags']);
}
public function testExtraParameters()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$checksum = '098f6bcd4621d373cade4e832627b4f6';
$release = '05a671c66aefea124cc08b76ea6d30bb';
$eventId = '31423';
$record = $this->getRecord(Logger::INFO, 'test', ['checksum' => $checksum, 'release' => $release, 'event_id' => $eventId]);
$handler->handle($record);
$this->assertEquals($checksum, $ravenClient->lastData['checksum']);
$this->assertEquals($release, $ravenClient->lastData['release']);
$this->assertEquals($eventId, $ravenClient->lastData['event_id']);
}
public function testFingerprint()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$fingerprint = ['{{ default }}', 'other value'];
$record = $this->getRecord(Logger::INFO, 'test', ['fingerprint' => $fingerprint]);
$handler->handle($record);
$this->assertEquals($fingerprint, $ravenClient->lastData['fingerprint']);
}
public function testUserContext()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$recordWithNoContext = $this->getRecord(Logger::INFO, 'test with default user context');
// set user context 'externally'
$user = [
'id' => '123',
'email' => 'test@test.com',
];
$recordWithContext = $this->getRecord(Logger::INFO, 'test', ['user' => $user]);
$ravenClient->user_context(['id' => 'test_user_id']);
// handle context
$handler->handle($recordWithContext);
$this->assertEquals($user, $ravenClient->lastData['user']);
// check to see if its reset
$handler->handle($recordWithNoContext);
$this->assertIsArray($ravenClient->context->user);
$this->assertSame('test_user_id', $ravenClient->context->user['id']);
// handle with null context
$ravenClient->user_context(null, false);
$handler->handle($recordWithContext);
$this->assertEquals($user, $ravenClient->lastData['user']);
// check to see if its reset
$handler->handle($recordWithNoContext);
$this->assertNull($ravenClient->context->user);
}
public function testException()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
try {
$this->methodThatThrowsAnException();
} catch (\Exception $e) {
$record = $this->getRecord(Logger::ERROR, $e->getMessage(), ['exception' => $e]);
$handler->handle($record);
}
$this->assertEquals('[test] ' . $record['message'], $ravenClient->lastData['message']);
}
public function testHandleBatch()
{
$records = $this->getMultipleRecords();
$records[] = $this->getRecord(Logger::WARNING, 'warning');
$records[] = $this->getRecord(Logger::WARNING, 'warning');
$logFormatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$logFormatter->expects($this->once())->method('formatBatch');
$formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$formatter->expects($this->once())->method('format')->with($this->callback(function ($record) {
return $record['level'] == 400;
}));
$handler = $this->getHandler($this->getRavenClient());
$handler->setBatchFormatter($logFormatter);
$handler->setFormatter($formatter);
$handler->handleBatch($records);
}
public function testHandleBatchDoNothingIfRecordsAreBelowLevel()
{
$records = [
$this->getRecord(Logger::DEBUG, 'debug message 1'),
$this->getRecord(Logger::DEBUG, 'debug message 2'),
$this->getRecord(Logger::INFO, 'information'),
];
$handler = $this->getMockBuilder('Monolog\Handler\RavenHandler')
->setMethods(['handle'])
->setConstructorArgs([$this->getRavenClient()])
->getMock();
$handler->expects($this->never())->method('handle');
$handler->setLevel(Logger::ERROR);
$handler->handleBatch($records);
}
public function testHandleBatchPicksProperMessage()
{
$records = array(
$this->getRecord(Logger::DEBUG, 'debug message 1'),
$this->getRecord(Logger::DEBUG, 'debug message 2'),
$this->getRecord(Logger::INFO, 'information 1'),
$this->getRecord(Logger::ERROR, 'error 1'),
$this->getRecord(Logger::WARNING, 'warning'),
$this->getRecord(Logger::ERROR, 'error 2'),
$this->getRecord(Logger::INFO, 'information 2'),
);
$logFormatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$logFormatter->expects($this->once())->method('formatBatch');
$formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$formatter->expects($this->once())->method('format')->with($this->callback(function ($record) use ($records) {
return $record['message'] == 'error 1';
}));
$handler = $this->getHandler($this->getRavenClient());
$handler->setBatchFormatter($logFormatter);
$handler->setFormatter($formatter);
$handler->handleBatch($records);
}
public function testGetSetBatchFormatter()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$handler->setBatchFormatter($formatter = new LineFormatter());
$this->assertSame($formatter, $handler->getBatchFormatter());
}
public function testRelease()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$release = 'v42.42.42';
$handler->setRelease($release);
$record = $this->getRecord(Logger::INFO, 'test');
$handler->handle($record);
$this->assertEquals($release, $ravenClient->lastData['release']);
$localRelease = 'v41.41.41';
$record = $this->getRecord(Logger::INFO, 'test', ['release' => $localRelease]);
$handler->handle($record);
$this->assertEquals($localRelease, $ravenClient->lastData['release']);
}
public function testEnvironment()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$handler->setEnvironment('preprod');
$handler->handle($this->getRecord(Logger::INFO, 'Hello 👋 from PREPROD env'));
$this->assertEquals('preprod', $ravenClient->lastData['environment']);
$handler->handle($this->getRecord(Logger::INFO, 'Hello 👋 from STAGING env', ['environment' => 'staging']));
$this->assertEquals('staging', $ravenClient->lastData['environment']);
}
public function testBreadcrumbs()
{
$ravenClient = $this->getRavenClient();
$handler = $this->getHandler($ravenClient);
$handler->addBreadcrumb($crumb1 = [
'category' => 'test',
'level' => 'info',
'message' => 'Step 1: user auth',
]);
$handler->addBreadcrumb($crumb2 = [
'category' => 'test',
'level' => 'info',
'message' => 'Step 2: prepare user redirect',
]);
$handler->handle($this->getRecord(Logger::ERROR, 'ERROR 💥'));
$breadcrumbs = $ravenClient->breadcrumbs->fetch();
$this->assertCount(2, $breadcrumbs);
$this->assertSame('test', $breadcrumbs[0]['category']);
$this->assertSame('info', $breadcrumbs[0]['level']);
$this->assertSame('Step 1: user auth', $breadcrumbs[0]['message']);
$this->assertSame('test', $breadcrumbs[1]['category']);
$this->assertSame('info', $breadcrumbs[1]['level']);
$this->assertSame('Step 2: prepare user redirect', $breadcrumbs[1]['message']);
$handler->resetBreadcrumbs();
$handler->handle($this->getRecord(Logger::INFO, 'Hello!'));
$this->assertEmpty($ravenClient->breadcrumbs->fetch());
}
private function methodThatThrowsAnException()
{
throw new \Exception('This is an exception');
}
}