Просмотр исходного кода

Merge pull request #1 from Seldaek/master

Update fork
Tiago Brito 12 лет назад
Родитель
Сommit
475847fc07

+ 2 - 0
README.mdown

@@ -178,6 +178,7 @@ 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.
@@ -196,6 +197,7 @@ Processors
 - _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.
 
 Utilities
 ---------

+ 3 - 1
src/Monolog/Formatter/ElasticaFormatter.php

@@ -47,6 +47,7 @@ class ElasticaFormatter extends NormalizerFormatter
     public function format(array $record)
     {
         $record = parent::format($record);
+
         return $this->getDocument($record);
     }
 
@@ -71,7 +72,7 @@ class ElasticaFormatter extends NormalizerFormatter
     /**
      * Convert a log message into an Elastica Document
      *
-     * @param array  $record Log message
+     * @param  array    $record Log message
      * @return Document
      */
     protected function getDocument($record)
@@ -80,6 +81,7 @@ class ElasticaFormatter extends NormalizerFormatter
         $document->setData($record);
         $document->setType($this->type);
         $document->setIndex($this->index);
+
         return $document;
     }
 }

+ 22 - 17
src/Monolog/Formatter/HtmlEmailFormatter.php → src/Monolog/Formatter/HtmlFormatter.php

@@ -10,14 +10,16 @@
 
 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
  *
  * @author Tiago Brito <tlfbrito@gmail.com>
  */
-class HtmlEmailFormatter extends NormalizerFormatter
+class HtmlFormatter extends NormalizerFormatter
 {
     /**
      * Translates Monolog log levels to html color priorities.
@@ -44,14 +46,14 @@ class HtmlEmailFormatter extends NormalizerFormatter
     /**
      * Creates an HTML table row
      *
-     * @param $th string Row header content
-     * @param string $td Row standard cell content
+     * @param  string $th Row header content
+     * @param  string $td Row standard cell content
      * @return string
      */
     private function addRow($th, $td = ' ')
     {
-        $th = htmlspecialchars($th);
-        $td = '<pre>'.htmlspecialchars($td).'</pre>';
+        $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8');
+        $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>";
     }
@@ -59,14 +61,14 @@ class HtmlEmailFormatter extends NormalizerFormatter
     /**
      * Create a HTML h1 tag
      *
-     * @param $title string Text to be in the h1
-     * @param $level integer Error level
+     * @param  string  $title Text to be in the h1
+     * @param  integer $level Error level
      * @return string
      */
     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>';
     }
     /**
@@ -77,15 +79,18 @@ class HtmlEmailFormatter extends NormalizerFormatter
      */
     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 .= $this->addRow('Message', $this->convertToString($record['message']));
-        $output .= $this->addRow('Generated at', $this->convertToString($record['datetime']));
-        $output .= $this->addRow('Level', $this->convertToString($record['level']));
-        $output .= $this->addRow('Channel', $this->convertToString($record['channel']));
-        $output .= $this->addRow('Context', $this->convertToString($record['context']));
-        $output .= $this->addRow('Extra', $this->convertToString($record['extra']));
+        $output .= $this->addRow('Message', (string) $record['message']);
+        $output .= $this->addRow('Time', $record['datetime']->format('Y-m-d\TH:i:s.uO'));
+        $output .= $this->addRow('Channel', $record['channel']);
+        if ($record['context']) {
+            $output .= $this->addRow('Context', $this->convertToString($record['context']));
+        }
+        if ($record['extra']) {
+            $output .= $this->addRow('Extra', $this->convertToString($record['extra']));
+        }
 
         return $output.'</table>';
     }

+ 1 - 1
src/Monolog/Formatter/ScalarFormatter.php

@@ -34,7 +34,7 @@ class ScalarFormatter extends NormalizerFormatter
     }
 
     /**
-     * @param mixed $value
+     * @param  mixed $value
      * @return mixed
      */
     protected function normalizeValue($value)

+ 4 - 4
src/Monolog/Handler/DynamoDbHandler.php

@@ -39,9 +39,9 @@ class DynamoDbHandler extends AbstractProcessingHandler
 
     /**
      * @param DynamoDbClient $client
-     * @param string $table
-     * @param integer $level
-     * @param boolean $bubble
+     * @param string         $table
+     * @param integer        $level
+     * @param boolean        $bubble
      */
     public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true)
     {
@@ -70,7 +70,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
     }
 
     /**
-     * @param array $record
+     * @param  array $record
      * @return array
      */
     protected function filterEmptyFields(array $record)

+ 5 - 5
src/Monolog/Handler/ElasticSearchHandler.php

@@ -46,10 +46,10 @@ class ElasticSearchHandler extends AbstractProcessingHandler
     protected $options = array();
 
     /**
-     * @param Client  $client   Elastica Client object
-     * @param array   $options  Handler configuration
-     * @param integer $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 Client  $client  Elastica Client object
+     * @param array   $options Handler configuration
+     * @param integer $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)
     {
@@ -112,7 +112,7 @@ class ElasticSearchHandler extends AbstractProcessingHandler
 
     /**
      * Use Elasticsearch bulk API to send list of documents
-     * @param array $documents
+     * @param  array             $documents
      * @throws \RuntimeException
      */
     protected function bulkSend(array $documents)

+ 2 - 1
src/Monolog/Handler/StreamHandler.php

@@ -73,7 +73,8 @@ class StreamHandler extends AbstractProcessingHandler
         fwrite($this->stream, (string) $record['formatted']);
     }
 
-    private function customErrorHandler($code, $msg) {
+    private function customErrorHandler($code, $msg)
+    {
         $this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $msg);
     }
 }

+ 64 - 0
src/Monolog/Processor/GitProcessor.php

@@ -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 - 0
src/Monolog/Registry.php

@@ -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 - 0
tests/Monolog/Processor/GitProcessorTest.php

@@ -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']));
+    }
+}