mirror of
https://github.com/Seldaek/monolog.git
synced 2025-08-09 14:46:46 +02:00
@@ -178,6 +178,7 @@ Formatters
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
- _LineFormatter_: Formats a log record into a one-line string.
|
- _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.
|
- _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.
|
- _ScalarFormatter_: Used to format log records into an associative array of scalar values.
|
||||||
- _JsonFormatter_: Encodes a log record into json.
|
- _JsonFormatter_: Encodes a log record into json.
|
||||||
@@ -196,6 +197,7 @@ Processors
|
|||||||
- _MemoryPeakUsageProcessor_: Adds the peak 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.
|
- _ProcessIdProcessor_: Adds the process id to a log record.
|
||||||
- _UidProcessor_: Adds a unique identifier 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.
|
||||||
|
|
||||||
Utilities
|
Utilities
|
||||||
---------
|
---------
|
||||||
|
@@ -47,6 +47,7 @@ class ElasticaFormatter extends NormalizerFormatter
|
|||||||
public function format(array $record)
|
public function format(array $record)
|
||||||
{
|
{
|
||||||
$record = parent::format($record);
|
$record = parent::format($record);
|
||||||
|
|
||||||
return $this->getDocument($record);
|
return $this->getDocument($record);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ class ElasticaFormatter extends NormalizerFormatter
|
|||||||
$document->setData($record);
|
$document->setData($record);
|
||||||
$document->setType($this->type);
|
$document->setType($this->type);
|
||||||
$document->setIndex($this->index);
|
$document->setIndex($this->index);
|
||||||
|
|
||||||
return $document;
|
return $document;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,14 +10,16 @@
|
|||||||
|
|
||||||
namespace Monolog\Formatter;
|
namespace Monolog\Formatter;
|
||||||
|
|
||||||
|
use Monolog\Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats incoming records into a HTML table
|
* Formats incoming records into an HTML table
|
||||||
*
|
*
|
||||||
* This is especially useful for html email logging
|
* This is especially useful for html email logging
|
||||||
*
|
*
|
||||||
* @author Tiago Brito <tlfbrito@gmail.com>
|
* @author Tiago Brito <tlfbrito@gmail.com>
|
||||||
*/
|
*/
|
||||||
class HtmlEmailFormatter extends NormalizerFormatter
|
class HtmlFormatter extends NormalizerFormatter
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Translates Monolog log levels to html color priorities.
|
* Translates Monolog log levels to html color priorities.
|
||||||
@@ -44,14 +46,14 @@ class HtmlEmailFormatter extends NormalizerFormatter
|
|||||||
/**
|
/**
|
||||||
* Creates an HTML table row
|
* Creates an HTML table row
|
||||||
*
|
*
|
||||||
* @param $th string Row header content
|
* @param string $th Row header content
|
||||||
* @param string $td Row standard cell content
|
* @param string $td Row standard cell content
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function addRow($th, $td = ' ')
|
private function addRow($th, $td = ' ')
|
||||||
{
|
{
|
||||||
$th = htmlspecialchars($th);
|
$th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8');
|
||||||
$td = '<pre>'.htmlspecialchars($td).'</pre>';
|
$td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>';
|
||||||
|
|
||||||
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>";
|
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>";
|
||||||
}
|
}
|
||||||
@@ -59,13 +61,13 @@ class HtmlEmailFormatter extends NormalizerFormatter
|
|||||||
/**
|
/**
|
||||||
* Create a HTML h1 tag
|
* Create a HTML h1 tag
|
||||||
*
|
*
|
||||||
* @param $title string Text to be in the h1
|
* @param string $title Text to be in the h1
|
||||||
* @param $level integer Error level
|
* @param integer $level Error level
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function addTitle($title, $level)
|
private function addTitle($title, $level)
|
||||||
{
|
{
|
||||||
$title = htmlspecialchars($title);
|
$title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8');
|
||||||
|
|
||||||
return '<h1 style="background: '.$this->logLevels[$level].';color: #ffffff;padding: 5px;">'.$title.'</h1>';
|
return '<h1 style="background: '.$this->logLevels[$level].';color: #ffffff;padding: 5px;">'.$title.'</h1>';
|
||||||
}
|
}
|
||||||
@@ -77,15 +79,18 @@ class HtmlEmailFormatter extends NormalizerFormatter
|
|||||||
*/
|
*/
|
||||||
public function format(array $record)
|
public function format(array $record)
|
||||||
{
|
{
|
||||||
$output = $this->addTitle($this->convertToString($record['level_name']), $record['level']);
|
$output = $this->addTitle($record['level_name'], $record['level']);
|
||||||
$output .= '<table cellspacing="1" width="100%">';
|
$output .= '<table cellspacing="1" width="100%">';
|
||||||
|
|
||||||
$output .= $this->addRow('Message', $this->convertToString($record['message']));
|
$output .= $this->addRow('Message', (string) $record['message']);
|
||||||
$output .= $this->addRow('Generated at', $this->convertToString($record['datetime']));
|
$output .= $this->addRow('Time', $record['datetime']->format('Y-m-d\TH:i:s.uO'));
|
||||||
$output .= $this->addRow('Level', $this->convertToString($record['level']));
|
$output .= $this->addRow('Channel', $record['channel']);
|
||||||
$output .= $this->addRow('Channel', $this->convertToString($record['channel']));
|
if ($record['context']) {
|
||||||
$output .= $this->addRow('Context', $this->convertToString($record['context']));
|
$output .= $this->addRow('Context', $this->convertToString($record['context']));
|
||||||
|
}
|
||||||
|
if ($record['extra']) {
|
||||||
$output .= $this->addRow('Extra', $this->convertToString($record['extra']));
|
$output .= $this->addRow('Extra', $this->convertToString($record['extra']));
|
||||||
|
}
|
||||||
|
|
||||||
return $output.'</table>';
|
return $output.'</table>';
|
||||||
}
|
}
|
@@ -73,7 +73,8 @@ class StreamHandler extends AbstractProcessingHandler
|
|||||||
fwrite($this->stream, (string) $record['formatted']);
|
fwrite($this->stream, (string) $record['formatted']);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function customErrorHandler($code, $msg) {
|
private function customErrorHandler($code, $msg)
|
||||||
|
{
|
||||||
$this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $msg);
|
$this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
src/Monolog/Processor/GitProcessor.php
Normal file
64
src/Monolog/Processor/GitProcessor.php
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?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\Processor;
|
||||||
|
|
||||||
|
use Monolog\Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects Git branch and Git commit SHA in all records
|
||||||
|
*
|
||||||
|
* @author Nick Otter
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*/
|
||||||
|
class GitProcessor
|
||||||
|
{
|
||||||
|
private $level;
|
||||||
|
private static $cache;
|
||||||
|
|
||||||
|
public function __construct($level = Logger::DEBUG)
|
||||||
|
{
|
||||||
|
$this->level = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $record
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function __invoke(array $record)
|
||||||
|
{
|
||||||
|
// return if the level is not high enough
|
||||||
|
if ($record['level'] < $this->level) {
|
||||||
|
return $record;
|
||||||
|
}
|
||||||
|
|
||||||
|
$record['extra']['git'] = self::getGitInfo();
|
||||||
|
|
||||||
|
return $record;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getGitInfo()
|
||||||
|
{
|
||||||
|
if (self::$cache) {
|
||||||
|
return self::$cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
$branches = `git branch -v --no-abbrev`;
|
||||||
|
if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
|
||||||
|
return self::$cache = array(
|
||||||
|
'branch' => $matches[1],
|
||||||
|
'commit' => $matches[2],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$cache = array();
|
||||||
|
}
|
||||||
|
}
|
118
src/Monolog/Registry.php
Normal file
118
src/Monolog/Registry.php
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monolog log registry
|
||||||
|
*
|
||||||
|
* Allows to get `Logger` instances in the global scope
|
||||||
|
* via static method calls on this class.
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* $application = new Monolog\Logger('application');
|
||||||
|
* $api = new Monolog\Logger('api');
|
||||||
|
*
|
||||||
|
* Monolog\Registry::addLogger($application);
|
||||||
|
* Monolog\Registry::addLogger($api);
|
||||||
|
*
|
||||||
|
* function testLogger()
|
||||||
|
* {
|
||||||
|
* Monolog\Registry::api()->addError('Sent to $api Logger instance');
|
||||||
|
* Monolog\Registry::application()->addError('Sent to $application Logger instance');
|
||||||
|
* }
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @author Tomas Tatarko <tomas@tatarko.sk>
|
||||||
|
*/
|
||||||
|
class Registry
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* List of all loggers in the registry (ba named indexes)
|
||||||
|
*
|
||||||
|
* @var Logger[]
|
||||||
|
*/
|
||||||
|
private static $loggers = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds new logging channel to the registry
|
||||||
|
*
|
||||||
|
* @param Logger $logger Instance of the logging channel
|
||||||
|
* @param string $name Name of the logging channel ($logger->getName() by default)
|
||||||
|
* @param boolean $overwrite Overwrite instance in the registry if the given name already exists?
|
||||||
|
* @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
|
||||||
|
*/
|
||||||
|
public static function addLogger(Logger $logger, $name = null, $overwrite = false)
|
||||||
|
{
|
||||||
|
$name = $name ?: $logger->getName();
|
||||||
|
|
||||||
|
if (isset(self::$loggers[$name]) && !$overwrite) {
|
||||||
|
throw new InvalidArgumentException('Logger with the given name already exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$loggers[$name] = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes instance from registry by name or instance
|
||||||
|
*
|
||||||
|
* @param string|Logger $logger Name or logger instance
|
||||||
|
*/
|
||||||
|
public static function removeLogger($logger)
|
||||||
|
{
|
||||||
|
if ($logger instanceof Logger) {
|
||||||
|
if (false !== ($idx = array_search($logger, self::$loggers, true))) {
|
||||||
|
unset(self::$loggers[$idx]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unset(self::$loggers[$logger]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the registry
|
||||||
|
*/
|
||||||
|
public static function clear()
|
||||||
|
{
|
||||||
|
self::$loggers = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets Logger instance from the registry
|
||||||
|
*
|
||||||
|
* @param string $name Name of the requested Logger instance
|
||||||
|
* @return Logger Requested instance of Logger
|
||||||
|
* @throws \InvalidArgumentException If named Logger instance is not in the registry
|
||||||
|
*/
|
||||||
|
public static function getInstance($name)
|
||||||
|
{
|
||||||
|
if (!isset(self::$loggers[$name])) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$loggers[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets Logger instance from the registry via static method call
|
||||||
|
*
|
||||||
|
* @param string $name Name of the requested Logger instance
|
||||||
|
* @param array $arguments Arguments passed to static method call
|
||||||
|
* @return Logger Requested instance of Logger
|
||||||
|
* @throws \InvalidArgumentException If named Logger instance is not in the registry
|
||||||
|
*/
|
||||||
|
public static function __callStatic($name, $arguments)
|
||||||
|
{
|
||||||
|
return self::getInstance($name);
|
||||||
|
}
|
||||||
|
}
|
29
tests/Monolog/Processor/GitProcessorTest.php
Normal file
29
tests/Monolog/Processor/GitProcessorTest.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?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\Processor;
|
||||||
|
|
||||||
|
use Monolog\TestCase;
|
||||||
|
|
||||||
|
class GitProcessorTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers Monolog\Processor\GitProcessor::__invoke
|
||||||
|
*/
|
||||||
|
public function testProcessor()
|
||||||
|
{
|
||||||
|
$processor = new GitProcessor();
|
||||||
|
$record = $processor($this->getRecord());
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('git', $record['extra']);
|
||||||
|
$this->assertTrue(!is_array($record['extra']['git']['branch']));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user