commit
48c55c6f3e
@ -0,0 +1 @@ |
||||
../sabre/vobject/bin/generate_vcards |
||||
@ -0,0 +1 @@ |
||||
../sabre/vobject/bin/vobject |
||||
@ -0,0 +1,10 @@ |
||||
<?php |
||||
|
||||
// autoload_psr4.php @generated by Composer |
||||
|
||||
$vendorDir = dirname(dirname(__FILE__)); |
||||
$baseDir = dirname($vendorDir); |
||||
|
||||
return array( |
||||
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), |
||||
); |
||||
@ -0,0 +1,87 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Elastica\Document; |
||||
|
||||
/** |
||||
* Format a log message into an Elastica Document |
||||
* |
||||
* @author Jelle Vink <jelle.vink@gmail.com> |
||||
*/ |
||||
class ElasticaFormatter extends NormalizerFormatter |
||||
{ |
||||
/** |
||||
* @var string Elastic search index name |
||||
*/ |
||||
protected $index; |
||||
|
||||
/** |
||||
* @var string Elastic search document type |
||||
*/ |
||||
protected $type; |
||||
|
||||
/** |
||||
* @param string $index Elastic Search index name |
||||
* @param string $type Elastic Search document type |
||||
*/ |
||||
public function __construct($index, $type) |
||||
{ |
||||
parent::__construct(\DateTime::ISO8601); |
||||
$this->index = $index; |
||||
$this->type = $type; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
$record = parent::format($record); |
||||
|
||||
return $this->getDocument($record); |
||||
} |
||||
|
||||
/** |
||||
* Getter index |
||||
* @return string |
||||
*/ |
||||
public function getIndex() |
||||
{ |
||||
return $this->index; |
||||
} |
||||
|
||||
/** |
||||
* Getter type |
||||
* @return string |
||||
*/ |
||||
public function getType() |
||||
{ |
||||
return $this->type; |
||||
} |
||||
|
||||
/** |
||||
* Convert a log message into an Elastica Document |
||||
* |
||||
* @param array $record Log message |
||||
* @return Document |
||||
*/ |
||||
protected function getDocument($record) |
||||
{ |
||||
$document = new Document(); |
||||
$document->setData($record); |
||||
$document->setType($this->type); |
||||
$document->setIndex($this->index); |
||||
|
||||
return $document; |
||||
} |
||||
} |
||||
@ -0,0 +1,104 @@ |
||||
<?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\Formatter; |
||||
|
||||
/** |
||||
* formats the record to be used in the FlowdockHandler |
||||
* |
||||
* @author Dominik Liebler <liebler.dominik@gmail.com> |
||||
*/ |
||||
class FlowdockFormatter implements FormatterInterface |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $source; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $sourceEmail; |
||||
|
||||
/** |
||||
* @param string $source |
||||
* @param string $sourceEmail |
||||
*/ |
||||
public function __construct($source, $sourceEmail) |
||||
{ |
||||
$this->source = $source; |
||||
$this->sourceEmail = $sourceEmail; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
$tags = array( |
||||
'#logs', |
||||
'#' . strtolower($record['level_name']), |
||||
'#' . $record['channel'], |
||||
); |
||||
|
||||
foreach ($record['extra'] as $value) { |
||||
$tags[] = '#' . $value; |
||||
} |
||||
|
||||
$subject = sprintf( |
||||
'in %s: %s - %s', |
||||
$this->source, |
||||
$record['level_name'], |
||||
$this->getShortMessage($record['message']) |
||||
); |
||||
|
||||
$record['flowdock'] = array( |
||||
'source' => $this->source, |
||||
'from_address' => $this->sourceEmail, |
||||
'subject' => $subject, |
||||
'content' => $record['message'], |
||||
'tags' => $tags, |
||||
'project' => $this->source, |
||||
); |
||||
|
||||
return $record; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function formatBatch(array $records) |
||||
{ |
||||
$formatted = array(); |
||||
|
||||
foreach ($records as $record) { |
||||
$formatted[] = $this->format($record); |
||||
} |
||||
|
||||
return $formatted; |
||||
} |
||||
|
||||
/** |
||||
* @param string $message |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function getShortMessage($message) |
||||
{ |
||||
$maxLength = 45; |
||||
|
||||
if (strlen($message) > $maxLength) { |
||||
$message = substr($message, 0, $maxLength - 4) . ' ...'; |
||||
} |
||||
|
||||
return $message; |
||||
} |
||||
} |
||||
@ -0,0 +1,127 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Formats incoming records into an HTML table |
||||
* |
||||
* This is especially useful for html email logging |
||||
* |
||||
* @author Tiago Brito <tlfbrito@gmail.com> |
||||
*/ |
||||
class HtmlFormatter extends NormalizerFormatter |
||||
{ |
||||
/** |
||||
* Translates Monolog log levels to html color priorities. |
||||
*/ |
||||
private $logLevels = array( |
||||
Logger::DEBUG => '#cccccc', |
||||
Logger::INFO => '#468847', |
||||
Logger::NOTICE => '#3a87ad', |
||||
Logger::WARNING => '#c09853', |
||||
Logger::ERROR => '#f0ad4e', |
||||
Logger::CRITICAL => '#FF7708', |
||||
Logger::ALERT => '#C12A19', |
||||
Logger::EMERGENCY => '#000000', |
||||
); |
||||
|
||||
/** |
||||
* @param string $dateFormat The format of the timestamp: one supported by DateTime::format |
||||
*/ |
||||
public function __construct($dateFormat = null) |
||||
{ |
||||
parent::__construct($dateFormat); |
||||
} |
||||
|
||||
/** |
||||
* Creates an HTML table row |
||||
* |
||||
* @param string $th Row header content |
||||
* @param string $td Row standard cell content |
||||
* @return string |
||||
*/ |
||||
private function addRow($th, $td = ' ') |
||||
{ |
||||
$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>"; |
||||
} |
||||
|
||||
/** |
||||
* Create a HTML h1 tag |
||||
* |
||||
* @param string $title Text to be in the h1 |
||||
* @param integer $level Error level |
||||
* @return string |
||||
*/ |
||||
private function addTitle($title, $level) |
||||
{ |
||||
$title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8'); |
||||
|
||||
return '<h1 style="background: '.$this->logLevels[$level].';color: #ffffff;padding: 5px;">'.$title.'</h1>'; |
||||
} |
||||
/** |
||||
* Formats a log record. |
||||
* |
||||
* @param array $record A record to format |
||||
* @return mixed The formatted record |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
$output = $this->addTitle($record['level_name'], $record['level']); |
||||
$output .= '<table cellspacing="1" width="100%">'; |
||||
|
||||
$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>'; |
||||
} |
||||
|
||||
/** |
||||
* Formats a set of log records. |
||||
* |
||||
* @param array $records A set of records to format |
||||
* @return mixed The formatted set of records |
||||
*/ |
||||
public function formatBatch(array $records) |
||||
{ |
||||
$message = ''; |
||||
foreach ($records as $record) { |
||||
$message .= $this->format($record); |
||||
} |
||||
|
||||
return $message; |
||||
} |
||||
|
||||
protected function convertToString($data) |
||||
{ |
||||
if (null === $data || is_scalar($data)) { |
||||
return (string) $data; |
||||
} |
||||
|
||||
$data = $this->normalize($data); |
||||
if (version_compare(PHP_VERSION, '5.4.0', '>=')) { |
||||
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); |
||||
} |
||||
|
||||
return str_replace('\\/', '/', json_encode($data)); |
||||
} |
||||
} |
||||
@ -0,0 +1,47 @@ |
||||
<?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\Formatter; |
||||
|
||||
/** |
||||
* Encodes message information into JSON in a format compatible with Loggly. |
||||
* |
||||
* @author Adam Pancutt <adam@pancutt.com> |
||||
*/ |
||||
class LogglyFormatter extends JsonFormatter |
||||
{ |
||||
/** |
||||
* Overrides the default batch mode to new lines for compatibility with the |
||||
* Loggly bulk API. |
||||
* |
||||
* @param integer $batchMode |
||||
*/ |
||||
public function __construct($batchMode = self::BATCH_MODE_NEWLINES, $appendNewline = false) |
||||
{ |
||||
parent::__construct($batchMode, $appendNewline); |
||||
} |
||||
|
||||
/** |
||||
* Appends the 'timestamp' parameter for indexing by Loggly. |
||||
* |
||||
* @see https://www.loggly.com/docs/automated-parsing/#json |
||||
* @see \Monolog\Formatter\JsonFormatter::format() |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTime)) { |
||||
$record["timestamp"] = $record["datetime"]->format("c"); |
||||
// TODO 2.0 unset the 'datetime' parameter, retained for BC |
||||
} |
||||
|
||||
return parent::format($record); |
||||
} |
||||
} |
||||
@ -0,0 +1,48 @@ |
||||
<?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\Formatter; |
||||
|
||||
/** |
||||
* Formats data into an associative array of scalar values. |
||||
* Objects and arrays will be JSON encoded. |
||||
* |
||||
* @author Andrew Lawson <adlawson@gmail.com> |
||||
*/ |
||||
class ScalarFormatter extends NormalizerFormatter |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
foreach ($record as $key => $value) { |
||||
$record[$key] = $this->normalizeValue($value); |
||||
} |
||||
|
||||
return $record; |
||||
} |
||||
|
||||
/** |
||||
* @param mixed $value |
||||
* @return mixed |
||||
*/ |
||||
protected function normalizeValue($value) |
||||
{ |
||||
$normalized = $this->normalize($value); |
||||
|
||||
if (is_array($normalized) || is_object($normalized)) { |
||||
return $this->toJson($normalized, true); |
||||
} |
||||
|
||||
return $normalized; |
||||
} |
||||
} |
||||
@ -0,0 +1,92 @@ |
||||
<?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; |
||||
use Monolog\Formatter\LineFormatter; |
||||
|
||||
/** |
||||
* Common syslog functionality |
||||
*/ |
||||
abstract class AbstractSyslogHandler extends AbstractProcessingHandler |
||||
{ |
||||
protected $facility; |
||||
|
||||
/** |
||||
* Translates Monolog log levels to syslog log priorities. |
||||
*/ |
||||
protected $logLevels = array( |
||||
Logger::DEBUG => LOG_DEBUG, |
||||
Logger::INFO => LOG_INFO, |
||||
Logger::NOTICE => LOG_NOTICE, |
||||
Logger::WARNING => LOG_WARNING, |
||||
Logger::ERROR => LOG_ERR, |
||||
Logger::CRITICAL => LOG_CRIT, |
||||
Logger::ALERT => LOG_ALERT, |
||||
Logger::EMERGENCY => LOG_EMERG, |
||||
); |
||||
|
||||
/** |
||||
* List of valid log facility names. |
||||
*/ |
||||
protected $facilities = array( |
||||
'auth' => LOG_AUTH, |
||||
'authpriv' => LOG_AUTHPRIV, |
||||
'cron' => LOG_CRON, |
||||
'daemon' => LOG_DAEMON, |
||||
'kern' => LOG_KERN, |
||||
'lpr' => LOG_LPR, |
||||
'mail' => LOG_MAIL, |
||||
'news' => LOG_NEWS, |
||||
'syslog' => LOG_SYSLOG, |
||||
'user' => LOG_USER, |
||||
'uucp' => LOG_UUCP, |
||||
); |
||||
|
||||
/** |
||||
* @param mixed $facility |
||||
* @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($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
parent::__construct($level, $bubble); |
||||
|
||||
if (!defined('PHP_WINDOWS_VERSION_BUILD')) { |
||||
$this->facilities['local0'] = LOG_LOCAL0; |
||||
$this->facilities['local1'] = LOG_LOCAL1; |
||||
$this->facilities['local2'] = LOG_LOCAL2; |
||||
$this->facilities['local3'] = LOG_LOCAL3; |
||||
$this->facilities['local4'] = LOG_LOCAL4; |
||||
$this->facilities['local5'] = LOG_LOCAL5; |
||||
$this->facilities['local6'] = LOG_LOCAL6; |
||||
$this->facilities['local7'] = LOG_LOCAL7; |
||||
} |
||||
|
||||
// convert textual description of facility to syslog constant |
||||
if (array_key_exists(strtolower($facility), $this->facilities)) { |
||||
$facility = $this->facilities[strtolower($facility)]; |
||||
} elseif (!in_array($facility, array_values($this->facilities), true)) { |
||||
throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given'); |
||||
} |
||||
|
||||
$this->facility = $facility; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function getDefaultFormatter() |
||||
{ |
||||
return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%'); |
||||
} |
||||
} |
||||
@ -0,0 +1,184 @@ |
||||
<?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\Formatter\LineFormatter; |
||||
|
||||
/** |
||||
* Handler sending logs to browser's javascript console with no browser extension required |
||||
* |
||||
* @author Olivier Poitrey <rs@dailymotion.com> |
||||
*/ |
||||
class BrowserConsoleHandler extends AbstractProcessingHandler |
||||
{ |
||||
protected static $initialized = false; |
||||
protected static $records = array(); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
* |
||||
* Formatted output may contain some formatting markers to be transfered to `console.log` using the %c format. |
||||
* |
||||
* Example of formatted string: |
||||
* |
||||
* You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white} |
||||
* |
||||
*/ |
||||
protected function getDefaultFormatter() |
||||
{ |
||||
return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
// Accumulate records |
||||
self::$records[] = $record; |
||||
|
||||
// Register shutdown handler if not already done |
||||
if (PHP_SAPI !== 'cli' && !self::$initialized) { |
||||
self::$initialized = true; |
||||
register_shutdown_function(array('Monolog\Handler\BrowserConsoleHandler', 'send')); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Convert records to javascript console commands and send it to the browser. |
||||
* This method is automatically called on PHP shutdown if output is HTML. |
||||
*/ |
||||
public static function send() |
||||
{ |
||||
// Check content type |
||||
foreach (headers_list() as $header) { |
||||
if (stripos($header, 'content-type:') === 0) { |
||||
if (stripos($header, 'text/html') === false) { |
||||
// This handler only works with HTML outputs |
||||
return; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (count(self::$records)) { |
||||
echo '<script>' . self::generateScript() . '</script>'; |
||||
self::reset(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Forget all logged records |
||||
*/ |
||||
public static function reset() |
||||
{ |
||||
self::$records = array(); |
||||
} |
||||
|
||||
private static function generateScript() |
||||
{ |
||||
$script = array(); |
||||
foreach (self::$records as $record) { |
||||
$context = self::dump('Context', $record['context']); |
||||
$extra = self::dump('Extra', $record['extra']); |
||||
|
||||
if (empty($context) && empty($extra)) { |
||||
$script[] = self::call_array('log', self::handleStyles($record['formatted'])); |
||||
} else { |
||||
$script = array_merge($script, |
||||
array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))), |
||||
$context, |
||||
$extra, |
||||
array(self::call('groupEnd')) |
||||
); |
||||
} |
||||
} |
||||
|
||||
return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; |
||||
} |
||||
|
||||
private static function handleStyles($formatted) |
||||
{ |
||||
$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"'; |
||||
|
||||
$pos = $match[0][1]; |
||||
$format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0])); |
||||
} |
||||
|
||||
array_unshift($args, self::quote($format)); |
||||
|
||||
return $args; |
||||
} |
||||
|
||||
private static function handleCustomStyles($style, $string) |
||||
{ |
||||
static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'); |
||||
static $labels = array(); |
||||
|
||||
return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function ($m) use ($string, &$colors, &$labels) { |
||||
if (trim($m[1]) === 'autolabel') { |
||||
// Format the string as a label with consistent auto assigned background color |
||||
if (!isset($labels[$string])) { |
||||
$labels[$string] = $colors[count($labels) % count($colors)]; |
||||
} |
||||
$color = $labels[$string]; |
||||
|
||||
return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px"; |
||||
} |
||||
|
||||
return $m[1]; |
||||
}, $style); |
||||
} |
||||
|
||||
private static function dump($title, array $dict) |
||||
{ |
||||
$script = array(); |
||||
$dict = array_filter($dict); |
||||
if (empty($dict)) { |
||||
return $script; |
||||
} |
||||
$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 = self::quote(''); |
||||
} |
||||
$script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value); |
||||
} |
||||
|
||||
return $script; |
||||
} |
||||
|
||||
private static function quote($arg) |
||||
{ |
||||
return '"' . addcslashes($arg, "\"\n") . '"'; |
||||
} |
||||
|
||||
private static function call() |
||||
{ |
||||
$args = func_get_args(); |
||||
$method = array_shift($args); |
||||
|
||||
return self::call_array($method, $args); |
||||
} |
||||
|
||||
private static function call_array($method, array $args) |
||||
{ |
||||
return 'c.' . $method . '(' . implode(', ', $args) . ');'; |
||||
} |
||||
} |
||||
@ -0,0 +1,89 @@ |
||||
<?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 Aws\Common\Aws; |
||||
use Aws\DynamoDb\DynamoDbClient; |
||||
use Monolog\Formatter\ScalarFormatter; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) |
||||
* |
||||
* @link https://github.com/aws/aws-sdk-php/ |
||||
* @author Andrew Lawson <adlawson@gmail.com> |
||||
*/ |
||||
class DynamoDbHandler extends AbstractProcessingHandler |
||||
{ |
||||
const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; |
||||
|
||||
/** |
||||
* @var DynamoDbClient |
||||
*/ |
||||
protected $client; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $table; |
||||
|
||||
/** |
||||
* @param DynamoDbClient $client |
||||
* @param string $table |
||||
* @param integer $level |
||||
* @param boolean $bubble |
||||
*/ |
||||
public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
if (!defined('Aws\Common\Aws::VERSION') || version_compare('3.0', Aws::VERSION, '<=')) { |
||||
throw new \RuntimeException('The DynamoDbHandler is only known to work with the AWS SDK 2.x releases'); |
||||
} |
||||
|
||||
$this->client = $client; |
||||
$this->table = $table; |
||||
|
||||
parent::__construct($level, $bubble); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
$filtered = $this->filterEmptyFields($record['formatted']); |
||||
$formatted = $this->client->formatAttributes($filtered); |
||||
|
||||
$this->client->putItem(array( |
||||
'TableName' => $this->table, |
||||
'Item' => $formatted |
||||
)); |
||||
} |
||||
|
||||
/** |
||||
* @param array $record |
||||
* @return array |
||||
*/ |
||||
protected function filterEmptyFields(array $record) |
||||
{ |
||||
return array_filter($record, function ($value) { |
||||
return !empty($value) || false === $value || 0 === $value; |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function getDefaultFormatter() |
||||
{ |
||||
return new ScalarFormatter(self::DATE_FORMAT); |
||||
} |
||||
} |
||||
@ -0,0 +1,128 @@ |
||||
<?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\Formatter\FormatterInterface; |
||||
use Monolog\Formatter\ElasticaFormatter; |
||||
use Monolog\Logger; |
||||
use Elastica\Client; |
||||
use Elastica\Exception\ExceptionInterface; |
||||
|
||||
/** |
||||
* Elastic Search handler |
||||
* |
||||
* Usage example: |
||||
* |
||||
* $client = new \Elastica\Client(); |
||||
* $options = array( |
||||
* 'index' => 'elastic_index_name', |
||||
* 'type' => 'elastic_doc_type', |
||||
* ); |
||||
* $handler = new ElasticSearchHandler($client, $options); |
||||
* $log = new Logger('application'); |
||||
* $log->pushHandler($handler); |
||||
* |
||||
* @author Jelle Vink <jelle.vink@gmail.com> |
||||
*/ |
||||
class ElasticSearchHandler extends AbstractProcessingHandler |
||||
{ |
||||
/** |
||||
* @var Client |
||||
*/ |
||||
protected $client; |
||||
|
||||
/** |
||||
* @var array Handler config options |
||||
*/ |
||||
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 |
||||
*/ |
||||
public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
parent::__construct($level, $bubble); |
||||
$this->client = $client; |
||||
$this->options = array_merge( |
||||
array( |
||||
'index' => 'monolog', // Elastic index name |
||||
'type' => 'record', // Elastic document type |
||||
'ignore_error' => false, // Suppress Elastica exceptions |
||||
), |
||||
$options |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
$this->bulkSend(array($record['formatted'])); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setFormatter(FormatterInterface $formatter) |
||||
{ |
||||
if ($formatter instanceof ElasticaFormatter) { |
||||
return parent::setFormatter($formatter); |
||||
} |
||||
throw new \InvalidArgumentException('ElasticSearchHandler is only compatible with ElasticaFormatter'); |
||||
} |
||||
|
||||
/** |
||||
* Getter options |
||||
* @return array |
||||
*/ |
||||
public function getOptions() |
||||
{ |
||||
return $this->options; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
protected function getDefaultFormatter() |
||||
{ |
||||
return new ElasticaFormatter($this->options['index'], $this->options['type']); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handleBatch(array $records) |
||||
{ |
||||
$documents = $this->getFormatter()->formatBatch($records); |
||||
$this->bulkSend($documents); |
||||
} |
||||
|
||||
/** |
||||
* Use Elasticsearch bulk API to send list of documents |
||||
* @param array $documents |
||||
* @throws \RuntimeException |
||||
*/ |
||||
protected function bulkSend(array $documents) |
||||
{ |
||||
try { |
||||
$this->client->addDocuments($documents); |
||||
} catch (ExceptionInterface $e) { |
||||
if (!$this->options['ignore_error']) { |
||||
throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,131 @@ |
||||
<?php |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Simple handler wrapper that filters records based on a list of levels |
||||
* |
||||
* It can be configured with an exact list of levels to allow, or a min/max level. |
||||
* |
||||
* @author Hennadiy Verkh |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class FilterHandler extends AbstractHandler |
||||
{ |
||||
/** |
||||
* Handler or factory callable($record, $this) |
||||
* |
||||
* @var callable|\Monolog\Handler\HandlerInterface |
||||
*/ |
||||
protected $handler; |
||||
|
||||
/** |
||||
* Minimum level for logs that are passes to handler |
||||
* |
||||
* @var int |
||||
*/ |
||||
protected $acceptedLevels; |
||||
|
||||
/** |
||||
* Whether the messages that are handled can bubble up the stack or not |
||||
* |
||||
* @var Boolean |
||||
*/ |
||||
protected $bubble; |
||||
|
||||
/** |
||||
* @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 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) |
||||
{ |
||||
$this->handler = $handler; |
||||
$this->bubble = $bubble; |
||||
$this->setAcceptedLevels($minLevelOrList, $maxLevel); |
||||
} |
||||
|
||||
/** |
||||
* @return array |
||||
*/ |
||||
public function getAcceptedLevels() |
||||
{ |
||||
return array_flip($this->acceptedLevels); |
||||
} |
||||
|
||||
/** |
||||
* @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 |
||||
*/ |
||||
public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY) |
||||
{ |
||||
if (is_array($minLevelOrList)) { |
||||
$acceptedLevels = $minLevelOrList; |
||||
} else { |
||||
$acceptedLevels = array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) { |
||||
return $level >= $minLevelOrList && $level <= $maxLevel; |
||||
}); |
||||
} |
||||
$this->acceptedLevels = array_flip($acceptedLevels); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isHandling(array $record) |
||||
{ |
||||
return isset($this->acceptedLevels[$record['level']]); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handle(array $record) |
||||
{ |
||||
if (!$this->isHandling($record)) { |
||||
return false; |
||||
} |
||||
|
||||
// The same logic as in FingersCrossedHandler |
||||
if (!$this->handler instanceof HandlerInterface) { |
||||
if (!is_callable($this->handler)) { |
||||
throw new \RuntimeException( |
||||
"The given handler (" . json_encode($this->handler) |
||||
. ") is not a callable nor a Monolog\\Handler\\HandlerInterface object" |
||||
); |
||||
} |
||||
$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->handler->handle($record); |
||||
|
||||
return false === $this->bubble; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handleBatch(array $records) |
||||
{ |
||||
$filtered = array(); |
||||
foreach ($records as $record) { |
||||
if ($this->isHandling($record)) { |
||||
$filtered[] = $record; |
||||
} |
||||
} |
||||
|
||||
$this->handler->handleBatch($filtered); |
||||
} |
||||
} |
||||
@ -0,0 +1,103 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* Sends notifications through the Flowdock push API |
||||
* |
||||
* This must be configured with a FlowdockFormatter instance via setFormatter() |
||||
* |
||||
* Notes: |
||||
* API token - Flowdock API token |
||||
* |
||||
* @author Dominik Liebler <liebler.dominik@gmail.com> |
||||
* @see https://www.flowdock.com/api/push |
||||
*/ |
||||
class FlowdockHandler extends SocketHandler |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $apiToken; |
||||
|
||||
/** |
||||
* @param string $apiToken |
||||
* @param bool|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 |
||||
* |
||||
* @throws MissingExtensionException if OpenSSL is missing |
||||
*/ |
||||
public function __construct($apiToken, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
if (!extension_loaded('openssl')) { |
||||
throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler'); |
||||
} |
||||
|
||||
parent::__construct('ssl://api.flowdock.com:443', $level, $bubble); |
||||
$this->apiToken = $apiToken; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @param array $record |
||||
*/ |
||||
public function write(array $record) |
||||
{ |
||||
parent::write($record); |
||||
|
||||
$this->closeSocket(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* |
||||
* @param array $record |
||||
* @return string |
||||
*/ |
||||
protected function generateDataStream($record) |
||||
{ |
||||
$content = $this->buildContent($record); |
||||
|
||||
return $this->buildHeader($content) . $content; |
||||
} |
||||
|
||||
/** |
||||
* Builds the body of API call |
||||
* |
||||
* @param array $record |
||||
* @return string |
||||
*/ |
||||
private function buildContent($record) |
||||
{ |
||||
return json_encode($record['formatted']['flowdock']); |
||||
} |
||||
|
||||
/** |
||||
* Builds the header of the API Call |
||||
* |
||||
* @param string $content |
||||
* @return string |
||||
*/ |
||||
private function buildHeader($content) |
||||
{ |
||||
$header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n"; |
||||
$header .= "Host: api.flowdock.com\r\n"; |
||||
$header .= "Content-Type: application/json\r\n"; |
||||
$header .= "Content-Length: " . strlen($content) . "\r\n"; |
||||
$header .= "\r\n"; |
||||
|
||||
return $header; |
||||
} |
||||
} |
||||
@ -0,0 +1,57 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* @author Robert Kaufmann III <rok3@rok3.me> |
||||
*/ |
||||
class LogEntriesHandler extends SocketHandler |
||||
{ |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $logToken; |
||||
|
||||
/** |
||||
* @param string $token Log token supplied by LogEntries |
||||
* @param boolean $useSSL Whether or not SSL encryption should be used. |
||||
* @param int $level The minimum logging level to trigger this handler |
||||
* @param boolean $bubble Whether or not messages that are handled should bubble up the stack. |
||||
* |
||||
* @throws MissingExtensionExcpetion If SSL encryption is set to true and OpenSSL is missing |
||||
*/ |
||||
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://api.logentries.com:20000' : 'data.logentries.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']; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,93 @@ |
||||
<?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; |
||||
use Monolog\Formatter\LogglyFormatter; |
||||
|
||||
/** |
||||
* Sends errors to Loggly. |
||||
* |
||||
* @author Przemek Sobstel <przemek@sobstel.org> |
||||
* @author Adam Pancutt <adam@pancutt.com> |
||||
*/ |
||||
class LogglyHandler extends AbstractProcessingHandler |
||||
{ |
||||
const HOST = 'logs-01.loggly.com'; |
||||
const ENDPOINT_SINGLE = 'inputs'; |
||||
const ENDPOINT_BATCH = 'bulk'; |
||||
|
||||
protected $token; |
||||
|
||||
protected $tag; |
||||
|
||||
public function __construct($token, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
if (!extension_loaded('curl')) { |
||||
throw new \LogicException('The curl extension is needed to use the LogglyHandler'); |
||||
} |
||||
|
||||
$this->token = $token; |
||||
|
||||
parent::__construct($level, $bubble); |
||||
} |
||||
|
||||
public function setTag($tag) |
||||
{ |
||||
$this->tag = $tag; |
||||
} |
||||
|
||||
protected function write(array $record) |
||||
{ |
||||
$this->send($record["formatted"], self::ENDPOINT_SINGLE); |
||||
} |
||||
|
||||
public function handleBatch(array $records) |
||||
{ |
||||
$level = $this->level; |
||||
|
||||
$records = array_filter($records, function ($record) use ($level) { |
||||
return ($record['level'] >= $level); |
||||
}); |
||||
|
||||
if ($records) { |
||||
$this->send($this->getFormatter()->formatBatch($records), self::ENDPOINT_BATCH); |
||||
} |
||||
} |
||||
|
||||
protected function send($data, $endpoint) |
||||
{ |
||||
$url = sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token); |
||||
|
||||
$headers = array('Content-Type: application/json'); |
||||
|
||||
if ($this->tag) { |
||||
$headers[] = "X-LOGGLY-TAG: {$this->tag}"; |
||||
} |
||||
|
||||
$ch = curl_init(); |
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $url); |
||||
curl_setopt($ch, CURLOPT_POST, true); |
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); |
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); |
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||
|
||||
curl_exec($ch); |
||||
curl_close($ch); |
||||
} |
||||
|
||||
protected function getDefaultFormatter() |
||||
{ |
||||
return new LogglyFormatter(); |
||||
} |
||||
} |
||||
@ -0,0 +1,64 @@ |
||||
<?php |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use RollbarNotifier; |
||||
use Exception; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Sends errors to Rollbar |
||||
* |
||||
* @author Paul Statezny <paulstatezny@gmail.com> |
||||
*/ |
||||
class RollbarHandler extends AbstractProcessingHandler |
||||
{ |
||||
/** |
||||
* Rollbar notifier |
||||
* |
||||
* @var RollbarNotifier |
||||
*/ |
||||
protected $rollbarNotifier; |
||||
|
||||
/** |
||||
* @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token |
||||
* @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(RollbarNotifier $rollbarNotifier, $level = Logger::ERROR, $bubble = true) |
||||
{ |
||||
$this->rollbarNotifier = $rollbarNotifier; |
||||
|
||||
parent::__construct($level, $bubble); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) { |
||||
$this->rollbarNotifier->report_exception($record['context']['exception']); |
||||
} else { |
||||
$extraData = array( |
||||
'level' => $record['level'], |
||||
'channel' => $record['channel'], |
||||
'datetime' => $record['datetime']->format('U'), |
||||
); |
||||
|
||||
$this->rollbarNotifier->report_message( |
||||
$record['message'], |
||||
$record['level_name'], |
||||
array_merge($record['context'], $record['extra'], $extraData) |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function close() |
||||
{ |
||||
$this->rollbarNotifier->flush(); |
||||
} |
||||
} |
||||
@ -0,0 +1,62 @@ |
||||
<?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\SyslogUdp; |
||||
|
||||
class UdpSocket |
||||
{ |
||||
const DATAGRAM_MAX_LENGTH = 2048; |
||||
|
||||
public function __construct($ip, $port = 514) |
||||
{ |
||||
$this->ip = $ip; |
||||
$this->port = $port; |
||||
$this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); |
||||
} |
||||
|
||||
public function write($line, $header = "") |
||||
{ |
||||
$remaining = $line; |
||||
while (!is_null($remaining)) { |
||||
list($chunk, $remaining) = $this->splitLineIfNessesary($remaining, $header); |
||||
$this->send($chunk); |
||||
} |
||||
} |
||||
|
||||
public function close() |
||||
{ |
||||
socket_close($this->socket); |
||||
} |
||||
|
||||
protected function send($chunk) |
||||
{ |
||||
socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port); |
||||
} |
||||
|
||||
protected function splitLineIfNessesary($line, $header) |
||||
{ |
||||
if ($this->shouldSplitLine($line, $header)) { |
||||
$chunkSize = self::DATAGRAM_MAX_LENGTH - strlen($header); |
||||
$chunk = $header . substr($line, 0, $chunkSize); |
||||
$remaining = substr($line, $chunkSize); |
||||
} else { |
||||
$chunk = $header . $line; |
||||
$remaining = null; |
||||
} |
||||
|
||||
return array($chunk, $remaining); |
||||
} |
||||
|
||||
protected function shouldSplitLine($remaining, $header) |
||||
{ |
||||
return strlen($header.$remaining) > self::DATAGRAM_MAX_LENGTH; |
||||
} |
||||
} |
||||
@ -0,0 +1,80 @@ |
||||
<?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; |
||||
use Monolog\Handler\SyslogUdp\UdpSocket; |
||||
|
||||
/** |
||||
* A Handler for logging to a remote syslogd server. |
||||
* |
||||
* @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com> |
||||
*/ |
||||
class SyslogUdpHandler extends AbstractSyslogHandler |
||||
{ |
||||
/** |
||||
* @param string $host |
||||
* @param int $port |
||||
* @param mixed $facility |
||||
* @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($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
parent::__construct($facility, $level, $bubble); |
||||
|
||||
$this->socket = new UdpSocket($host, $port ?: 514); |
||||
} |
||||
|
||||
protected function write(array $record) |
||||
{ |
||||
$lines = $this->splitMessageIntoLines($record['formatted']); |
||||
|
||||
$header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]); |
||||
|
||||
foreach ($lines as $line) { |
||||
$this->socket->write($line, $header); |
||||
} |
||||
} |
||||
|
||||
public function close() |
||||
{ |
||||
$this->socket->close(); |
||||
} |
||||
|
||||
private function splitMessageIntoLines($message) |
||||
{ |
||||
if (is_array($message)) { |
||||
$message = implode("\n", $message); |
||||
} |
||||
|
||||
return preg_split('/$\R?^/m', $message); |
||||
} |
||||
|
||||
/** |
||||
* Make common syslog header (see rfc5424) |
||||
*/ |
||||
private function makeCommonSyslogHeader($severity) |
||||
{ |
||||
$priority = $severity + $this->facility; |
||||
|
||||
return "<$priority>: "; |
||||
} |
||||
|
||||
/** |
||||
* Inject your own socket, mainly used for testing |
||||
*/ |
||||
public function setSocket($socket) |
||||
{ |
||||
$this->socket = $socket; |
||||
} |
||||
} |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* Adds a tags array into record |
||||
* |
||||
* @author Martijn Riemers |
||||
*/ |
||||
class TagProcessor |
||||
{ |
||||
private $tags; |
||||
|
||||
public function __construct(array $tags = array()) |
||||
{ |
||||
$this->tags = $tags; |
||||
} |
||||
|
||||
public function __invoke(array $record) |
||||
{ |
||||
$record['extra']['tags'] = $this->tags; |
||||
|
||||
return $record; |
||||
} |
||||
} |
||||
@ -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|null $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); |
||||
} |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
<?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 Monolog\Handler\TestHandler; |
||||
|
||||
class ErrorHandlerTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public function testHandleError() |
||||
{ |
||||
$logger = new Logger('test', array($handler = new TestHandler)); |
||||
$errHandler = new ErrorHandler($logger); |
||||
|
||||
$errHandler->registerErrorHandler(array(E_USER_NOTICE => Logger::EMERGENCY), false); |
||||
trigger_error('Foo', E_USER_ERROR); |
||||
$this->assertCount(1, $handler->getRecords()); |
||||
$this->assertTrue($handler->hasErrorRecords()); |
||||
trigger_error('Foo', E_USER_NOTICE); |
||||
$this->assertCount(2, $handler->getRecords()); |
||||
$this->assertTrue($handler->hasEmergencyRecords()); |
||||
} |
||||
} |
||||
@ -0,0 +1,158 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
class ChromePHPFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Formatter\ChromePHPFormatter::format |
||||
*/ |
||||
public function testDefaultFormat() |
||||
{ |
||||
$formatter = new ChromePHPFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('ip' => '127.0.0.1'), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertEquals( |
||||
array( |
||||
'meh', |
||||
array( |
||||
'message' => 'log', |
||||
'context' => array('from' => 'logger'), |
||||
'extra' => array('ip' => '127.0.0.1'), |
||||
), |
||||
'unknown', |
||||
'error' |
||||
), |
||||
$message |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\ChromePHPFormatter::format |
||||
*/ |
||||
public function testFormatWithFileAndLine() |
||||
{ |
||||
$formatter = new ChromePHPFormatter(); |
||||
$record = array( |
||||
'level' => Logger::CRITICAL, |
||||
'level_name' => 'CRITICAL', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertEquals( |
||||
array( |
||||
'meh', |
||||
array( |
||||
'message' => 'log', |
||||
'context' => array('from' => 'logger'), |
||||
'extra' => array('ip' => '127.0.0.1'), |
||||
), |
||||
'test : 14', |
||||
'error' |
||||
), |
||||
$message |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\ChromePHPFormatter::format |
||||
*/ |
||||
public function testFormatWithoutContext() |
||||
{ |
||||
$formatter = new ChromePHPFormatter(); |
||||
$record = array( |
||||
'level' => Logger::DEBUG, |
||||
'level_name' => 'DEBUG', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertEquals( |
||||
array( |
||||
'meh', |
||||
'log', |
||||
'unknown', |
||||
'log' |
||||
), |
||||
$message |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\ChromePHPFormatter::formatBatch |
||||
*/ |
||||
public function testBatchFormatThrowException() |
||||
{ |
||||
$formatter = new ChromePHPFormatter(); |
||||
$records = array( |
||||
array( |
||||
'level' => Logger::INFO, |
||||
'level_name' => 'INFO', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
), |
||||
array( |
||||
'level' => Logger::WARNING, |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'foo', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log2', |
||||
), |
||||
); |
||||
|
||||
$this->assertEquals( |
||||
array( |
||||
array( |
||||
'meh', |
||||
'log', |
||||
'unknown', |
||||
'info' |
||||
), |
||||
array( |
||||
'foo', |
||||
'log2', |
||||
'unknown', |
||||
'warn' |
||||
), |
||||
), |
||||
$formatter->formatBatch($records) |
||||
); |
||||
} |
||||
} |
||||
@ -0,0 +1,79 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
class ElasticaFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
if (!class_exists("Elastica\Document")) { |
||||
$this->markTestSkipped("ruflin/elastica not installed"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\ElasticaFormatter::__construct |
||||
* @covers Monolog\Formatter\ElasticaFormatter::format |
||||
* @covers Monolog\Formatter\ElasticaFormatter::getDocument |
||||
*/ |
||||
public function testFormat() |
||||
{ |
||||
// test log message |
||||
$msg = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
// expected values |
||||
$expected = $msg; |
||||
$expected['datetime'] = '1970-01-01T00:00:00+0000'; |
||||
$expected['context'] = array( |
||||
'class' => '[object] (stdClass: {})', |
||||
'foo' => 7, |
||||
0 => 'bar', |
||||
); |
||||
|
||||
// format log message |
||||
$formatter = new ElasticaFormatter('my_index', 'doc_type'); |
||||
$doc = $formatter->format($msg); |
||||
$this->assertInstanceOf('Elastica\Document', $doc); |
||||
|
||||
// Document parameters |
||||
$params = $doc->getParams(); |
||||
$this->assertEquals('my_index', $params['_index']); |
||||
$this->assertEquals('doc_type', $params['_type']); |
||||
|
||||
// Document data values |
||||
$data = $doc->getData(); |
||||
foreach (array_keys($expected) as $key) { |
||||
$this->assertEquals($expected[$key], $data[$key]); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\ElasticaFormatter::getIndex |
||||
* @covers Monolog\Formatter\ElasticaFormatter::getType |
||||
*/ |
||||
public function testGetters() |
||||
{ |
||||
$formatter = new ElasticaFormatter('my_index', 'doc_type'); |
||||
$this->assertEquals('my_index', $formatter->getIndex()); |
||||
$this->assertEquals('doc_type', $formatter->getType()); |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\TestCase; |
||||
|
||||
class FlowdockFormatterTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Formatter\FlowdockFormatter::format |
||||
*/ |
||||
public function testFormat() |
||||
{ |
||||
$formatter = new FlowdockFormatter('test_source', 'source@test.com'); |
||||
$record = $this->getRecord(); |
||||
|
||||
$expected = array( |
||||
'source' => 'test_source', |
||||
'from_address' => 'source@test.com', |
||||
'subject' => 'in test_source: WARNING - test', |
||||
'content' => 'test', |
||||
'tags' => array('#logs', '#warning', '#test'), |
||||
'project' => 'test_source', |
||||
); |
||||
$formatted = $formatter->format($record); |
||||
|
||||
$this->assertEquals($expected, $formatted['flowdock']); |
||||
} |
||||
|
||||
/** |
||||
* @ covers Monolog\Formatter\FlowdockFormatter::formatBatch |
||||
*/ |
||||
public function testFormatBatch() |
||||
{ |
||||
$formatter = new FlowdockFormatter('test_source', 'source@test.com'); |
||||
$records = array( |
||||
$this->getRecord(Logger::WARNING), |
||||
$this->getRecord(Logger::DEBUG), |
||||
); |
||||
$formatted = $formatter->formatBatch($records); |
||||
|
||||
$this->assertArrayHasKey('flowdock', $formatted[0]); |
||||
$this->assertArrayHasKey('flowdock', $formatted[1]); |
||||
} |
||||
} |
||||
@ -0,0 +1,191 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
class GelfMessageFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
if (!class_exists('\Gelf\Message')) { |
||||
$this->markTestSkipped("graylog2/gelf-php or mlehner/gelf-php is not installed"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format |
||||
*/ |
||||
public function testDefaultFormatter() |
||||
{ |
||||
$formatter = new GelfMessageFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
$this->assertEquals(0, $message->getTimestamp()); |
||||
$this->assertEquals('log', $message->getShortMessage()); |
||||
$this->assertEquals('meh', $message->getFacility()); |
||||
$this->assertEquals(null, $message->getLine()); |
||||
$this->assertEquals(null, $message->getFile()); |
||||
$this->assertEquals($this->isLegacy() ? 3 : 'error', $message->getLevel()); |
||||
$this->assertNotEmpty($message->getHost()); |
||||
|
||||
$formatter = new GelfMessageFormatter('mysystem'); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
$this->assertEquals('mysystem', $message->getHost()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format |
||||
*/ |
||||
public function testFormatWithFileAndLine() |
||||
{ |
||||
$formatter = new GelfMessageFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('file' => 'test', 'line' => 14), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
$this->assertEquals('test', $message->getFile()); |
||||
$this->assertEquals(14, $message->getLine()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format |
||||
*/ |
||||
public function testFormatWithContext() |
||||
{ |
||||
$formatter = new GelfMessageFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
|
||||
$message_array = $message->toArray(); |
||||
|
||||
$this->assertArrayHasKey('_ctxt_from', $message_array); |
||||
$this->assertEquals('logger', $message_array['_ctxt_from']); |
||||
|
||||
// Test with extraPrefix |
||||
$formatter = new GelfMessageFormatter(null, null, 'CTX'); |
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
|
||||
$message_array = $message->toArray(); |
||||
|
||||
$this->assertArrayHasKey('_CTXfrom', $message_array); |
||||
$this->assertEquals('logger', $message_array['_CTXfrom']); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format |
||||
*/ |
||||
public function testFormatWithContextContainingException() |
||||
{ |
||||
$formatter = new GelfMessageFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger', 'exception' => array( |
||||
'class' => '\Exception', |
||||
'file' => '/some/file/in/dir.php:56', |
||||
'trace' => array('/some/file/1.php:23', '/some/file/2.php:3') |
||||
)), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
|
||||
$this->assertEquals("/some/file/in/dir.php", $message->getFile()); |
||||
$this->assertEquals("56", $message->getLine()); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format |
||||
*/ |
||||
public function testFormatWithExtra() |
||||
{ |
||||
$formatter = new GelfMessageFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
|
||||
$message_array = $message->toArray(); |
||||
|
||||
$this->assertArrayHasKey('_key', $message_array); |
||||
$this->assertEquals('pair', $message_array['_key']); |
||||
|
||||
// Test with extraPrefix |
||||
$formatter = new GelfMessageFormatter(null, 'EXT'); |
||||
$message = $formatter->format($record); |
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message); |
||||
|
||||
$message_array = $message->toArray(); |
||||
|
||||
$this->assertArrayHasKey('_EXTkey', $message_array); |
||||
$this->assertEquals('pair', $message_array['_EXTkey']); |
||||
} |
||||
|
||||
private function isLegacy() |
||||
{ |
||||
return interface_exists('\Gelf\IMessagePublisher'); |
||||
} |
||||
} |
||||
@ -0,0 +1,79 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\TestCase; |
||||
|
||||
class JsonFormatterTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Formatter\JsonFormatter::__construct |
||||
* @covers Monolog\Formatter\JsonFormatter::getBatchMode |
||||
* @covers Monolog\Formatter\JsonFormatter::isAppendingNewlines |
||||
*/ |
||||
public function testConstruct() |
||||
{ |
||||
$formatter = new JsonFormatter(); |
||||
$this->assertEquals(JsonFormatter::BATCH_MODE_JSON, $formatter->getBatchMode()); |
||||
$this->assertEquals(true, $formatter->isAppendingNewlines()); |
||||
$formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES, false); |
||||
$this->assertEquals(JsonFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode()); |
||||
$this->assertEquals(false, $formatter->isAppendingNewlines()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\JsonFormatter::format |
||||
*/ |
||||
public function testFormat() |
||||
{ |
||||
$formatter = new JsonFormatter(); |
||||
$record = $this->getRecord(); |
||||
$this->assertEquals(json_encode($record)."\n", $formatter->format($record)); |
||||
|
||||
$formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); |
||||
$record = $this->getRecord(); |
||||
$this->assertEquals(json_encode($record), $formatter->format($record)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatch |
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatchJson |
||||
*/ |
||||
public function testFormatBatch() |
||||
{ |
||||
$formatter = new JsonFormatter(); |
||||
$records = array( |
||||
$this->getRecord(Logger::WARNING), |
||||
$this->getRecord(Logger::DEBUG), |
||||
); |
||||
$this->assertEquals(json_encode($records), $formatter->formatBatch($records)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatch |
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatchNewlines |
||||
*/ |
||||
public function testFormatBatchNewlines() |
||||
{ |
||||
|
||||
$formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES); |
||||
$records = $expected = array( |
||||
$this->getRecord(Logger::WARNING), |
||||
$this->getRecord(Logger::DEBUG), |
||||
); |
||||
array_walk($expected, function (&$value, $key) { |
||||
$value = json_encode($value); |
||||
}); |
||||
$this->assertEquals(implode("\n", $expected), $formatter->formatBatch($records)); |
||||
} |
||||
} |
||||
@ -0,0 +1,194 @@ |
||||
<?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\Formatter; |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LineFormatter |
||||
*/ |
||||
class LineFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public function testDefFormatWithString() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$message = $formatter->format(array( |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'log', |
||||
'context' => array(), |
||||
'message' => 'foo', |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
)); |
||||
$this->assertEquals('['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message); |
||||
} |
||||
|
||||
public function testDefFormatWithArrayContext() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$message = $formatter->format(array( |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'message' => 'foo', |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
'context' => array( |
||||
'foo' => 'bar', |
||||
'baz' => 'qux', |
||||
'bool' => false, |
||||
'null' => null, |
||||
) |
||||
)); |
||||
$this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foo {"foo":"bar","baz":"qux","bool":false,"null":null} []'."\n", $message); |
||||
} |
||||
|
||||
public function testDefFormatExtras() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$message = $formatter->format(array( |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array('ip' => '127.0.0.1'), |
||||
'message' => 'log', |
||||
)); |
||||
$this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] {"ip":"127.0.0.1"}'."\n", $message); |
||||
} |
||||
|
||||
public function testFormatExtras() |
||||
{ |
||||
$formatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context% %extra.file% %extra%\n", 'Y-m-d'); |
||||
$message = $formatter->format(array( |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array('ip' => '127.0.0.1', 'file' => 'test'), |
||||
'message' => 'log', |
||||
)); |
||||
$this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] test {"ip":"127.0.0.1"}'."\n", $message); |
||||
} |
||||
|
||||
public function testDefFormatWithObject() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$message = $formatter->format(array( |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array('foo' => new TestFoo, 'bar' => new TestBar, 'baz' => array(), 'res' => fopen('php://memory', 'rb')), |
||||
'message' => 'foobar', |
||||
)); |
||||
|
||||
$this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foobar [] {"foo":"[object] (Monolog\\\\Formatter\\\\TestFoo: {\\"foo\\":\\"foo\\"})","bar":"[object] (Monolog\\\\Formatter\\\\TestBar: {})","baz":[],"res":"[resource]"}'."\n", $message); |
||||
} |
||||
|
||||
public function testDefFormatWithException() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$message = $formatter->format(array( |
||||
'level_name' => 'CRITICAL', |
||||
'channel' => 'core', |
||||
'context' => array('exception' => new \RuntimeException('Foo')), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
'message' => 'foobar', |
||||
)); |
||||
|
||||
$path = str_replace('\\/', '/', json_encode(__FILE__)); |
||||
|
||||
$this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException: Foo at '.substr($path, 1, -1).':'.(__LINE__-8).')"} []'."\n", $message); |
||||
} |
||||
|
||||
public function testDefFormatWithPreviousException() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$previous = new \LogicException('Wut?'); |
||||
$message = $formatter->format(array( |
||||
'level_name' => 'CRITICAL', |
||||
'channel' => 'core', |
||||
'context' => array('exception' => new \RuntimeException('Foo', 0, $previous)), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
'message' => 'foobar', |
||||
)); |
||||
|
||||
$path = str_replace('\\/', '/', json_encode(__FILE__)); |
||||
|
||||
$this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException: Foo at '.substr($path, 1, -1).':'.(__LINE__-8).', LogicException: Wut? at '.substr($path, 1, -1).':'.(__LINE__-12).')"} []'."\n", $message); |
||||
} |
||||
|
||||
public function testBatchFormat() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$message = $formatter->formatBatch(array( |
||||
array( |
||||
'level_name' => 'CRITICAL', |
||||
'channel' => 'test', |
||||
'message' => 'bar', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
), |
||||
array( |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'log', |
||||
'message' => 'foo', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
), |
||||
)); |
||||
$this->assertEquals('['.date('Y-m-d').'] test.CRITICAL: bar [] []'."\n".'['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message); |
||||
} |
||||
|
||||
public function testFormatShouldStripInlineLineBreaks() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d'); |
||||
$message = $formatter->format( |
||||
array( |
||||
'message' => "foo\nbar", |
||||
'context' => array(), |
||||
'extra' => array(), |
||||
) |
||||
); |
||||
|
||||
$this->assertRegExp('/foo bar/', $message); |
||||
} |
||||
|
||||
public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet() |
||||
{ |
||||
$formatter = new LineFormatter(null, 'Y-m-d', true); |
||||
$message = $formatter->format( |
||||
array( |
||||
'message' => "foo\nbar", |
||||
'context' => array(), |
||||
'extra' => array(), |
||||
) |
||||
); |
||||
|
||||
$this->assertRegExp('/foo\nbar/', $message); |
||||
} |
||||
} |
||||
|
||||
class TestFoo |
||||
{ |
||||
public $foo = 'foo'; |
||||
} |
||||
|
||||
class TestBar |
||||
{ |
||||
public function __toString() |
||||
{ |
||||
return 'bar'; |
||||
} |
||||
} |
||||
@ -0,0 +1,40 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\TestCase; |
||||
|
||||
class LogglyFormatterTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Formatter\LogglyFormatter::__construct |
||||
*/ |
||||
public function testConstruct() |
||||
{ |
||||
$formatter = new LogglyFormatter(); |
||||
$this->assertEquals(LogglyFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode()); |
||||
$formatter = new LogglyFormatter(LogglyFormatter::BATCH_MODE_JSON); |
||||
$this->assertEquals(LogglyFormatter::BATCH_MODE_JSON, $formatter->getBatchMode()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogglyFormatter::format |
||||
*/ |
||||
public function testFormat() |
||||
{ |
||||
$formatter = new LogglyFormatter(); |
||||
$record = $this->getRecord(); |
||||
$formatted_decoded = json_decode($formatter->format($record), true); |
||||
$this->assertArrayHasKey("timestamp", $formatted_decoded); |
||||
$this->assertEquals(new \DateTime($formatted_decoded["timestamp"]), $record["datetime"]); |
||||
} |
||||
} |
||||
@ -0,0 +1,292 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
class LogstashFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testDefaultFormatter() |
||||
{ |
||||
$formatter = new LogstashFormatter('test', 'hostname'); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']); |
||||
$this->assertEquals('log', $message['@message']); |
||||
$this->assertEquals('meh', $message['@fields']['channel']); |
||||
$this->assertContains('meh', $message['@tags']); |
||||
$this->assertEquals(Logger::ERROR, $message['@fields']['level']); |
||||
$this->assertEquals('test', $message['@type']); |
||||
$this->assertEquals('hostname', $message['@source']); |
||||
|
||||
$formatter = new LogstashFormatter('mysystem'); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertEquals('mysystem', $message['@type']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testFormatWithFileAndLine() |
||||
{ |
||||
$formatter = new LogstashFormatter('test'); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('file' => 'test', 'line' => 14), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertEquals('test', $message['@fields']['file']); |
||||
$this->assertEquals(14, $message['@fields']['line']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testFormatWithContext() |
||||
{ |
||||
$formatter = new LogstashFormatter('test'); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$message_array = $message['@fields']; |
||||
|
||||
$this->assertArrayHasKey('ctxt_from', $message_array); |
||||
$this->assertEquals('logger', $message_array['ctxt_from']); |
||||
|
||||
// Test with extraPrefix |
||||
$formatter = new LogstashFormatter('test', null, null, 'CTX'); |
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$message_array = $message['@fields']; |
||||
|
||||
$this->assertArrayHasKey('CTXfrom', $message_array); |
||||
$this->assertEquals('logger', $message_array['CTXfrom']); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testFormatWithExtra() |
||||
{ |
||||
$formatter = new LogstashFormatter('test'); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$message_array = $message['@fields']; |
||||
|
||||
$this->assertArrayHasKey('key', $message_array); |
||||
$this->assertEquals('pair', $message_array['key']); |
||||
|
||||
// Test with extraPrefix |
||||
$formatter = new LogstashFormatter('test', null, 'EXT'); |
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$message_array = $message['@fields']; |
||||
|
||||
$this->assertArrayHasKey('EXTkey', $message_array); |
||||
$this->assertEquals('pair', $message_array['EXTkey']); |
||||
} |
||||
|
||||
public function testFormatWithApplicationName() |
||||
{ |
||||
$formatter = new LogstashFormatter('app', 'test'); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertArrayHasKey('@type', $message); |
||||
$this->assertEquals('app', $message['@type']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testDefaultFormatterV1() |
||||
{ |
||||
$formatter = new LogstashFormatter('test', 'hostname', null, 'ctxt_', LogstashFormatter::V1); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']); |
||||
$this->assertEquals("1", $message['@version']); |
||||
$this->assertEquals('log', $message['message']); |
||||
$this->assertEquals('meh', $message['channel']); |
||||
$this->assertEquals('ERROR', $message['level']); |
||||
$this->assertEquals('test', $message['type']); |
||||
$this->assertEquals('hostname', $message['host']); |
||||
|
||||
$formatter = new LogstashFormatter('mysystem', null, null, 'ctxt_', LogstashFormatter::V1); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertEquals('mysystem', $message['type']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testFormatWithFileAndLineV1() |
||||
{ |
||||
$formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('file' => 'test', 'line' => 14), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertEquals('test', $message['file']); |
||||
$this->assertEquals(14, $message['line']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testFormatWithContextV1() |
||||
{ |
||||
$formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertArrayHasKey('ctxt_from', $message); |
||||
$this->assertEquals('logger', $message['ctxt_from']); |
||||
|
||||
// Test with extraPrefix |
||||
$formatter = new LogstashFormatter('test', null, null, 'CTX', LogstashFormatter::V1); |
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertArrayHasKey('CTXfrom', $message); |
||||
$this->assertEquals('logger', $message['CTXfrom']); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\LogstashFormatter::format |
||||
*/ |
||||
public function testFormatWithExtraV1() |
||||
{ |
||||
$formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertArrayHasKey('key', $message); |
||||
$this->assertEquals('pair', $message['key']); |
||||
|
||||
// Test with extraPrefix |
||||
$formatter = new LogstashFormatter('test', null, 'EXT', 'ctxt_', LogstashFormatter::V1); |
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertArrayHasKey('EXTkey', $message); |
||||
$this->assertEquals('pair', $message['EXTkey']); |
||||
} |
||||
|
||||
public function testFormatWithApplicationNameV1() |
||||
{ |
||||
$formatter = new LogstashFormatter('app', 'test', null, 'ctxt_', LogstashFormatter::V1); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('key' => 'pair'), |
||||
'message' => 'log' |
||||
); |
||||
|
||||
$message = json_decode($formatter->format($record), true); |
||||
|
||||
$this->assertArrayHasKey('type', $message); |
||||
$this->assertEquals('app', $message['type']); |
||||
} |
||||
} |
||||
@ -0,0 +1,182 @@ |
||||
<?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\Formatter; |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\NormalizerFormatter |
||||
*/ |
||||
class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public function testFormat() |
||||
{ |
||||
$formatter = new NormalizerFormatter('Y-m-d'); |
||||
$formatted = $formatter->format(array( |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'message' => 'foo', |
||||
'datetime' => new \DateTime, |
||||
'extra' => array('foo' => new TestFooNorm, 'bar' => new TestBarNorm, 'baz' => array(), 'res' => fopen('php://memory', 'rb')), |
||||
'context' => array( |
||||
'foo' => 'bar', |
||||
'baz' => 'qux', |
||||
), |
||||
)); |
||||
|
||||
$this->assertEquals(array( |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'message' => 'foo', |
||||
'datetime' => date('Y-m-d'), |
||||
'extra' => array( |
||||
'foo' => '[object] (Monolog\\Formatter\\TestFooNorm: {"foo":"foo"})', |
||||
'bar' => '[object] (Monolog\\Formatter\\TestBarNorm: {})', |
||||
'baz' => array(), |
||||
'res' => '[resource]', |
||||
), |
||||
'context' => array( |
||||
'foo' => 'bar', |
||||
'baz' => 'qux', |
||||
) |
||||
), $formatted); |
||||
} |
||||
|
||||
public function testFormatExceptions() |
||||
{ |
||||
$formatter = new NormalizerFormatter('Y-m-d'); |
||||
$e = new \LogicException('bar'); |
||||
$e2 = new \RuntimeException('foo', 0, $e); |
||||
$formatted = $formatter->format(array( |
||||
'exception' => $e2, |
||||
)); |
||||
|
||||
$this->assertGreaterThan(5, count($formatted['exception']['trace'])); |
||||
$this->assertTrue(isset($formatted['exception']['previous'])); |
||||
unset($formatted['exception']['trace'], $formatted['exception']['previous']); |
||||
|
||||
$this->assertEquals(array( |
||||
'exception' => array( |
||||
'class' => get_class($e2), |
||||
'message' => $e2->getMessage(), |
||||
'file' => $e2->getFile().':'.$e2->getLine(), |
||||
) |
||||
), $formatted); |
||||
} |
||||
|
||||
public function testBatchFormat() |
||||
{ |
||||
$formatter = new NormalizerFormatter('Y-m-d'); |
||||
$formatted = $formatter->formatBatch(array( |
||||
array( |
||||
'level_name' => 'CRITICAL', |
||||
'channel' => 'test', |
||||
'message' => 'bar', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
), |
||||
array( |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'log', |
||||
'message' => 'foo', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime, |
||||
'extra' => array(), |
||||
), |
||||
)); |
||||
$this->assertEquals(array( |
||||
array( |
||||
'level_name' => 'CRITICAL', |
||||
'channel' => 'test', |
||||
'message' => 'bar', |
||||
'context' => array(), |
||||
'datetime' => date('Y-m-d'), |
||||
'extra' => array(), |
||||
), |
||||
array( |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'log', |
||||
'message' => 'foo', |
||||
'context' => array(), |
||||
'datetime' => date('Y-m-d'), |
||||
'extra' => array(), |
||||
), |
||||
), $formatted); |
||||
} |
||||
|
||||
/** |
||||
* Test issue #137 |
||||
*/ |
||||
public function testIgnoresRecursiveObjectReferences() |
||||
{ |
||||
// set up the recursion |
||||
$foo = new \stdClass(); |
||||
$bar = new \stdClass(); |
||||
|
||||
$foo->bar = $bar; |
||||
$bar->foo = $foo; |
||||
|
||||
// set an error handler to assert that the error is not raised anymore |
||||
$that = $this; |
||||
set_error_handler(function ($level, $message, $file, $line, $context) use ($that) { |
||||
if (error_reporting() & $level) { |
||||
restore_error_handler(); |
||||
$that->fail("$message should not be raised"); |
||||
} |
||||
}); |
||||
|
||||
$formatter = new NormalizerFormatter(); |
||||
$reflMethod = new \ReflectionMethod($formatter, 'toJson'); |
||||
$reflMethod->setAccessible(true); |
||||
$res = $reflMethod->invoke($formatter, array($foo, $bar), true); |
||||
|
||||
restore_error_handler(); |
||||
|
||||
$this->assertEquals(@json_encode(array($foo, $bar)), $res); |
||||
} |
||||
|
||||
public function testIgnoresInvalidTypes() |
||||
{ |
||||
// set up the recursion |
||||
$resource = fopen(__FILE__, 'r'); |
||||
|
||||
// set an error handler to assert that the error is not raised anymore |
||||
$that = $this; |
||||
set_error_handler(function ($level, $message, $file, $line, $context) use ($that) { |
||||
if (error_reporting() & $level) { |
||||
restore_error_handler(); |
||||
$that->fail("$message should not be raised"); |
||||
} |
||||
}); |
||||
|
||||
$formatter = new NormalizerFormatter(); |
||||
$reflMethod = new \ReflectionMethod($formatter, 'toJson'); |
||||
$reflMethod->setAccessible(true); |
||||
$res = $reflMethod->invoke($formatter, array($resource), true); |
||||
|
||||
restore_error_handler(); |
||||
|
||||
$this->assertEquals(@json_encode(array($resource)), $res); |
||||
} |
||||
} |
||||
|
||||
class TestFooNorm |
||||
{ |
||||
public $foo = 'foo'; |
||||
} |
||||
|
||||
class TestBarNorm |
||||
{ |
||||
public function __toString() |
||||
{ |
||||
return 'bar'; |
||||
} |
||||
} |
||||
@ -0,0 +1,96 @@ |
||||
<?php |
||||
namespace Monolog\Formatter; |
||||
|
||||
class ScalarFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
$this->formatter = new ScalarFormatter(); |
||||
} |
||||
|
||||
public function buildTrace(\Exception $e) |
||||
{ |
||||
$data = array(); |
||||
$trace = $e->getTrace(); |
||||
foreach ($trace as $frame) { |
||||
if (isset($frame['file'])) { |
||||
$data[] = $frame['file'].':'.$frame['line']; |
||||
} else { |
||||
$data[] = json_encode($frame); |
||||
} |
||||
} |
||||
|
||||
return $data; |
||||
} |
||||
|
||||
public function encodeJson($data) |
||||
{ |
||||
if (version_compare(PHP_VERSION, '5.4.0', '>=')) { |
||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); |
||||
} |
||||
|
||||
return json_encode($data); |
||||
} |
||||
|
||||
public function testFormat() |
||||
{ |
||||
$exception = new \Exception('foo'); |
||||
$formatted = $this->formatter->format(array( |
||||
'foo' => 'string', |
||||
'bar' => 1, |
||||
'baz' => false, |
||||
'bam' => array(1,2,3), |
||||
'bat' => array('foo' => 'bar'), |
||||
'bap' => \DateTime::createFromFormat(\DateTime::ISO8601, '1970-01-01T00:00:00+0000'), |
||||
'ban' => $exception |
||||
)); |
||||
|
||||
$this->assertSame(array( |
||||
'foo' => 'string', |
||||
'bar' => 1, |
||||
'baz' => false, |
||||
'bam' => $this->encodeJson(array(1,2,3)), |
||||
'bat' => $this->encodeJson(array('foo' => 'bar')), |
||||
'bap' => '1970-01-01 00:00:00', |
||||
'ban' => $this->encodeJson(array( |
||||
'class' => get_class($exception), |
||||
'message' => $exception->getMessage(), |
||||
'file' => $exception->getFile() . ':' . $exception->getLine(), |
||||
'trace' => $this->buildTrace($exception) |
||||
)) |
||||
), $formatted); |
||||
} |
||||
|
||||
public function testFormatWithErrorContext() |
||||
{ |
||||
$context = array('file' => 'foo', 'line' => 1); |
||||
$formatted = $this->formatter->format(array( |
||||
'context' => $context |
||||
)); |
||||
|
||||
$this->assertSame(array( |
||||
'context' => $this->encodeJson($context) |
||||
), $formatted); |
||||
} |
||||
|
||||
public function testFormatWithExceptionContext() |
||||
{ |
||||
$exception = new \Exception('foo'); |
||||
$formatted = $this->formatter->format(array( |
||||
'context' => array( |
||||
'exception' => $exception |
||||
) |
||||
)); |
||||
|
||||
$this->assertSame(array( |
||||
'context' => $this->encodeJson(array( |
||||
'exception' => array( |
||||
'class' => get_class($exception), |
||||
'message' => $exception->getMessage(), |
||||
'file' => $exception->getFile() . ':' . $exception->getLine(), |
||||
'trace' => $this->buildTrace($exception) |
||||
) |
||||
)) |
||||
), $formatted); |
||||
} |
||||
} |
||||
@ -0,0 +1,142 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
class WildfireFormatterTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Formatter\WildfireFormatter::format |
||||
*/ |
||||
public function testDefaultFormat() |
||||
{ |
||||
$wildfire = new WildfireFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('ip' => '127.0.0.1'), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $wildfire->format($record); |
||||
|
||||
$this->assertEquals( |
||||
'125|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},' |
||||
.'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|', |
||||
$message |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\WildfireFormatter::format |
||||
*/ |
||||
public function testFormatWithFileAndLine() |
||||
{ |
||||
$wildfire = new WildfireFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('from' => 'logger'), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $wildfire->format($record); |
||||
|
||||
$this->assertEquals( |
||||
'129|[{"Type":"ERROR","File":"test","Line":14,"Label":"meh"},' |
||||
.'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|', |
||||
$message |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\WildfireFormatter::format |
||||
*/ |
||||
public function testFormatWithoutContext() |
||||
{ |
||||
$wildfire = new WildfireFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$message = $wildfire->format($record); |
||||
|
||||
$this->assertEquals( |
||||
'58|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},"log"]|', |
||||
$message |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\WildfireFormatter::formatBatch |
||||
* @expectedException BadMethodCallException |
||||
*/ |
||||
public function testBatchFormatThrowException() |
||||
{ |
||||
$wildfire = new WildfireFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array(), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$wildfire->formatBatch(array($record)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Formatter\WildfireFormatter::format |
||||
*/ |
||||
public function testTableFormat() |
||||
{ |
||||
$wildfire = new WildfireFormatter(); |
||||
$record = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'table-channel', |
||||
'context' => array( |
||||
WildfireFormatter::TABLE => array( |
||||
array('col1', 'col2', 'col3'), |
||||
array('val1', 'val2', 'val3'), |
||||
array('foo1', 'foo2', 'foo3'), |
||||
array('bar1', 'bar2', 'bar3'), |
||||
), |
||||
), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'table-message', |
||||
); |
||||
|
||||
$message = $wildfire->format($record); |
||||
|
||||
$this->assertEquals( |
||||
'171|[{"Type":"TABLE","File":"","Line":"","Label":"table-channel: table-message"},[["col1","col2","col3"],["val1","val2","val3"],["foo1","foo2","foo3"],["bar1","bar2","bar3"]]]|', |
||||
$message |
||||
); |
||||
} |
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
<?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. |
||||
*/ |
||||
|
||||
spl_autoload_register(function ($class) { |
||||
$file = __DIR__.'/../../../../src/'.strtr($class, '\\', '/').'.php'; |
||||
if (file_exists($file)) { |
||||
require $file; |
||||
|
||||
return true; |
||||
} |
||||
}); |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\Handler\FirePHPHandler; |
||||
use Monolog\Handler\ChromePHPHandler; |
||||
|
||||
$logger = new Logger('firephp'); |
||||
$logger->pushHandler(new FirePHPHandler); |
||||
$logger->pushHandler(new ChromePHPHandler()); |
||||
|
||||
$logger->addDebug('Debug'); |
||||
$logger->addInfo('Info'); |
||||
$logger->addWarning('Warning'); |
||||
$logger->addError('Error'); |
||||
@ -0,0 +1,104 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\LineFormatter; |
||||
use Monolog\Processor\WebProcessor; |
||||
|
||||
class AbstractHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\AbstractHandler::__construct |
||||
* @covers Monolog\Handler\AbstractHandler::getLevel |
||||
* @covers Monolog\Handler\AbstractHandler::setLevel |
||||
* @covers Monolog\Handler\AbstractHandler::getBubble |
||||
* @covers Monolog\Handler\AbstractHandler::setBubble |
||||
* @covers Monolog\Handler\AbstractHandler::getFormatter |
||||
* @covers Monolog\Handler\AbstractHandler::setFormatter |
||||
*/ |
||||
public function testConstructAndGetSet() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false)); |
||||
$this->assertEquals(Logger::WARNING, $handler->getLevel()); |
||||
$this->assertEquals(false, $handler->getBubble()); |
||||
|
||||
$handler->setLevel(Logger::ERROR); |
||||
$handler->setBubble(true); |
||||
$handler->setFormatter($formatter = new LineFormatter); |
||||
$this->assertEquals(Logger::ERROR, $handler->getLevel()); |
||||
$this->assertEquals(true, $handler->getBubble()); |
||||
$this->assertSame($formatter, $handler->getFormatter()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractHandler::handleBatch |
||||
*/ |
||||
public function testHandleBatch() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); |
||||
$handler->expects($this->exactly(2)) |
||||
->method('handle'); |
||||
$handler->handleBatch(array($this->getRecord(), $this->getRecord())); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractHandler::isHandling |
||||
*/ |
||||
public function testIsHandling() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false)); |
||||
$this->assertTrue($handler->isHandling($this->getRecord())); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractHandler::getFormatter |
||||
* @covers Monolog\Handler\AbstractHandler::getDefaultFormatter |
||||
*/ |
||||
public function testGetFormatterInitializesDefault() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); |
||||
$this->assertInstanceOf('Monolog\Formatter\LineFormatter', $handler->getFormatter()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractHandler::pushProcessor |
||||
* @covers Monolog\Handler\AbstractHandler::popProcessor |
||||
* @expectedException LogicException |
||||
*/ |
||||
public function testPushPopProcessor() |
||||
{ |
||||
$logger = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); |
||||
$processor1 = new WebProcessor; |
||||
$processor2 = new WebProcessor; |
||||
|
||||
$logger->pushProcessor($processor1); |
||||
$logger->pushProcessor($processor2); |
||||
|
||||
$this->assertEquals($processor2, $logger->popProcessor()); |
||||
$this->assertEquals($processor1, $logger->popProcessor()); |
||||
$logger->popProcessor(); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractHandler::pushProcessor |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testPushProcessorWithNonCallable() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); |
||||
|
||||
$handler->pushProcessor(new \stdClass()); |
||||
} |
||||
} |
||||
@ -0,0 +1,80 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
use Monolog\Processor\WebProcessor; |
||||
|
||||
class AbstractProcessingHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle |
||||
*/ |
||||
public function testHandleLowerLevelMessage() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, true)); |
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle |
||||
*/ |
||||
public function testHandleBubbling() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, true)); |
||||
$this->assertFalse($handler->handle($this->getRecord())); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle |
||||
*/ |
||||
public function testHandleNotBubbling() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, false)); |
||||
$this->assertTrue($handler->handle($this->getRecord())); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle |
||||
*/ |
||||
public function testHandleIsFalseWhenNotHandled() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, false)); |
||||
$this->assertTrue($handler->handle($this->getRecord())); |
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\AbstractProcessingHandler::processRecord |
||||
*/ |
||||
public function testProcessRecord() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler'); |
||||
$handler->pushProcessor(new WebProcessor(array( |
||||
'REQUEST_URI' => '', |
||||
'REQUEST_METHOD' => '', |
||||
'REMOTE_ADDR' => '', |
||||
'SERVER_NAME' => '', |
||||
'UNIQUE_ID' => '', |
||||
))); |
||||
$handledRecord = null; |
||||
$handler->expects($this->once()) |
||||
->method('write') |
||||
->will($this->returnCallback(function ($record) use (&$handledRecord) { |
||||
$handledRecord = $record; |
||||
})) |
||||
; |
||||
$handler->handle($this->getRecord()); |
||||
$this->assertEquals(6, count($handledRecord['extra'])); |
||||
} |
||||
} |
||||
@ -0,0 +1,80 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\RotatingFileHandler |
||||
*/ |
||||
class AmqpHandlerTest extends TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
if (!class_exists('AMQPConnection') || !class_exists('AMQPExchange')) { |
||||
$this->markTestSkipped("amqp-php not installed"); |
||||
} |
||||
|
||||
if (!class_exists('AMQPChannel')) { |
||||
$this->markTestSkipped("Please update AMQP to version >= 1.0"); |
||||
} |
||||
} |
||||
|
||||
public function testHandle() |
||||
{ |
||||
$messages = array(); |
||||
|
||||
$exchange = $this->getMock('AMQPExchange', array('publish', 'setName'), array(), '', false); |
||||
$exchange->expects($this->once()) |
||||
->method('setName') |
||||
->with('log') |
||||
; |
||||
$exchange->expects($this->any()) |
||||
->method('publish') |
||||
->will($this->returnCallback(function ($message, $routing_key, $flags = 0, $attributes = array()) use (&$messages) { |
||||
$messages[] = array($message, $routing_key, $flags, $attributes); |
||||
})) |
||||
; |
||||
|
||||
$handler = new AmqpHandler($exchange, 'log'); |
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); |
||||
|
||||
$expected = array( |
||||
array( |
||||
'message' => 'test', |
||||
'context' => array( |
||||
'data' => array(), |
||||
'foo' => 34, |
||||
), |
||||
'level' => 300, |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'test', |
||||
'extra' => array(), |
||||
), |
||||
'warn.test', |
||||
0, |
||||
array( |
||||
'delivery_mode' => 2, |
||||
'Content-type' => 'application/json' |
||||
) |
||||
); |
||||
|
||||
$handler->handle($record); |
||||
|
||||
$this->assertCount(1, $messages); |
||||
$messages[0][0] = json_decode($messages[0][0], true); |
||||
unset($messages[0][0]['datetime']); |
||||
$this->assertEquals($expected, $messages[0]); |
||||
} |
||||
} |
||||
@ -0,0 +1,131 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\BrowserConsoleHandlerTest |
||||
*/ |
||||
class BrowserConsoleHandlerTest extends TestCase |
||||
{ |
||||
protected function setUp() |
||||
{ |
||||
BrowserConsoleHandler::reset(); |
||||
} |
||||
|
||||
protected function generateScript() |
||||
{ |
||||
$reflMethod = new \ReflectionMethod('Monolog\Handler\BrowserConsoleHandler', 'generateScript'); |
||||
$reflMethod->setAccessible(true); |
||||
|
||||
return $reflMethod->invoke(null); |
||||
} |
||||
|
||||
public function testStyling() |
||||
{ |
||||
$handler = new BrowserConsoleHandler(); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, 'foo[[bar]]{color: red}')); |
||||
|
||||
$expected = <<<EOF |
||||
(function (c) {if (c && c.groupCollapsed) { |
||||
c.log("%cfoo%cbar%c", "font-weight: normal", "color: red", "font-weight: normal"); |
||||
}})(console); |
||||
EOF; |
||||
|
||||
$this->assertEquals($expected, $this->generateScript()); |
||||
} |
||||
|
||||
public function testEscaping() |
||||
{ |
||||
$handler = new BrowserConsoleHandler(); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, "[foo] [[\"bar\n[baz]\"]]{color: red}")); |
||||
|
||||
$expected = <<<EOF |
||||
(function (c) {if (c && c.groupCollapsed) { |
||||
c.log("%c[foo] %c\"bar\\n[baz]\"%c", "font-weight: normal", "color: red", "font-weight: normal"); |
||||
}})(console); |
||||
EOF; |
||||
|
||||
$this->assertEquals($expected, $this->generateScript()); |
||||
} |
||||
|
||||
|
||||
public function testAutolabel() |
||||
{ |
||||
$handler = new BrowserConsoleHandler(); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}')); |
||||
$handler->handle($this->getRecord(Logger::DEBUG, '[[bar]]{macro: autolabel}')); |
||||
$handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}')); |
||||
|
||||
$expected = <<<EOF |
||||
(function (c) {if (c && c.groupCollapsed) { |
||||
c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); |
||||
c.log("%c%cbar%c", "font-weight: normal", "background-color: green; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); |
||||
c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); |
||||
}})(console); |
||||
EOF; |
||||
|
||||
$this->assertEquals($expected, $this->generateScript()); |
||||
} |
||||
|
||||
public function testContext() |
||||
{ |
||||
$handler = new BrowserConsoleHandler(); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, 'test', array('foo' => 'bar'))); |
||||
|
||||
$expected = <<<EOF |
||||
(function (c) {if (c && c.groupCollapsed) { |
||||
c.groupCollapsed("%ctest", "font-weight: normal"); |
||||
c.log("%c%s", "font-weight: bold", "Context"); |
||||
c.log("%s: %o", "foo", "bar"); |
||||
c.groupEnd(); |
||||
}})(console); |
||||
EOF; |
||||
|
||||
$this->assertEquals($expected, $this->generateScript()); |
||||
} |
||||
|
||||
public function testConcurrentHandlers() |
||||
{ |
||||
$handler1 = new BrowserConsoleHandler(); |
||||
$handler1->setFormatter($this->getIdentityFormatter()); |
||||
|
||||
$handler2 = new BrowserConsoleHandler(); |
||||
$handler2->setFormatter($this->getIdentityFormatter()); |
||||
|
||||
$handler1->handle($this->getRecord(Logger::DEBUG, 'test1')); |
||||
$handler2->handle($this->getRecord(Logger::DEBUG, 'test2')); |
||||
$handler1->handle($this->getRecord(Logger::DEBUG, 'test3')); |
||||
$handler2->handle($this->getRecord(Logger::DEBUG, 'test4')); |
||||
|
||||
$expected = <<<EOF |
||||
(function (c) {if (c && c.groupCollapsed) { |
||||
c.log("%ctest1", "font-weight: normal"); |
||||
c.log("%ctest2", "font-weight: normal"); |
||||
c.log("%ctest3", "font-weight: normal"); |
||||
c.log("%ctest4", "font-weight: normal"); |
||||
}})(console); |
||||
EOF; |
||||
|
||||
$this->assertEquals($expected, $this->generateScript()); |
||||
} |
||||
} |
||||
@ -0,0 +1,149 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
class BufferHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\BufferHandler::__construct |
||||
* @covers Monolog\Handler\BufferHandler::handle |
||||
* @covers Monolog\Handler\BufferHandler::close |
||||
*/ |
||||
public function testHandleBuffers() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new BufferHandler($test); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
$this->assertFalse($test->hasInfoRecords()); |
||||
$handler->close(); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertTrue(count($test->getRecords()) === 2); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\BufferHandler::close |
||||
* @covers Monolog\Handler\BufferHandler::flush |
||||
*/ |
||||
public function testDestructPropagatesRecords() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new BufferHandler($test); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->__destruct(); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\BufferHandler::handle |
||||
*/ |
||||
public function testHandleBufferLimit() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new BufferHandler($test, 2); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$handler->close(); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\BufferHandler::handle |
||||
*/ |
||||
public function testHandleBufferLimitWithFlushOnOverflow() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new BufferHandler($test, 3, Logger::DEBUG, true, true); |
||||
|
||||
// send two records |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
$this->assertCount(0, $test->getRecords()); |
||||
|
||||
// overflow |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertCount(3, $test->getRecords()); |
||||
|
||||
// should buffer again |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertCount(3, $test->getRecords()); |
||||
|
||||
$handler->close(); |
||||
$this->assertCount(5, $test->getRecords()); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\BufferHandler::handle |
||||
*/ |
||||
public function testHandleLevel() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new BufferHandler($test, 0, Logger::INFO); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->close(); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\BufferHandler::flush |
||||
*/ |
||||
public function testFlush() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new BufferHandler($test, 0); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$handler->flush(); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertFalse($test->hasWarningRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\BufferHandler::handle |
||||
*/ |
||||
public function testHandleUsesProcessors() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new BufferHandler($test); |
||||
$handler->pushProcessor(function ($record) { |
||||
$record['extra']['foo'] = true; |
||||
|
||||
return $record; |
||||
}); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$handler->flush(); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$records = $test->getRecords(); |
||||
$this->assertTrue($records[0]['extra']['foo']); |
||||
} |
||||
} |
||||
@ -0,0 +1,141 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ChromePHPHandler |
||||
*/ |
||||
class ChromePHPHandlerTest extends TestCase |
||||
{ |
||||
protected function setUp() |
||||
{ |
||||
TestChromePHPHandler::reset(); |
||||
$_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; Chrome/1.0'; |
||||
} |
||||
|
||||
public function testHeaders() |
||||
{ |
||||
$handler = new TestChromePHPHandler(); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
|
||||
$expected = array( |
||||
'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( |
||||
'version' => ChromePHPHandler::VERSION, |
||||
'columns' => array('label', 'log', 'backtrace', 'type'), |
||||
'rows' => array( |
||||
'test', |
||||
'test', |
||||
), |
||||
'request_uri' => '', |
||||
)))) |
||||
); |
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders()); |
||||
} |
||||
|
||||
public function testHeadersOverflow() |
||||
{ |
||||
$handler = new TestChromePHPHandler(); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 150*1024))); |
||||
|
||||
// overflow chrome headers limit |
||||
$handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 100*1024))); |
||||
|
||||
$expected = array( |
||||
'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( |
||||
'version' => ChromePHPHandler::VERSION, |
||||
'columns' => array('label', 'log', 'backtrace', 'type'), |
||||
'rows' => array( |
||||
array( |
||||
'test', |
||||
'test', |
||||
'unknown', |
||||
'log', |
||||
), |
||||
array( |
||||
'test', |
||||
str_repeat('a', 150*1024), |
||||
'unknown', |
||||
'warn', |
||||
), |
||||
array( |
||||
'monolog', |
||||
'Incomplete logs, chrome header size limit reached', |
||||
'unknown', |
||||
'warn', |
||||
), |
||||
), |
||||
'request_uri' => '', |
||||
)))) |
||||
); |
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders()); |
||||
} |
||||
|
||||
public function testConcurrentHandlers() |
||||
{ |
||||
$handler = new TestChromePHPHandler(); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
|
||||
$handler2 = new TestChromePHPHandler(); |
||||
$handler2->setFormatter($this->getIdentityFormatter()); |
||||
$handler2->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler2->handle($this->getRecord(Logger::WARNING)); |
||||
|
||||
$expected = array( |
||||
'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( |
||||
'version' => ChromePHPHandler::VERSION, |
||||
'columns' => array('label', 'log', 'backtrace', 'type'), |
||||
'rows' => array( |
||||
'test', |
||||
'test', |
||||
'test', |
||||
'test', |
||||
), |
||||
'request_uri' => '', |
||||
)))) |
||||
); |
||||
|
||||
$this->assertEquals($expected, $handler2->getHeaders()); |
||||
} |
||||
} |
||||
|
||||
class TestChromePHPHandler extends ChromePHPHandler |
||||
{ |
||||
protected $headers = array(); |
||||
|
||||
public static function reset() |
||||
{ |
||||
self::$initialized = false; |
||||
self::$overflowed = false; |
||||
self::$sendHeaders = true; |
||||
self::$json['rows'] = array(); |
||||
} |
||||
|
||||
protected function sendHeader($header, $content) |
||||
{ |
||||
$this->headers[$header] = $content; |
||||
} |
||||
|
||||
public function getHeaders() |
||||
{ |
||||
return $this->headers; |
||||
} |
||||
} |
||||
@ -0,0 +1,41 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
class CouchDBHandlerTest extends TestCase |
||||
{ |
||||
public function testHandle() |
||||
{ |
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); |
||||
|
||||
$expected = array( |
||||
'message' => 'test', |
||||
'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), |
||||
'level' => Logger::WARNING, |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'test', |
||||
'datetime' => $record['datetime']->format('Y-m-d H:i:s'), |
||||
'extra' => array(), |
||||
); |
||||
|
||||
$handler = new CouchDBHandler(); |
||||
|
||||
try { |
||||
$handler->handle($record); |
||||
} catch (\RuntimeException $e) { |
||||
$this->markTestSkipped('Could not connect to couchdb server on http://localhost:5984'); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,52 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
class DoctrineCouchDBHandlerTest extends TestCase |
||||
{ |
||||
protected function setup() |
||||
{ |
||||
if (!class_exists('Doctrine\CouchDB\CouchDBClient')) { |
||||
$this->markTestSkipped('The "doctrine/couchdb" package is not installed'); |
||||
} |
||||
} |
||||
|
||||
public function testHandle() |
||||
{ |
||||
$client = $this->getMockBuilder('Doctrine\\CouchDB\\CouchDBClient') |
||||
->setMethods(array('postDocument')) |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); |
||||
|
||||
$expected = array( |
||||
'message' => 'test', |
||||
'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), |
||||
'level' => Logger::WARNING, |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'test', |
||||
'datetime' => $record['datetime']->format('Y-m-d H:i:s'), |
||||
'extra' => array(), |
||||
); |
||||
|
||||
$client->expects($this->once()) |
||||
->method('postDocument') |
||||
->with($expected); |
||||
|
||||
$handler = new DoctrineCouchDBHandler($client); |
||||
$handler->handle($record); |
||||
} |
||||
} |
||||
@ -0,0 +1,73 @@ |
||||
<?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\TestCase; |
||||
|
||||
class DynamoDbHandlerTest extends TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
if (!class_exists('Aws\DynamoDb\DynamoDbClient')) { |
||||
$this->markTestSkipped('aws/aws-sdk-php not installed'); |
||||
} |
||||
|
||||
$this->client = $this->getMockBuilder('Aws\DynamoDb\DynamoDbClient') |
||||
->setMethods(array('formatAttributes', '__call')) |
||||
->disableOriginalConstructor()->getMock(); |
||||
} |
||||
|
||||
public function testConstruct() |
||||
{ |
||||
$this->assertInstanceOf('Monolog\Handler\DynamoDbHandler', new DynamoDbHandler($this->client, 'foo')); |
||||
} |
||||
|
||||
public function testInterface() |
||||
{ |
||||
$this->assertInstanceOf('Monolog\Handler\HandlerInterface', new DynamoDbHandler($this->client, 'foo')); |
||||
} |
||||
|
||||
public function testGetFormatter() |
||||
{ |
||||
$handler = new DynamoDbHandler($this->client, 'foo'); |
||||
$this->assertInstanceOf('Monolog\Formatter\ScalarFormatter', $handler->getFormatter()); |
||||
} |
||||
|
||||
public function testHandle() |
||||
{ |
||||
$record = $this->getRecord(); |
||||
$formatter = $this->getMock('Monolog\Formatter\FormatterInterface'); |
||||
$formatted = array('foo' => 1, 'bar' => 2); |
||||
$handler = new DynamoDbHandler($this->client, 'foo'); |
||||
$handler->setFormatter($formatter); |
||||
|
||||
$formatter |
||||
->expects($this->once()) |
||||
->method('format') |
||||
->with($record) |
||||
->will($this->returnValue($formatted)); |
||||
$this->client |
||||
->expects($this->once()) |
||||
->method('formatAttributes') |
||||
->with($this->isType('array')) |
||||
->will($this->returnValue($formatted)); |
||||
$this->client |
||||
->expects($this->once()) |
||||
->method('__call') |
||||
->with('putItem', array(array( |
||||
'TableName' => 'foo', |
||||
'Item' => $formatted |
||||
))); |
||||
|
||||
$handler->handle($record); |
||||
} |
||||
} |
||||
@ -0,0 +1,239 @@ |
||||
<?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\Formatter\ElasticaFormatter; |
||||
use Monolog\Formatter\NormalizerFormatter; |
||||
use Monolog\TestCase; |
||||
use Monolog\Logger; |
||||
use Elastica\Client; |
||||
use Elastica\Request; |
||||
use Elastica\Response; |
||||
|
||||
class ElasticSearchHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @var Client mock |
||||
*/ |
||||
protected $client; |
||||
|
||||
/** |
||||
* @var array Default handler options |
||||
*/ |
||||
protected $options = array( |
||||
'index' => 'my_index', |
||||
'type' => 'doc_type', |
||||
); |
||||
|
||||
public function setUp() |
||||
{ |
||||
// Elastica lib required |
||||
if (!class_exists("Elastica\Client")) { |
||||
$this->markTestSkipped("ruflin/elastica not installed"); |
||||
} |
||||
|
||||
// base mock Elastica Client object |
||||
$this->client = $this->getMockBuilder('Elastica\Client') |
||||
->setMethods(array('addDocuments')) |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ElasticSearchHandler::write |
||||
* @covers Monolog\Handler\ElasticSearchHandler::handleBatch |
||||
* @covers Monolog\Handler\ElasticSearchHandler::bulkSend |
||||
* @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter |
||||
*/ |
||||
public function testHandle() |
||||
{ |
||||
// log message |
||||
$msg = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
// format expected result |
||||
$formatter = new ElasticaFormatter($this->options['index'], $this->options['type']); |
||||
$expected = array($formatter->format($msg)); |
||||
|
||||
// setup ES client mock |
||||
$this->client->expects($this->any()) |
||||
->method('addDocuments') |
||||
->with($expected); |
||||
|
||||
// perform tests |
||||
$handler = new ElasticSearchHandler($this->client, $this->options); |
||||
$handler->handle($msg); |
||||
$handler->handleBatch(array($msg)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ElasticSearchHandler::setFormatter |
||||
*/ |
||||
public function testSetFormatter() |
||||
{ |
||||
$handler = new ElasticSearchHandler($this->client); |
||||
$formatter = new ElasticaFormatter('index_new', 'type_new'); |
||||
$handler->setFormatter($formatter); |
||||
$this->assertInstanceOf('Monolog\Formatter\ElasticaFormatter', $handler->getFormatter()); |
||||
$this->assertEquals('index_new', $handler->getFormatter()->getIndex()); |
||||
$this->assertEquals('type_new', $handler->getFormatter()->getType()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ElasticSearchHandler::setFormatter |
||||
* @expectedException InvalidArgumentException |
||||
* @expectedExceptionMessage ElasticSearchHandler is only compatible with ElasticaFormatter |
||||
*/ |
||||
public function testSetFormatterInvalid() |
||||
{ |
||||
$handler = new ElasticSearchHandler($this->client); |
||||
$formatter = new NormalizerFormatter(); |
||||
$handler->setFormatter($formatter); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ElasticSearchHandler::__construct |
||||
* @covers Monolog\Handler\ElasticSearchHandler::getOptions |
||||
*/ |
||||
public function testOptions() |
||||
{ |
||||
$expected = array( |
||||
'index' => $this->options['index'], |
||||
'type' => $this->options['type'], |
||||
'ignore_error' => false, |
||||
); |
||||
$handler = new ElasticSearchHandler($this->client, $this->options); |
||||
$this->assertEquals($expected, $handler->getOptions()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ElasticSearchHandler::bulkSend |
||||
* @dataProvider providerTestConnectionErrors |
||||
*/ |
||||
public function testConnectionErrors($ignore, $expectedError) |
||||
{ |
||||
$clientOpts = array('host' => '127.0.0.1', 'port' => 1); |
||||
$client = new Client($clientOpts); |
||||
$handlerOpts = array('ignore_error' => $ignore); |
||||
$handler = new ElasticSearchHandler($client, $handlerOpts); |
||||
|
||||
if ($expectedError) { |
||||
$this->setExpectedException($expectedError[0], $expectedError[1]); |
||||
$handler->handle($this->getRecord()); |
||||
} else { |
||||
$this->assertFalse($handler->handle($this->getRecord())); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @return array |
||||
*/ |
||||
public function providerTestConnectionErrors() |
||||
{ |
||||
return array( |
||||
array(false, array('RuntimeException', 'Error sending messages to Elasticsearch')), |
||||
array(true, false), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Integration test using localhost Elastic Search server |
||||
* |
||||
* @covers Monolog\Handler\ElasticSearchHandler::__construct |
||||
* @covers Monolog\Handler\ElasticSearchHandler::handleBatch |
||||
* @covers Monolog\Handler\ElasticSearchHandler::bulkSend |
||||
* @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter |
||||
*/ |
||||
public function testHandleIntegration() |
||||
{ |
||||
$msg = array( |
||||
'level' => Logger::ERROR, |
||||
'level_name' => 'ERROR', |
||||
'channel' => 'meh', |
||||
'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), |
||||
'datetime' => new \DateTime("@0"), |
||||
'extra' => array(), |
||||
'message' => 'log', |
||||
); |
||||
|
||||
$expected = $msg; |
||||
$expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601); |
||||
$expected['context'] = array( |
||||
'class' => '[object] (stdClass: {})', |
||||
'foo' => 7, |
||||
0 => 'bar', |
||||
); |
||||
|
||||
$client = new Client(); |
||||
$handler = new ElasticSearchHandler($client, $this->options); |
||||
try { |
||||
$handler->handleBatch(array($msg)); |
||||
} catch (\RuntimeException $e) { |
||||
$this->markTestSkipped("Cannot connect to Elastic Search server on localhost"); |
||||
} |
||||
|
||||
// check document id from ES server response |
||||
$documentId = $this->getCreatedDocId($client->getLastResponse()); |
||||
$this->assertNotEmpty($documentId, 'No elastic document id received'); |
||||
|
||||
// retrieve document source from ES and validate |
||||
$document = $this->getDocSourceFromElastic( |
||||
$client, |
||||
$this->options['index'], |
||||
$this->options['type'], |
||||
$documentId |
||||
); |
||||
$this->assertEquals($expected, $document); |
||||
|
||||
// remove test index from ES |
||||
$client->request("/{$this->options['index']}", Request::DELETE); |
||||
} |
||||
|
||||
/** |
||||
* Return last created document id from ES response |
||||
* @param Response $response Elastica Response object |
||||
* @return string|null |
||||
*/ |
||||
protected function getCreatedDocId(Response $response) |
||||
{ |
||||
$data = $response->getData(); |
||||
if (!empty($data['items'][0]['create']['_id'])) { |
||||
return $data['items'][0]['create']['_id']; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Retrieve document by id from Elasticsearch |
||||
* @param Client $client Elastica client |
||||
* @param string $index |
||||
* @param string $type |
||||
* @param string $documentId |
||||
* @return array |
||||
*/ |
||||
protected function getDocSourceFromElastic(Client $client, $index, $type, $documentId) |
||||
{ |
||||
$resp = $client->request("/{$index}/{$type}/{$documentId}", Request::GET); |
||||
$data = $resp->getData(); |
||||
if (!empty($data['_source'])) { |
||||
return $data['_source']; |
||||
} |
||||
|
||||
return array(); |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@ |
||||
<?php |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
function error_log() |
||||
{ |
||||
$GLOBALS['error_log'] = func_get_args(); |
||||
} |
||||
|
||||
class ErrorLogHandlerTest extends TestCase |
||||
{ |
||||
|
||||
protected function setUp() |
||||
{ |
||||
$GLOBALS['error_log'] = array(); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ErrorLogHandler::__construct |
||||
* @expectedException InvalidArgumentException |
||||
* @expectedExceptionMessage The given message type "42" is not supported |
||||
*/ |
||||
public function testShouldNotAcceptAnInvalidTypeOnContructor() |
||||
{ |
||||
new ErrorLogHandler(42); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ErrorLogHandler::write |
||||
*/ |
||||
public function testShouldLogMessagesUsingErrorLogFuncion() |
||||
{ |
||||
$type = ErrorLogHandler::OPERATING_SYSTEM; |
||||
$handler = new ErrorLogHandler($type); |
||||
$handler->handle($this->getRecord(Logger::ERROR)); |
||||
|
||||
$this->assertStringMatchesFormat('[%s] test.ERROR: test [] []', $GLOBALS['error_log'][0]); |
||||
$this->assertSame($GLOBALS['error_log'][1], $type); |
||||
} |
||||
} |
||||
@ -0,0 +1,151 @@ |
||||
<?php |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\TestCase; |
||||
|
||||
class FilterHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\FilterHandler::isHandling |
||||
*/ |
||||
public function testIsHandling() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); |
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::INFO))); |
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::NOTICE))); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::WARNING))); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::ERROR))); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::CRITICAL))); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::ALERT))); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::EMERGENCY))); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FilterHandler::handle |
||||
* @covers Monolog\Handler\FilterHandler::setAcceptedLevels |
||||
* @covers Monolog\Handler\FilterHandler::isHandling |
||||
*/ |
||||
public function testHandleProcessOnlyNeededLevels() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE); |
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
|
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$handler->handle($this->getRecord(Logger::NOTICE)); |
||||
$this->assertTrue($test->hasNoticeRecords()); |
||||
|
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertFalse($test->hasWarningRecords()); |
||||
$handler->handle($this->getRecord(Logger::ERROR)); |
||||
$this->assertFalse($test->hasErrorRecords()); |
||||
$handler->handle($this->getRecord(Logger::CRITICAL)); |
||||
$this->assertFalse($test->hasCriticalRecords()); |
||||
$handler->handle($this->getRecord(Logger::ALERT)); |
||||
$this->assertFalse($test->hasAlertRecords()); |
||||
$handler->handle($this->getRecord(Logger::EMERGENCY)); |
||||
$this->assertFalse($test->hasEmergencyRecords()); |
||||
|
||||
$test = new TestHandler(); |
||||
$handler = new FilterHandler($test, array(Logger::INFO, Logger::ERROR)); |
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$handler->handle($this->getRecord(Logger::NOTICE)); |
||||
$this->assertFalse($test->hasNoticeRecords()); |
||||
$handler->handle($this->getRecord(Logger::ERROR)); |
||||
$this->assertTrue($test->hasErrorRecords()); |
||||
$handler->handle($this->getRecord(Logger::CRITICAL)); |
||||
$this->assertFalse($test->hasCriticalRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FilterHandler::setAcceptedLevels |
||||
* @covers Monolog\Handler\FilterHandler::getAcceptedLevels |
||||
*/ |
||||
public function testAcceptedLevelApi() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FilterHandler($test); |
||||
|
||||
$levels = array(Logger::INFO, Logger::ERROR); |
||||
$handler->setAcceptedLevels($levels); |
||||
$this->assertSame($levels, $handler->getAcceptedLevels()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FilterHandler::handle |
||||
*/ |
||||
public function testHandleUsesProcessors() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FilterHandler($test, Logger::DEBUG, Logger::EMERGENCY); |
||||
$handler->pushProcessor( |
||||
function ($record) { |
||||
$record['extra']['foo'] = true; |
||||
|
||||
return $record; |
||||
} |
||||
); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$records = $test->getRecords(); |
||||
$this->assertTrue($records[0]['extra']['foo']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FilterHandler::handle |
||||
*/ |
||||
public function testHandleRespectsBubble() |
||||
{ |
||||
$test = new TestHandler(); |
||||
|
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, false); |
||||
$this->assertTrue($handler->handle($this->getRecord(Logger::INFO))); |
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::WARNING))); |
||||
|
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, true); |
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::INFO))); |
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::WARNING))); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FilterHandler::handle |
||||
*/ |
||||
public function testHandleWithCallback() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FilterHandler( |
||||
function ($record, $handler) use ($test) { |
||||
return $test; |
||||
}, Logger::INFO, Logger::NOTICE, false |
||||
); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FilterHandler::handle |
||||
* @expectedException \RuntimeException |
||||
*/ |
||||
public function testHandleWithBadCallbackThrowsException() |
||||
{ |
||||
$handler = new FilterHandler( |
||||
function ($record, $handler) { |
||||
return 'foo'; |
||||
} |
||||
); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
} |
||||
} |
||||
@ -0,0 +1,189 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; |
||||
use Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy; |
||||
|
||||
class FingersCrossedHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::__construct |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
*/ |
||||
public function testHandleBuffers() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
$this->assertFalse($test->hasInfoRecords()); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertTrue(count($test->getRecords()) === 3); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
*/ |
||||
public function testHandleStopsBufferingAfterTrigger() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
* @covers Monolog\Handler\FingersCrossedHandler::reset |
||||
*/ |
||||
public function testHandleRestartBufferingAfterReset() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->reset(); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertFalse($test->hasInfoRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
*/ |
||||
public function testHandleRestartBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test, Logger::WARNING, 0, false, false); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertFalse($test->hasInfoRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
*/ |
||||
public function testHandleBufferLimit() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test, Logger::WARNING, 2); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
*/ |
||||
public function testHandleWithCallback() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler(function ($record, $handler) use ($test) { |
||||
return $test; |
||||
}); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
$this->assertFalse($test->hasInfoRecords()); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertTrue(count($test->getRecords()) === 3); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
* @expectedException RuntimeException |
||||
*/ |
||||
public function testHandleWithBadCallbackThrowsException() |
||||
{ |
||||
$handler = new FingersCrossedHandler(function ($record, $handler) { |
||||
return 'foo'; |
||||
}); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::isHandling |
||||
*/ |
||||
public function testIsHandlingAlways() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test, Logger::ERROR); |
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG))); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::__construct |
||||
* @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct |
||||
* @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated |
||||
*/ |
||||
public function testErrorLevelActivationStrategy() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING)); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$this->assertFalse($test->hasDebugRecords()); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct |
||||
* @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated |
||||
*/ |
||||
public function testChannelLevelActivationStrategy() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy(Logger::ERROR, array('othertest' => Logger::DEBUG))); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertFalse($test->hasWarningRecords()); |
||||
$record = $this->getRecord(Logger::DEBUG); |
||||
$record['channel'] = 'othertest'; |
||||
$handler->handle($record); |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle |
||||
*/ |
||||
public function testHandleUsesProcessors() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new FingersCrossedHandler($test, Logger::INFO); |
||||
$handler->pushProcessor(function ($record) { |
||||
$record['extra']['foo'] = true; |
||||
|
||||
return $record; |
||||
}); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$records = $test->getRecords(); |
||||
$this->assertTrue($records[0]['extra']['foo']); |
||||
} |
||||
} |
||||
@ -0,0 +1,96 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\FirePHPHandler |
||||
*/ |
||||
class FirePHPHandlerTest extends TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
TestFirePHPHandler::reset(); |
||||
$_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; FirePHP/1.0'; |
||||
} |
||||
|
||||
public function testHeaders() |
||||
{ |
||||
$handler = new TestFirePHPHandler; |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
|
||||
$expected = array( |
||||
'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2', |
||||
'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1', |
||||
'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3', |
||||
'X-Wf-1-1-1-1' => 'test', |
||||
'X-Wf-1-1-1-2' => 'test', |
||||
); |
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders()); |
||||
} |
||||
|
||||
public function testConcurrentHandlers() |
||||
{ |
||||
$handler = new TestFirePHPHandler; |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
|
||||
$handler2 = new TestFirePHPHandler; |
||||
$handler2->setFormatter($this->getIdentityFormatter()); |
||||
$handler2->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler2->handle($this->getRecord(Logger::WARNING)); |
||||
|
||||
$expected = array( |
||||
'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2', |
||||
'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1', |
||||
'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3', |
||||
'X-Wf-1-1-1-1' => 'test', |
||||
'X-Wf-1-1-1-2' => 'test', |
||||
); |
||||
|
||||
$expected2 = array( |
||||
'X-Wf-1-1-1-3' => 'test', |
||||
'X-Wf-1-1-1-4' => 'test', |
||||
); |
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders()); |
||||
$this->assertEquals($expected2, $handler2->getHeaders()); |
||||
} |
||||
} |
||||
|
||||
class TestFirePHPHandler extends FirePHPHandler |
||||
{ |
||||
protected $headers = array(); |
||||
|
||||
public static function reset() |
||||
{ |
||||
self::$initialized = false; |
||||
self::$sendHeaders = true; |
||||
self::$messageIndex = 1; |
||||
} |
||||
|
||||
protected function sendHeader($header, $content) |
||||
{ |
||||
$this->headers[$header] = $content; |
||||
} |
||||
|
||||
public function getHeaders() |
||||
{ |
||||
return $this->headers; |
||||
} |
||||
} |
||||
@ -0,0 +1,88 @@ |
||||
<?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\Formatter\FlowdockFormatter; |
||||
use Monolog\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @author Dominik Liebler <liebler.dominik@gmail.com> |
||||
* @see https://www.hipchat.com/docs/api |
||||
*/ |
||||
class FlowdockHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @var resource |
||||
*/ |
||||
private $res; |
||||
|
||||
/** |
||||
* @var FlowdockHandler |
||||
*/ |
||||
private $handler; |
||||
|
||||
public function setUp() |
||||
{ |
||||
if (!extension_loaded('openssl')) { |
||||
$this->markTestSkipped('This test requires openssl to run'); |
||||
} |
||||
} |
||||
|
||||
public function testWriteHeader() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/POST \/v1\/messages\/team_inbox\/.* HTTP\/1.1\\r\\nHost: api.flowdock.com\\r\\nContent-Type: application\/json\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); |
||||
|
||||
return $content; |
||||
} |
||||
|
||||
/** |
||||
* @depends testWriteHeader |
||||
*/ |
||||
public function testWriteContent($content) |
||||
{ |
||||
$this->assertRegexp('/"source":"test_source"/', $content); |
||||
$this->assertRegexp('/"from_address":"source@test\.com"/', $content); |
||||
} |
||||
|
||||
private function createHandler($token = 'myToken') |
||||
{ |
||||
$constructorArgs = array($token, Logger::DEBUG); |
||||
$this->res = fopen('php://memory', 'a'); |
||||
$this->handler = $this->getMock( |
||||
'\Monolog\Handler\FlowdockHandler', |
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'), |
||||
$constructorArgs |
||||
); |
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); |
||||
$reflectionProperty->setAccessible(true); |
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234'); |
||||
|
||||
$this->handler->expects($this->any()) |
||||
->method('fsockopen') |
||||
->will($this->returnValue($this->res)); |
||||
$this->handler->expects($this->any()) |
||||
->method('streamSetTimeout') |
||||
->will($this->returnValue(true)); |
||||
$this->handler->expects($this->any()) |
||||
->method('closeSocket') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$this->handler->setFormatter(new FlowdockFormatter('test_source', 'source@test.com')); |
||||
} |
||||
} |
||||
@ -0,0 +1,93 @@ |
||||
<?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 Gelf\Message; |
||||
use Monolog\TestCase; |
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\GelfMessageFormatter; |
||||
|
||||
class GelfHandlerLegacyTest extends TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
if (!class_exists('Gelf\MessagePublisher') || !class_exists('Gelf\Message')) { |
||||
$this->markTestSkipped("mlehner/gelf-php not installed"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\GelfHandler::__construct |
||||
*/ |
||||
public function testConstruct() |
||||
{ |
||||
$handler = new GelfHandler($this->getMessagePublisher()); |
||||
$this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler); |
||||
} |
||||
|
||||
protected function getHandler($messagePublisher) |
||||
{ |
||||
$handler = new GelfHandler($messagePublisher); |
||||
|
||||
return $handler; |
||||
} |
||||
|
||||
protected function getMessagePublisher() |
||||
{ |
||||
return new MockMessagePublisher('localhost'); |
||||
} |
||||
|
||||
public function testDebug() |
||||
{ |
||||
$messagePublisher = $this->getMessagePublisher(); |
||||
$handler = $this->getHandler($messagePublisher); |
||||
|
||||
$record = $this->getRecord(Logger::DEBUG, "A test debug message"); |
||||
$handler->handle($record); |
||||
|
||||
$this->assertEquals(7, $messagePublisher->lastMessage->getLevel()); |
||||
$this->assertEquals('test', $messagePublisher->lastMessage->getFacility()); |
||||
$this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage()); |
||||
$this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage()); |
||||
} |
||||
|
||||
public function testWarning() |
||||
{ |
||||
$messagePublisher = $this->getMessagePublisher(); |
||||
$handler = $this->getHandler($messagePublisher); |
||||
|
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message"); |
||||
$handler->handle($record); |
||||
|
||||
$this->assertEquals(4, $messagePublisher->lastMessage->getLevel()); |
||||
$this->assertEquals('test', $messagePublisher->lastMessage->getFacility()); |
||||
$this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage()); |
||||
$this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage()); |
||||
} |
||||
|
||||
public function testInjectedGelfMessageFormatter() |
||||
{ |
||||
$messagePublisher = $this->getMessagePublisher(); |
||||
$handler = $this->getHandler($messagePublisher); |
||||
|
||||
$handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX')); |
||||
|
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message"); |
||||
$record['extra']['blarg'] = 'yep'; |
||||
$record['context']['from'] = 'logger'; |
||||
$handler->handle($record); |
||||
|
||||
$this->assertEquals('mysystem', $messagePublisher->lastMessage->getHost()); |
||||
$this->assertArrayHasKey('_EXTblarg', $messagePublisher->lastMessage->toArray()); |
||||
$this->assertArrayHasKey('_CTXfrom', $messagePublisher->lastMessage->toArray()); |
||||
} |
||||
} |
||||
@ -0,0 +1,119 @@ |
||||
<?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 Gelf\Message; |
||||
use Monolog\TestCase; |
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\GelfMessageFormatter; |
||||
|
||||
class GelfHandlerTest extends TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
if (!class_exists('Gelf\Publisher') || !class_exists('Gelf\Message')) { |
||||
$this->markTestSkipped("graylog2/gelf-php not installed"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\GelfHandler::__construct |
||||
*/ |
||||
public function testConstruct() |
||||
{ |
||||
$handler = new GelfHandler($this->getMessagePublisher()); |
||||
$this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler); |
||||
} |
||||
|
||||
protected function getHandler($messagePublisher) |
||||
{ |
||||
$handler = new GelfHandler($messagePublisher); |
||||
|
||||
return $handler; |
||||
} |
||||
|
||||
protected function getMessagePublisher() |
||||
{ |
||||
return $this->getMock('Gelf\Publisher', array('publish'), array(), '', false); |
||||
} |
||||
|
||||
public function testDebug() |
||||
{ |
||||
$record = $this->getRecord(Logger::DEBUG, "A test debug message"); |
||||
$expectedMessage = new Message(); |
||||
$expectedMessage |
||||
->setLevel(7) |
||||
->setFacility("test") |
||||
->setShortMessage($record['message']) |
||||
->setTimestamp($record['datetime']) |
||||
; |
||||
|
||||
$messagePublisher = $this->getMessagePublisher(); |
||||
$messagePublisher->expects($this->once()) |
||||
->method('publish') |
||||
->with($expectedMessage); |
||||
|
||||
$handler = $this->getHandler($messagePublisher); |
||||
|
||||
$handler->handle($record); |
||||
|
||||
} |
||||
|
||||
public function testWarning() |
||||
{ |
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message"); |
||||
$expectedMessage = new Message(); |
||||
$expectedMessage |
||||
->setLevel(4) |
||||
->setFacility("test") |
||||
->setShortMessage($record['message']) |
||||
->setTimestamp($record['datetime']) |
||||
; |
||||
|
||||
$messagePublisher = $this->getMessagePublisher(); |
||||
$messagePublisher->expects($this->once()) |
||||
->method('publish') |
||||
->with($expectedMessage); |
||||
|
||||
$handler = $this->getHandler($messagePublisher); |
||||
|
||||
$handler->handle($record); |
||||
} |
||||
|
||||
public function testInjectedGelfMessageFormatter() |
||||
{ |
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message"); |
||||
$record['extra']['blarg'] = 'yep'; |
||||
$record['context']['from'] = 'logger'; |
||||
|
||||
$expectedMessage = new Message(); |
||||
$expectedMessage |
||||
->setLevel(4) |
||||
->setFacility("test") |
||||
->setHost("mysystem") |
||||
->setShortMessage($record['message']) |
||||
->setTimestamp($record['datetime']) |
||||
->setAdditional("EXTblarg", 'yep') |
||||
->setAdditional("CTXfrom", 'logger') |
||||
; |
||||
|
||||
$messagePublisher = $this->getMessagePublisher(); |
||||
$messagePublisher->expects($this->once()) |
||||
->method('publish') |
||||
->with($expectedMessage); |
||||
|
||||
$handler = $this->getHandler($messagePublisher); |
||||
$handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX')); |
||||
$handler->handle($record); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,89 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
class GroupHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\GroupHandler::__construct |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testConstructorOnlyTakesHandler() |
||||
{ |
||||
new GroupHandler(array(new TestHandler(), "foo")); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\GroupHandler::__construct |
||||
* @covers Monolog\Handler\GroupHandler::handle |
||||
*/ |
||||
public function testHandle() |
||||
{ |
||||
$testHandlers = array(new TestHandler(), new TestHandler()); |
||||
$handler = new GroupHandler($testHandlers); |
||||
$handler->handle($this->getRecord(Logger::DEBUG)); |
||||
$handler->handle($this->getRecord(Logger::INFO)); |
||||
foreach ($testHandlers as $test) { |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertTrue(count($test->getRecords()) === 2); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\GroupHandler::handleBatch |
||||
*/ |
||||
public function testHandleBatch() |
||||
{ |
||||
$testHandlers = array(new TestHandler(), new TestHandler()); |
||||
$handler = new GroupHandler($testHandlers); |
||||
$handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO))); |
||||
foreach ($testHandlers as $test) { |
||||
$this->assertTrue($test->hasDebugRecords()); |
||||
$this->assertTrue($test->hasInfoRecords()); |
||||
$this->assertTrue(count($test->getRecords()) === 2); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\GroupHandler::isHandling |
||||
*/ |
||||
public function testIsHandling() |
||||
{ |
||||
$testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING)); |
||||
$handler = new GroupHandler($testHandlers); |
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR))); |
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING))); |
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\GroupHandler::handle |
||||
*/ |
||||
public function testHandleUsesProcessors() |
||||
{ |
||||
$test = new TestHandler(); |
||||
$handler = new GroupHandler(array($test)); |
||||
$handler->pushProcessor(function ($record) { |
||||
$record['extra']['foo'] = true; |
||||
|
||||
return $record; |
||||
}); |
||||
$handler->handle($this->getRecord(Logger::WARNING)); |
||||
$this->assertTrue($test->hasWarningRecords()); |
||||
$records = $test->getRecords(); |
||||
$this->assertTrue($records[0]['extra']['foo']); |
||||
} |
||||
} |
||||
@ -0,0 +1,167 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @author Rafael Dohms <rafael@doh.ms> |
||||
* @see https://www.hipchat.com/docs/api |
||||
*/ |
||||
class HipChatHandlerTest extends TestCase |
||||
{ |
||||
|
||||
private $res; |
||||
private $handler; |
||||
|
||||
public function testWriteHeader() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/POST \/v1\/rooms\/message\?format=json&auth_token=.* HTTP\/1.1\\r\\nHost: api.hipchat.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); |
||||
|
||||
return $content; |
||||
} |
||||
|
||||
/** |
||||
* @depends testWriteHeader |
||||
*/ |
||||
public function testWriteContent($content) |
||||
{ |
||||
$this->assertRegexp('/from=Monolog&room_id=room1¬ify=0&message=test1&message_format=text&color=red$/', $content); |
||||
} |
||||
|
||||
public function testWriteWithComplexMessage() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider provideLevelColors |
||||
*/ |
||||
public function testWriteWithErrorLevelsAndColors($level, $expectedColor) |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/color='.$expectedColor.'/', $content); |
||||
} |
||||
|
||||
public function provideLevelColors() |
||||
{ |
||||
return array( |
||||
array(Logger::DEBUG, 'gray'), |
||||
array(Logger::INFO, 'green'), |
||||
array(Logger::WARNING, 'yellow'), |
||||
array(Logger::ERROR, 'red'), |
||||
array(Logger::CRITICAL, 'red'), |
||||
array(Logger::ALERT, 'red'), |
||||
array(Logger::EMERGENCY,'red'), |
||||
array(Logger::NOTICE, 'green'), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider provideBatchRecords |
||||
*/ |
||||
public function testHandleBatch($records, $expectedColor) |
||||
{ |
||||
$this->createHandler(); |
||||
|
||||
$this->handler->handleBatch($records); |
||||
|
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/color='.$expectedColor.'/', $content); |
||||
} |
||||
|
||||
public function provideBatchRecords() |
||||
{ |
||||
return array( |
||||
array( |
||||
array( |
||||
array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()), |
||||
array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), |
||||
array('level' => Logger::CRITICAL, 'message' => 'Everything is broken!', 'level_name' => 'critical', 'datetime' => new \DateTime()) |
||||
), |
||||
'red', |
||||
), |
||||
array( |
||||
array( |
||||
array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()), |
||||
array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), |
||||
), |
||||
'yellow', |
||||
), |
||||
array( |
||||
array( |
||||
array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()), |
||||
array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), |
||||
), |
||||
'green', |
||||
), |
||||
array( |
||||
array( |
||||
array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()), |
||||
), |
||||
'gray', |
||||
), |
||||
); |
||||
} |
||||
|
||||
private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false) |
||||
{ |
||||
$constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG); |
||||
$this->res = fopen('php://memory', 'a'); |
||||
$this->handler = $this->getMock( |
||||
'\Monolog\Handler\HipChatHandler', |
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'), |
||||
$constructorArgs |
||||
); |
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); |
||||
$reflectionProperty->setAccessible(true); |
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234'); |
||||
|
||||
$this->handler->expects($this->any()) |
||||
->method('fsockopen') |
||||
->will($this->returnValue($this->res)); |
||||
$this->handler->expects($this->any()) |
||||
->method('streamSetTimeout') |
||||
->will($this->returnValue(true)); |
||||
$this->handler->expects($this->any()) |
||||
->method('closeSocket') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$this->handler->setFormatter($this->getIdentityFormatter()); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testCreateWithTooLongName() |
||||
{ |
||||
$hipChatHandler = new \Monolog\Handler\HipChatHandler('token', 'room', 'SixteenCharsHere'); |
||||
} |
||||
} |
||||
@ -0,0 +1,84 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @author Robert Kaufmann III <rok3@rok3.me> |
||||
*/ |
||||
class LogEntriesHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @var resource |
||||
*/ |
||||
private $res; |
||||
|
||||
/** |
||||
* @var LogEntriesHandler |
||||
*/ |
||||
private $handler; |
||||
|
||||
public function testWriteContent() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); |
||||
|
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] test.CRITICAL: Critical write test/', $content); |
||||
} |
||||
|
||||
public function testWriteBatchContent() |
||||
{ |
||||
$records = array( |
||||
$this->getRecord(), |
||||
$this->getRecord(), |
||||
$this->getRecord() |
||||
); |
||||
$this->createHandler(); |
||||
$this->handler->handleBatch($records); |
||||
|
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] .* \[\] \[\]\n){3}/', $content); |
||||
} |
||||
|
||||
private function createHandler() |
||||
{ |
||||
$useSSL = extension_loaded('openssl'); |
||||
$args = array('testToken', $useSSL, Logger::DEBUG, true); |
||||
$this->res = fopen('php://memory', 'a'); |
||||
$this->handler = $this->getMock( |
||||
'\Monolog\Handler\LogEntriesHandler', |
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'), |
||||
$args |
||||
); |
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); |
||||
$reflectionProperty->setAccessible(true); |
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234'); |
||||
|
||||
$this->handler->expects($this->any()) |
||||
->method('fsockopen') |
||||
->will($this->returnValue($this->res)); |
||||
$this->handler->expects($this->any()) |
||||
->method('streamSetTimeout') |
||||
->will($this->returnValue(true)); |
||||
$this->handler->expects($this->any()) |
||||
->method('closeSocket') |
||||
->will($this->returnValue(true)); |
||||
} |
||||
} |
||||
@ -0,0 +1,75 @@ |
||||
<?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; |
||||
use Monolog\TestCase; |
||||
|
||||
class MailHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\MailHandler::handleBatch |
||||
*/ |
||||
public function testHandleBatch() |
||||
{ |
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); |
||||
$formatter->expects($this->once()) |
||||
->method('formatBatch'); // Each record is formatted |
||||
|
||||
$handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); |
||||
$handler->expects($this->once()) |
||||
->method('send'); |
||||
$handler->expects($this->never()) |
||||
->method('write'); // write is for individual records |
||||
|
||||
$handler->setFormatter($formatter); |
||||
|
||||
$handler->handleBatch($this->getMultipleRecords()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\MailHandler::handleBatch |
||||
*/ |
||||
public function testHandleBatchNotSendsMailIfMessagesAreBelowLevel() |
||||
{ |
||||
$records = array( |
||||
$this->getRecord(Logger::DEBUG, 'debug message 1'), |
||||
$this->getRecord(Logger::DEBUG, 'debug message 2'), |
||||
$this->getRecord(Logger::INFO, 'information'), |
||||
); |
||||
|
||||
$handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); |
||||
$handler->expects($this->never()) |
||||
->method('send'); |
||||
$handler->setLevel(Logger::ERROR); |
||||
|
||||
$handler->handleBatch($records); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\MailHandler::write |
||||
*/ |
||||
public function testHandle() |
||||
{ |
||||
$handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); |
||||
|
||||
$record = $this->getRecord(); |
||||
$records = array($record); |
||||
$records[0]['formatted'] = '['.$record['datetime']->format('Y-m-d H:i:s').'] test.WARNING: test [] []'."\n"; |
||||
|
||||
$handler->expects($this->once()) |
||||
->method('send') |
||||
->with($records[0]['formatted'], $records); |
||||
|
||||
$handler->handle($record); |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@ |
||||
<?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 Raven_Client; |
||||
|
||||
class MockRavenClient extends Raven_Client |
||||
{ |
||||
public function capture($data, $stack, $vars = null) |
||||
{ |
||||
$this->lastData = $data; |
||||
$this->lastStack = $stack; |
||||
} |
||||
|
||||
public $lastData; |
||||
public $lastStack; |
||||
} |
||||
@ -0,0 +1,63 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
class MongoDBHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testConstructorShouldThrowExceptionForInvalidMongo() |
||||
{ |
||||
new MongoDBHandler(new \stdClass(), 'DB', 'Collection'); |
||||
} |
||||
|
||||
public function testHandle() |
||||
{ |
||||
$mongo = $this->getMock('Mongo', array('selectCollection'), array(), '', false); |
||||
$collection = $this->getMock('stdClass', array('save')); |
||||
|
||||
$mongo->expects($this->once()) |
||||
->method('selectCollection') |
||||
->with('DB', 'Collection') |
||||
->will($this->returnValue($collection)); |
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); |
||||
|
||||
$expected = array( |
||||
'message' => 'test', |
||||
'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), |
||||
'level' => Logger::WARNING, |
||||
'level_name' => 'WARNING', |
||||
'channel' => 'test', |
||||
'datetime' => $record['datetime']->format('Y-m-d H:i:s'), |
||||
'extra' => array(), |
||||
); |
||||
|
||||
$collection->expects($this->once()) |
||||
->method('save') |
||||
->with($expected); |
||||
|
||||
$handler = new MongoDBHandler($mongo, 'DB', 'Collection'); |
||||
$handler->handle($record); |
||||
} |
||||
} |
||||
|
||||
if (!class_exists('Mongo')) { |
||||
class Mongo |
||||
{ |
||||
public function selectCollection() {} |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@ |
||||
<?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\TestCase; |
||||
|
||||
class NativeMailerHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testConstructorHeaderInjection() |
||||
{ |
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', "receiver@example.org\r\nFrom: faked@attacker.org"); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testSetterHeaderInjection() |
||||
{ |
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); |
||||
$mailer->addHeader("Content-Type: text/html\r\nFrom: faked@attacker.org"); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testSetterArrayHeaderInjection() |
||||
{ |
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); |
||||
$mailer->addHeader(array("Content-Type: text/html\r\nFrom: faked@attacker.org")); |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
use Psr\Log\LogLevel; |
||||
|
||||
class NewRelicHandlerTest extends TestCase |
||||
{ |
||||
public static $appname; |
||||
|
||||
public function setUp() |
||||
{ |
||||
$this::$appname = null; |
||||
} |
||||
|
||||
/** |
||||
* @expectedException Monolog\Handler\MissingExtensionException |
||||
*/ |
||||
public function testThehandlerThrowsAnExceptionIfTheNRExtensionIsNotLoaded() |
||||
{ |
||||
$handler = new StubNewRelicHandlerWithoutExtension(); |
||||
$handler->handle($this->getRecord(Logger::ERROR)); |
||||
} |
||||
|
||||
public function testThehandlerCanHandleTheRecord() |
||||
{ |
||||
$handler = new StubNewRelicHandler(); |
||||
$handler->handle($this->getRecord(Logger::ERROR)); |
||||
} |
||||
|
||||
public function testThehandlerCanAddParamsToTheNewRelicTrace() |
||||
{ |
||||
$handler = new StubNewRelicHandler(); |
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message', array('a' => 'b'))); |
||||
} |
||||
|
||||
public function testTheAppNameIsNullByDefault() |
||||
{ |
||||
$handler = new StubNewRelicHandler(); |
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message')); |
||||
|
||||
$this->assertEquals(null, $this::$appname); |
||||
} |
||||
|
||||
public function testTheAppNameCanBeInjectedFromtheConstructor() |
||||
{ |
||||
$handler = new StubNewRelicHandler(LogLevel::ALERT, false, 'myAppName'); |
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message')); |
||||
|
||||
$this->assertEquals('myAppName', $this::$appname); |
||||
} |
||||
|
||||
public function testTheAppNameCanBeOverriddenFromEachLog() |
||||
{ |
||||
$handler = new StubNewRelicHandler(LogLevel::ALERT, false, 'myAppName'); |
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message', array('appname' => 'logAppName'))); |
||||
|
||||
$this->assertEquals('logAppName', $this::$appname); |
||||
} |
||||
} |
||||
|
||||
class StubNewRelicHandlerWithoutExtension extends NewRelicHandler |
||||
{ |
||||
protected function isNewRelicEnabled() |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
class StubNewRelicHandler extends NewRelicHandler |
||||
{ |
||||
protected function isNewRelicEnabled() |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
function newrelic_notice_error() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
function newrelic_set_appname($appname) |
||||
{ |
||||
return NewRelicHandlerTest::$appname = $appname; |
||||
} |
||||
|
||||
function newrelic_add_custom_parameter() |
||||
{ |
||||
return true; |
||||
} |
||||
@ -0,0 +1,33 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\NullHandler::handle |
||||
*/ |
||||
class NullHandlerTest extends TestCase |
||||
{ |
||||
public function testHandle() |
||||
{ |
||||
$handler = new NullHandler(); |
||||
$this->assertTrue($handler->handle($this->getRecord())); |
||||
} |
||||
|
||||
public function testHandleLowerLevelRecord() |
||||
{ |
||||
$handler = new NullHandler(Logger::WARNING); |
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); |
||||
} |
||||
} |
||||
@ -0,0 +1,142 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Almost all examples (expected header, titles, messages) taken from |
||||
* https://www.pushover.net/api |
||||
* @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com> |
||||
* @see https://www.pushover.net/api |
||||
*/ |
||||
class PushoverHandlerTest extends TestCase |
||||
{ |
||||
|
||||
private $res; |
||||
private $handler; |
||||
|
||||
public function testWriteHeader() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/POST \/1\/messages.json HTTP\/1.1\\r\\nHost: api.pushover.net\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); |
||||
|
||||
return $content; |
||||
} |
||||
|
||||
/** |
||||
* @depends testWriteHeader |
||||
*/ |
||||
public function testWriteContent($content) |
||||
{ |
||||
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}$/', $content); |
||||
} |
||||
|
||||
public function testWriteWithComplexTitle() |
||||
{ |
||||
$this->createHandler('myToken', 'myUser', 'Backup finished - SQL1', Logger::EMERGENCY); |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content); |
||||
} |
||||
|
||||
public function testWriteWithComplexMessage() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); |
||||
} |
||||
|
||||
public function testWriteWithTooLongMessage() |
||||
{ |
||||
$message = str_pad('test', 520, 'a'); |
||||
$this->createHandler(); |
||||
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, $message)); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$expectedMessage = substr($message, 0, 505); |
||||
|
||||
$this->assertRegexp('/message=' . $expectedMessage . '&title/', $content); |
||||
} |
||||
|
||||
public function testWriteWithHighPriority() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=1$/', $content); |
||||
} |
||||
|
||||
public function testWriteWithEmergencyPriority() |
||||
{ |
||||
$this->createHandler(); |
||||
$this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); |
||||
} |
||||
|
||||
public function testWriteToMultipleUsers() |
||||
{ |
||||
$this->createHandler('myToken', array('userA', 'userB')); |
||||
$this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); |
||||
fseek($this->res, 0); |
||||
$content = fread($this->res, 1024); |
||||
|
||||
$this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content); |
||||
$this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); |
||||
} |
||||
|
||||
private function createHandler($token = 'myToken', $user = 'myUser', $title = 'Monolog') |
||||
{ |
||||
$constructorArgs = array($token, $user, $title); |
||||
$this->res = fopen('php://memory', 'a'); |
||||
$this->handler = $this->getMock( |
||||
'\Monolog\Handler\PushoverHandler', |
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'), |
||||
$constructorArgs |
||||
); |
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); |
||||
$reflectionProperty->setAccessible(true); |
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234'); |
||||
|
||||
$this->handler->expects($this->any()) |
||||
->method('fsockopen') |
||||
->will($this->returnValue($this->res)); |
||||
$this->handler->expects($this->any()) |
||||
->method('streamSetTimeout') |
||||
->will($this->returnValue(true)); |
||||
$this->handler->expects($this->any()) |
||||
->method('closeSocket') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$this->handler->setFormatter($this->getIdentityFormatter()); |
||||
} |
||||
} |
||||
@ -0,0 +1,150 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\LineFormatter; |
||||
|
||||
class RavenHandlerTest extends TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
if (!class_exists("Raven_Client")) { |
||||
$this->markTestSkipped("raven/raven not installed"); |
||||
} |
||||
|
||||
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) |
||||
{ |
||||
$handler = new RavenHandler($ravenClient); |
||||
|
||||
return $handler; |
||||
} |
||||
|
||||
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 = array(1, 2, 'foo'); |
||||
$record = $this->getRecord(Logger::INFO, "test", array('tags' => $tags)); |
||||
$handler->handle($record); |
||||
|
||||
$this->assertEquals($tags, $ravenClient->lastData['tags']); |
||||
} |
||||
|
||||
public function testException() |
||||
{ |
||||
$ravenClient = $this->getRavenClient(); |
||||
$handler = $this->getHandler($ravenClient); |
||||
|
||||
try { |
||||
$this->methodThatThrowsAnException(); |
||||
} catch (\Exception $e) { |
||||
$record = $this->getRecord(Logger::ERROR, $e->getMessage(), array('exception' => $e)); |
||||
$handler->handle($record); |
||||
} |
||||
|
||||
$this->assertEquals($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->getMock('Monolog\\Formatter\\FormatterInterface'); |
||||
$logFormatter->expects($this->once())->method('formatBatch'); |
||||
|
||||
$formatter = $this->getMock('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 = array( |
||||
$this->getRecord(Logger::DEBUG, 'debug message 1'), |
||||
$this->getRecord(Logger::DEBUG, 'debug message 2'), |
||||
$this->getRecord(Logger::INFO, 'information'), |
||||
); |
||||
|
||||
$handler = $this->getMock('Monolog\Handler\RavenHandler', null, array($this->getRavenClient())); |
||||
$handler->expects($this->never())->method('handle'); |
||||
$handler->setLevel(Logger::ERROR); |
||||
$handler->handleBatch($records); |
||||
} |
||||
|
||||
public function testGetSetBatchFormatter() |
||||
{ |
||||
$ravenClient = $this->getRavenClient(); |
||||
$handler = $this->getHandler($ravenClient); |
||||
|
||||
$handler->setBatchFormatter($formatter = new LineFormatter()); |
||||
$this->assertSame($formatter, $handler->getBatchFormatter()); |
||||
} |
||||
|
||||
private function methodThatThrowsAnException() |
||||
{ |
||||
throw new \Exception('This is an exception'); |
||||
} |
||||
} |
||||
@ -0,0 +1,71 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\LineFormatter; |
||||
|
||||
class RedisHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testConstructorShouldThrowExceptionForInvalidRedis() |
||||
{ |
||||
new RedisHandler(new \stdClass(), 'key'); |
||||
} |
||||
|
||||
public function testConstructorShouldWorkWithPredis() |
||||
{ |
||||
$redis = $this->getMock('Predis\Client'); |
||||
$this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); |
||||
} |
||||
|
||||
public function testConstructorShouldWorkWithRedis() |
||||
{ |
||||
$redis = $this->getMock('Redis'); |
||||
$this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); |
||||
} |
||||
|
||||
public function testPredisHandle() |
||||
{ |
||||
$redis = $this->getMock('Predis\Client', array('rpush')); |
||||
|
||||
// Predis\Client uses rpush |
||||
$redis->expects($this->once()) |
||||
->method('rpush') |
||||
->with('key', 'test'); |
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); |
||||
|
||||
$handler = new RedisHandler($redis, 'key'); |
||||
$handler->setFormatter(new LineFormatter("%message%")); |
||||
$handler->handle($record); |
||||
} |
||||
|
||||
public function testRedisHandle() |
||||
{ |
||||
$redis = $this->getMock('Redis', array('rpush')); |
||||
|
||||
// Redis uses rPush |
||||
$redis->expects($this->once()) |
||||
->method('rPush') |
||||
->with('key', 'test'); |
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); |
||||
|
||||
$handler = new RedisHandler($redis, 'key'); |
||||
$handler->setFormatter(new LineFormatter("%message%")); |
||||
$handler->handle($record); |
||||
} |
||||
} |
||||
@ -0,0 +1,99 @@ |
||||
<?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\TestCase; |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\RotatingFileHandler |
||||
*/ |
||||
class RotatingFileHandlerTest extends TestCase |
||||
{ |
||||
public function setUp() |
||||
{ |
||||
$dir = __DIR__.'/Fixtures'; |
||||
chmod($dir, 0777); |
||||
if (!is_writable($dir)) { |
||||
$this->markTestSkipped($dir.' must be writeable to test the RotatingFileHandler.'); |
||||
} |
||||
} |
||||
|
||||
public function testRotationCreatesNewFile() |
||||
{ |
||||
touch(__DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot'); |
||||
|
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot'); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord()); |
||||
|
||||
$log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; |
||||
$this->assertTrue(file_exists($log)); |
||||
$this->assertEquals('test', file_get_contents($log)); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider rotationTests |
||||
*/ |
||||
public function testRotation($createFile) |
||||
{ |
||||
touch($old1 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot'); |
||||
touch($old2 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 2).'.rot'); |
||||
touch($old3 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 3).'.rot'); |
||||
touch($old4 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 4).'.rot'); |
||||
|
||||
$log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; |
||||
|
||||
if ($createFile) { |
||||
touch($log); |
||||
} |
||||
|
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord()); |
||||
|
||||
$handler->close(); |
||||
|
||||
$this->assertTrue(file_exists($log)); |
||||
$this->assertTrue(file_exists($old1)); |
||||
$this->assertEquals($createFile, file_exists($old2)); |
||||
$this->assertEquals($createFile, file_exists($old3)); |
||||
$this->assertEquals($createFile, file_exists($old4)); |
||||
$this->assertEquals('test', file_get_contents($log)); |
||||
} |
||||
|
||||
public function rotationTests() |
||||
{ |
||||
return array( |
||||
'Rotation is triggered when the file of the current day is not present' |
||||
=> array(true), |
||||
'Rotation is not triggered when the file is already present' |
||||
=> array(false), |
||||
); |
||||
} |
||||
|
||||
public function testReuseCurrentFile() |
||||
{ |
||||
$log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; |
||||
file_put_contents($log, "foo"); |
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot'); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord()); |
||||
$this->assertEquals('footest', file_get_contents($log)); |
||||
} |
||||
|
||||
public function tearDown() |
||||
{ |
||||
foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) { |
||||
unlink($file); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,283 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @author Pablo de Leon Belloc <pablolb@gmail.com> |
||||
*/ |
||||
class SocketHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @var Monolog\Handler\SocketHandler |
||||
*/ |
||||
private $handler; |
||||
|
||||
/** |
||||
* @var resource |
||||
*/ |
||||
private $res; |
||||
|
||||
/** |
||||
* @expectedException UnexpectedValueException |
||||
*/ |
||||
public function testInvalidHostname() |
||||
{ |
||||
$this->createHandler('garbage://here'); |
||||
$this->writeRecord('data'); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException \InvalidArgumentException |
||||
*/ |
||||
public function testBadConnectionTimeout() |
||||
{ |
||||
$this->createHandler('localhost:1234'); |
||||
$this->handler->setConnectionTimeout(-1); |
||||
} |
||||
|
||||
public function testSetConnectionTimeout() |
||||
{ |
||||
$this->createHandler('localhost:1234'); |
||||
$this->handler->setConnectionTimeout(10.1); |
||||
$this->assertEquals(10.1, $this->handler->getConnectionTimeout()); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException \InvalidArgumentException |
||||
*/ |
||||
public function testBadTimeout() |
||||
{ |
||||
$this->createHandler('localhost:1234'); |
||||
$this->handler->setTimeout(-1); |
||||
} |
||||
|
||||
public function testSetTimeout() |
||||
{ |
||||
$this->createHandler('localhost:1234'); |
||||
$this->handler->setTimeout(10.25); |
||||
$this->assertEquals(10.25, $this->handler->getTimeout()); |
||||
} |
||||
|
||||
public function testSetConnectionString() |
||||
{ |
||||
$this->createHandler('tcp://localhost:9090'); |
||||
$this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString()); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException UnexpectedValueException |
||||
*/ |
||||
public function testExceptionIsThrownOnFsockopenError() |
||||
{ |
||||
$this->setMockHandler(array('fsockopen')); |
||||
$this->handler->expects($this->once()) |
||||
->method('fsockopen') |
||||
->will($this->returnValue(false)); |
||||
$this->writeRecord('Hello world'); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException UnexpectedValueException |
||||
*/ |
||||
public function testExceptionIsThrownOnPfsockopenError() |
||||
{ |
||||
$this->setMockHandler(array('pfsockopen')); |
||||
$this->handler->expects($this->once()) |
||||
->method('pfsockopen') |
||||
->will($this->returnValue(false)); |
||||
$this->handler->setPersistent(true); |
||||
$this->writeRecord('Hello world'); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException UnexpectedValueException |
||||
*/ |
||||
public function testExceptionIsThrownIfCannotSetTimeout() |
||||
{ |
||||
$this->setMockHandler(array('streamSetTimeout')); |
||||
$this->handler->expects($this->once()) |
||||
->method('streamSetTimeout') |
||||
->will($this->returnValue(false)); |
||||
$this->writeRecord('Hello world'); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException RuntimeException |
||||
*/ |
||||
public function testWriteFailsOnIfFwriteReturnsFalse() |
||||
{ |
||||
$this->setMockHandler(array('fwrite')); |
||||
|
||||
$callback = function ($arg) { |
||||
$map = array( |
||||
'Hello world' => 6, |
||||
'world' => false, |
||||
); |
||||
|
||||
return $map[$arg]; |
||||
}; |
||||
|
||||
$this->handler->expects($this->exactly(2)) |
||||
->method('fwrite') |
||||
->will($this->returnCallback($callback)); |
||||
|
||||
$this->writeRecord('Hello world'); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException RuntimeException |
||||
*/ |
||||
public function testWriteFailsIfStreamTimesOut() |
||||
{ |
||||
$this->setMockHandler(array('fwrite', 'streamGetMetadata')); |
||||
|
||||
$callback = function ($arg) { |
||||
$map = array( |
||||
'Hello world' => 6, |
||||
'world' => 5, |
||||
); |
||||
|
||||
return $map[$arg]; |
||||
}; |
||||
|
||||
$this->handler->expects($this->exactly(1)) |
||||
->method('fwrite') |
||||
->will($this->returnCallback($callback)); |
||||
$this->handler->expects($this->exactly(1)) |
||||
->method('streamGetMetadata') |
||||
->will($this->returnValue(array('timed_out' => true))); |
||||
|
||||
$this->writeRecord('Hello world'); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException RuntimeException |
||||
*/ |
||||
public function testWriteFailsOnIncompleteWrite() |
||||
{ |
||||
$this->setMockHandler(array('fwrite', 'streamGetMetadata')); |
||||
|
||||
$res = $this->res; |
||||
$callback = function ($string) use ($res) { |
||||
fclose($res); |
||||
|
||||
return strlen('Hello'); |
||||
}; |
||||
|
||||
$this->handler->expects($this->exactly(1)) |
||||
->method('fwrite') |
||||
->will($this->returnCallback($callback)); |
||||
$this->handler->expects($this->exactly(1)) |
||||
->method('streamGetMetadata') |
||||
->will($this->returnValue(array('timed_out' => false))); |
||||
|
||||
$this->writeRecord('Hello world'); |
||||
} |
||||
|
||||
public function testWriteWithMemoryFile() |
||||
{ |
||||
$this->setMockHandler(); |
||||
$this->writeRecord('test1'); |
||||
$this->writeRecord('test2'); |
||||
$this->writeRecord('test3'); |
||||
fseek($this->res, 0); |
||||
$this->assertEquals('test1test2test3', fread($this->res, 1024)); |
||||
} |
||||
|
||||
public function testWriteWithMock() |
||||
{ |
||||
$this->setMockHandler(array('fwrite')); |
||||
|
||||
$callback = function ($arg) { |
||||
$map = array( |
||||
'Hello world' => 6, |
||||
'world' => 5, |
||||
); |
||||
|
||||
return $map[$arg]; |
||||
}; |
||||
|
||||
$this->handler->expects($this->exactly(2)) |
||||
->method('fwrite') |
||||
->will($this->returnCallback($callback)); |
||||
|
||||
$this->writeRecord('Hello world'); |
||||
} |
||||
|
||||
public function testClose() |
||||
{ |
||||
$this->setMockHandler(); |
||||
$this->writeRecord('Hello world'); |
||||
$this->assertInternalType('resource', $this->res); |
||||
$this->handler->close(); |
||||
$this->assertFalse(is_resource($this->res), "Expected resource to be closed after closing handler"); |
||||
} |
||||
|
||||
public function testCloseDoesNotClosePersistentSocket() |
||||
{ |
||||
$this->setMockHandler(); |
||||
$this->handler->setPersistent(true); |
||||
$this->writeRecord('Hello world'); |
||||
$this->assertTrue(is_resource($this->res)); |
||||
$this->handler->close(); |
||||
$this->assertTrue(is_resource($this->res)); |
||||
} |
||||
|
||||
private function createHandler($connectionString) |
||||
{ |
||||
$this->handler = new SocketHandler($connectionString); |
||||
$this->handler->setFormatter($this->getIdentityFormatter()); |
||||
} |
||||
|
||||
private function writeRecord($string) |
||||
{ |
||||
$this->handler->handle($this->getRecord(Logger::WARNING, $string)); |
||||
} |
||||
|
||||
private function setMockHandler(array $methods = array()) |
||||
{ |
||||
$this->res = fopen('php://memory', 'a'); |
||||
|
||||
$defaultMethods = array('fsockopen', 'pfsockopen', 'streamSetTimeout'); |
||||
$newMethods = array_diff($methods, $defaultMethods); |
||||
|
||||
$finalMethods = array_merge($defaultMethods, $newMethods); |
||||
|
||||
$this->handler = $this->getMock( |
||||
'\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234') |
||||
); |
||||
|
||||
if (!in_array('fsockopen', $methods)) { |
||||
$this->handler->expects($this->any()) |
||||
->method('fsockopen') |
||||
->will($this->returnValue($this->res)); |
||||
} |
||||
|
||||
if (!in_array('pfsockopen', $methods)) { |
||||
$this->handler->expects($this->any()) |
||||
->method('pfsockopen') |
||||
->will($this->returnValue($this->res)); |
||||
} |
||||
|
||||
if (!in_array('streamSetTimeout', $methods)) { |
||||
$this->handler->expects($this->any()) |
||||
->method('streamSetTimeout') |
||||
->will($this->returnValue(true)); |
||||
} |
||||
|
||||
$this->handler->setFormatter($this->getIdentityFormatter()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,88 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
class StreamHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\StreamHandler::__construct |
||||
* @covers Monolog\Handler\StreamHandler::write |
||||
*/ |
||||
public function testWrite() |
||||
{ |
||||
$handle = fopen('php://memory', 'a+'); |
||||
$handler = new StreamHandler($handle); |
||||
$handler->setFormatter($this->getIdentityFormatter()); |
||||
$handler->handle($this->getRecord(Logger::WARNING, 'test')); |
||||
$handler->handle($this->getRecord(Logger::WARNING, 'test2')); |
||||
$handler->handle($this->getRecord(Logger::WARNING, 'test3')); |
||||
fseek($handle, 0); |
||||
$this->assertEquals('testtest2test3', fread($handle, 100)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\StreamHandler::close |
||||
*/ |
||||
public function testClose() |
||||
{ |
||||
$handle = fopen('php://memory', 'a+'); |
||||
$handler = new StreamHandler($handle); |
||||
$this->assertTrue(is_resource($handle)); |
||||
$handler->close(); |
||||
$this->assertFalse(is_resource($handle)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\StreamHandler::write |
||||
*/ |
||||
public function testWriteCreatesTheStreamResource() |
||||
{ |
||||
$handler = new StreamHandler('php://memory'); |
||||
$handler->handle($this->getRecord()); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException LogicException |
||||
* @covers Monolog\Handler\StreamHandler::__construct |
||||
* @covers Monolog\Handler\StreamHandler::write |
||||
*/ |
||||
public function testWriteMissingResource() |
||||
{ |
||||
$handler = new StreamHandler(null); |
||||
$handler->handle($this->getRecord()); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException UnexpectedValueException |
||||
* @covers Monolog\Handler\StreamHandler::__construct |
||||
* @covers Monolog\Handler\StreamHandler::write |
||||
*/ |
||||
public function testWriteInvalidResource() |
||||
{ |
||||
$handler = new StreamHandler('bogus://url'); |
||||
$handler->handle($this->getRecord()); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException UnexpectedValueException |
||||
* @covers Monolog\Handler\StreamHandler::__construct |
||||
* @covers Monolog\Handler\StreamHandler::write |
||||
*/ |
||||
public function testWriteNonExistingResource() |
||||
{ |
||||
$handler = new StreamHandler('/foo/bar/baz/'.rand(0, 10000)); |
||||
$handler->handle($this->getRecord()); |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@ |
||||
<?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; |
||||
|
||||
class SyslogHandlerTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Handler\SyslogHandler::__construct |
||||
*/ |
||||
public function testConstruct() |
||||
{ |
||||
$handler = new SyslogHandler('test'); |
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); |
||||
|
||||
$handler = new SyslogHandler('test', LOG_USER); |
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); |
||||
|
||||
$handler = new SyslogHandler('test', 'user'); |
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); |
||||
|
||||
$handler = new SyslogHandler('test', LOG_USER, Logger::DEBUG, true, LOG_PERROR); |
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\SyslogHandler::__construct |
||||
*/ |
||||
public function testConstructInvalidFacility() |
||||
{ |
||||
$this->setExpectedException('UnexpectedValueException'); |
||||
$handler = new SyslogHandler('test', 'unknown'); |
||||
} |
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
<?php |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
class SyslogUdpHandlerTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @expectedException UnexpectedValueException |
||||
*/ |
||||
public function testWeValidateFacilities() |
||||
{ |
||||
$handler = new SyslogUdpHandler("ip", null, "invalidFacility"); |
||||
} |
||||
|
||||
public function testWeSplitIntoLines() |
||||
{ |
||||
$handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv"); |
||||
$handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter()); |
||||
|
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('write'), array('lol', 'lol')); |
||||
$socket->expects($this->at(0)) |
||||
->method('write') |
||||
->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">: "); |
||||
$socket->expects($this->at(1)) |
||||
->method('write') |
||||
->with("hej", "<".(LOG_AUTHPRIV + LOG_WARNING).">: "); |
||||
|
||||
$handler->setSocket($socket); |
||||
|
||||
$handler->handle($this->getRecordWithMessage("hej\nlol")); |
||||
} |
||||
|
||||
protected function getRecordWithMessage($msg) |
||||
{ |
||||
return array('message' => $msg, 'level' => \Monolog\Logger::WARNING, 'context' => null, 'extra' => array(), 'channel' => 'lol'); |
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@ |
||||
<?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\TestCase; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\TestHandler |
||||
*/ |
||||
class TestHandlerTest extends TestCase |
||||
{ |
||||
/** |
||||
* @dataProvider methodProvider |
||||
*/ |
||||
public function testHandler($method, $level) |
||||
{ |
||||
$handler = new TestHandler; |
||||
$record = $this->getRecord($level, 'test'.$method); |
||||
$this->assertFalse($handler->{'has'.$method}($record)); |
||||
$this->assertFalse($handler->{'has'.$method.'Records'}()); |
||||
$handler->handle($record); |
||||
|
||||
$this->assertFalse($handler->{'has'.$method}('bar')); |
||||
$this->assertTrue($handler->{'has'.$method}($record)); |
||||
$this->assertTrue($handler->{'has'.$method}('test'.$method)); |
||||
$this->assertTrue($handler->{'has'.$method.'Records'}()); |
||||
|
||||
$records = $handler->getRecords(); |
||||
unset($records[0]['formatted']); |
||||
$this->assertEquals(array($record), $records); |
||||
} |
||||
|
||||
public function methodProvider() |
||||
{ |
||||
return array( |
||||
array('Emergency', Logger::EMERGENCY), |
||||
array('Alert' , Logger::ALERT), |
||||
array('Critical' , Logger::CRITICAL), |
||||
array('Error' , Logger::ERROR), |
||||
array('Warning' , Logger::WARNING), |
||||
array('Info' , Logger::INFO), |
||||
array('Notice' , Logger::NOTICE), |
||||
array('Debug' , Logger::DEBUG), |
||||
); |
||||
} |
||||
} |
||||
@ -0,0 +1,45 @@ |
||||
<?php |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\TestCase; |
||||
|
||||
class UdpSocketTest extends TestCase |
||||
{ |
||||
public function testWeDoNotSplitShortMessages() |
||||
{ |
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol')); |
||||
|
||||
$socket->expects($this->at(0)) |
||||
->method('send') |
||||
->with("HEADER: The quick brown fox jumps over the lazy dog"); |
||||
|
||||
$socket->write("The quick brown fox jumps over the lazy dog", "HEADER: "); |
||||
} |
||||
|
||||
public function testWeSplitLongMessages() |
||||
{ |
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol')); |
||||
|
||||
$socket->expects($this->at(1)) |
||||
->method('send') |
||||
->with("The quick brown fox jumps over the lazy dog"); |
||||
|
||||
$aStringOfLength2048 = str_repeat("derp", 2048/4); |
||||
|
||||
$socket->write($aStringOfLength2048."The quick brown fox jumps over the lazy dog"); |
||||
} |
||||
|
||||
public function testAllSplitMessagesHasAHeader() |
||||
{ |
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol')); |
||||
|
||||
$socket->expects($this->exactly(5)) |
||||
->method('send') |
||||
->with($this->stringStartsWith("HEADER")); |
||||
|
||||
$aStringOfLength8192 = str_repeat("derp", 2048); |
||||
|
||||
$socket->write($aStringOfLength8192, "HEADER"); |
||||
} |
||||
} |
||||
@ -0,0 +1,69 @@ |
||||
<?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\TestCase; |
||||
|
||||
class ZendMonitorHandlerTest extends TestCase |
||||
{ |
||||
protected $zendMonitorHandler; |
||||
|
||||
public function setUp() |
||||
{ |
||||
if (!function_exists('zend_monitor_custom_event')) { |
||||
$this->markTestSkipped('ZendServer is not installed'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ZendMonitorHandler::write |
||||
*/ |
||||
public function testWrite() |
||||
{ |
||||
$record = $this->getRecord(); |
||||
$formatterResult = array( |
||||
'message' => $record['message'] |
||||
); |
||||
|
||||
$zendMonitor = $this->getMockBuilder('Monolog\Handler\ZendMonitorHandler') |
||||
->setMethods(array('writeZendMonitorCustomEvent', 'getDefaultFormatter')) |
||||
->getMock(); |
||||
|
||||
$formatterMock = $this->getMockBuilder('Monolog\Formatter\NormalizerFormatter') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
|
||||
$formatterMock->expects($this->once()) |
||||
->method('format') |
||||
->will($this->returnValue($formatterResult)); |
||||
|
||||
$zendMonitor->expects($this->once()) |
||||
->method('getDefaultFormatter') |
||||
->will($this->returnValue($formatterMock)); |
||||
|
||||
$levelMap = $zendMonitor->getLevelMap(); |
||||
|
||||
$zendMonitor->expects($this->once()) |
||||
->method('writeZendMonitorCustomEvent') |
||||
->with($levelMap[$record['level']], $record['message'], $formatterResult); |
||||
|
||||
$zendMonitor->handle($record); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Handler\ZendMonitorHandler::getDefaultFormatter |
||||
*/ |
||||
public function testGetDefaultFormatterReturnsNormalizerFormatter() |
||||
{ |
||||
$zendMonitor = new ZendMonitorHandler(); |
||||
$this->assertInstanceOf('Monolog\Formatter\NormalizerFormatter', $zendMonitor->getDefaultFormatter()); |
||||
} |
||||
} |
||||
@ -0,0 +1,409 @@ |
||||
<?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 Monolog\Processor\WebProcessor; |
||||
use Monolog\Handler\TestHandler; |
||||
|
||||
class LoggerTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @covers Monolog\Logger::getName |
||||
*/ |
||||
public function testGetName() |
||||
{ |
||||
$logger = new Logger('foo'); |
||||
$this->assertEquals('foo', $logger->getName()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::getLevelName |
||||
*/ |
||||
public function testGetLevelName() |
||||
{ |
||||
$this->assertEquals('ERROR', Logger::getLevelName(Logger::ERROR)); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::getLevelName |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testGetLevelNameThrows() |
||||
{ |
||||
Logger::getLevelName(5); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::__construct |
||||
*/ |
||||
public function testChannel() |
||||
{ |
||||
$logger = new Logger('foo'); |
||||
$handler = new TestHandler; |
||||
$logger->pushHandler($handler); |
||||
$logger->addWarning('test'); |
||||
list($record) = $handler->getRecords(); |
||||
$this->assertEquals('foo', $record['channel']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testLog() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
|
||||
$handler = $this->getMock('Monolog\Handler\NullHandler', array('handle')); |
||||
$handler->expects($this->once()) |
||||
->method('handle'); |
||||
$logger->pushHandler($handler); |
||||
|
||||
$this->assertTrue($logger->addWarning('test')); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testLogNotHandled() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
|
||||
$handler = $this->getMock('Monolog\Handler\NullHandler', array('handle'), array(Logger::ERROR)); |
||||
$handler->expects($this->never()) |
||||
->method('handle'); |
||||
$logger->pushHandler($handler); |
||||
|
||||
$this->assertFalse($logger->addWarning('test')); |
||||
} |
||||
|
||||
public function testHandlersInCtor() |
||||
{ |
||||
$handler1 = new TestHandler; |
||||
$handler2 = new TestHandler; |
||||
$logger = new Logger(__METHOD__, array($handler1, $handler2)); |
||||
|
||||
$this->assertEquals($handler1, $logger->popHandler()); |
||||
$this->assertEquals($handler2, $logger->popHandler()); |
||||
} |
||||
|
||||
public function testProcessorsInCtor() |
||||
{ |
||||
$processor1 = new WebProcessor; |
||||
$processor2 = new WebProcessor; |
||||
$logger = new Logger(__METHOD__, array(), array($processor1, $processor2)); |
||||
|
||||
$this->assertEquals($processor1, $logger->popProcessor()); |
||||
$this->assertEquals($processor2, $logger->popProcessor()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::pushHandler |
||||
* @covers Monolog\Logger::popHandler |
||||
* @expectedException LogicException |
||||
*/ |
||||
public function testPushPopHandler() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
$handler1 = new TestHandler; |
||||
$handler2 = new TestHandler; |
||||
|
||||
$logger->pushHandler($handler1); |
||||
$logger->pushHandler($handler2); |
||||
|
||||
$this->assertEquals($handler2, $logger->popHandler()); |
||||
$this->assertEquals($handler1, $logger->popHandler()); |
||||
$logger->popHandler(); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::pushProcessor |
||||
* @covers Monolog\Logger::popProcessor |
||||
* @expectedException LogicException |
||||
*/ |
||||
public function testPushPopProcessor() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
$processor1 = new WebProcessor; |
||||
$processor2 = new WebProcessor; |
||||
|
||||
$logger->pushProcessor($processor1); |
||||
$logger->pushProcessor($processor2); |
||||
|
||||
$this->assertEquals($processor2, $logger->popProcessor()); |
||||
$this->assertEquals($processor1, $logger->popProcessor()); |
||||
$logger->popProcessor(); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::pushProcessor |
||||
* @expectedException InvalidArgumentException |
||||
*/ |
||||
public function testPushProcessorWithNonCallable() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
|
||||
$logger->pushProcessor(new \stdClass()); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testProcessorsAreExecuted() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
$handler = new TestHandler; |
||||
$logger->pushHandler($handler); |
||||
$logger->pushProcessor(function ($record) { |
||||
$record['extra']['win'] = true; |
||||
|
||||
return $record; |
||||
}); |
||||
$logger->addError('test'); |
||||
list($record) = $handler->getRecords(); |
||||
$this->assertTrue($record['extra']['win']); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testProcessorsAreCalledOnlyOnce() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
$handler = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler->expects($this->any()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$handler->expects($this->any()) |
||||
->method('handle') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$logger->pushHandler($handler); |
||||
|
||||
$processor = $this->getMockBuilder('Monolog\Processor\WebProcessor') |
||||
->disableOriginalConstructor() |
||||
->setMethods(array('__invoke')) |
||||
->getMock() |
||||
; |
||||
$processor->expects($this->once()) |
||||
->method('__invoke') |
||||
->will($this->returnArgument(0)) |
||||
; |
||||
$logger->pushProcessor($processor); |
||||
|
||||
$logger->addError('test'); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testProcessorsNotCalledWhenNotHandled() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
$handler = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler->expects($this->once()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
$logger->pushHandler($handler); |
||||
$that = $this; |
||||
$logger->pushProcessor(function ($record) use ($that) { |
||||
$that->fail('The processor should not be called'); |
||||
}); |
||||
$logger->addAlert('test'); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testHandlersNotCalledBeforeFirstHandling() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler1->expects($this->never()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
$handler1->expects($this->once()) |
||||
->method('handle') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
$logger->pushHandler($handler1); |
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler2->expects($this->once()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$handler2->expects($this->once()) |
||||
->method('handle') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
$logger->pushHandler($handler2); |
||||
|
||||
$handler3 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler3->expects($this->once()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
$handler3->expects($this->never()) |
||||
->method('handle') |
||||
; |
||||
$logger->pushHandler($handler3); |
||||
|
||||
$logger->debug('test'); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testBubblingWhenTheHandlerReturnsFalse() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler1->expects($this->any()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$handler1->expects($this->once()) |
||||
->method('handle') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
$logger->pushHandler($handler1); |
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler2->expects($this->any()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$handler2->expects($this->once()) |
||||
->method('handle') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
$logger->pushHandler($handler2); |
||||
|
||||
$logger->debug('test'); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::addRecord |
||||
*/ |
||||
public function testNotBubblingWhenTheHandlerReturnsTrue() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler1->expects($this->any()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$handler1->expects($this->never()) |
||||
->method('handle') |
||||
; |
||||
$logger->pushHandler($handler1); |
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler2->expects($this->any()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$handler2->expects($this->once()) |
||||
->method('handle') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
$logger->pushHandler($handler2); |
||||
|
||||
$logger->debug('test'); |
||||
} |
||||
|
||||
/** |
||||
* @covers Monolog\Logger::isHandling |
||||
*/ |
||||
public function testIsHandling() |
||||
{ |
||||
$logger = new Logger(__METHOD__); |
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler1->expects($this->any()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(false)) |
||||
; |
||||
|
||||
$logger->pushHandler($handler1); |
||||
$this->assertFalse($logger->isHandling(Logger::DEBUG)); |
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
$handler2->expects($this->any()) |
||||
->method('isHandling') |
||||
->will($this->returnValue(true)) |
||||
; |
||||
|
||||
$logger->pushHandler($handler2); |
||||
$this->assertTrue($logger->isHandling(Logger::DEBUG)); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider logMethodProvider |
||||
* @covers Monolog\Logger::addDebug |
||||
* @covers Monolog\Logger::addInfo |
||||
* @covers Monolog\Logger::addNotice |
||||
* @covers Monolog\Logger::addWarning |
||||
* @covers Monolog\Logger::addError |
||||
* @covers Monolog\Logger::addCritical |
||||
* @covers Monolog\Logger::addAlert |
||||
* @covers Monolog\Logger::addEmergency |
||||
* @covers Monolog\Logger::debug |
||||
* @covers Monolog\Logger::info |
||||
* @covers Monolog\Logger::notice |
||||
* @covers Monolog\Logger::warn |
||||
* @covers Monolog\Logger::err |
||||
* @covers Monolog\Logger::crit |
||||
* @covers Monolog\Logger::alert |
||||
* @covers Monolog\Logger::emerg |
||||
*/ |
||||
public function testLogMethods($method, $expectedLevel) |
||||
{ |
||||
$logger = new Logger('foo'); |
||||
$handler = new TestHandler; |
||||
$logger->pushHandler($handler); |
||||
$logger->{$method}('test'); |
||||
list($record) = $handler->getRecords(); |
||||
$this->assertEquals($expectedLevel, $record['level']); |
||||
} |
||||
|
||||
public function logMethodProvider() |
||||
{ |
||||
return array( |
||||
// monolog methods |
||||
array('addDebug', Logger::DEBUG), |
||||
array('addInfo', Logger::INFO), |
||||
array('addNotice', Logger::NOTICE), |
||||
array('addWarning', Logger::WARNING), |
||||
array('addError', Logger::ERROR), |
||||
array('addCritical', Logger::CRITICAL), |
||||
array('addAlert', Logger::ALERT), |
||||
array('addEmergency', Logger::EMERGENCY), |
||||
|
||||
// ZF/Sf2 compat methods |
||||
array('debug', Logger::DEBUG), |
||||
array('info', Logger::INFO), |
||||
array('notice', Logger::NOTICE), |
||||
array('warn', Logger::WARNING), |
||||
array('err', Logger::ERROR), |
||||
array('crit', Logger::CRITICAL), |
||||
array('alert', Logger::ALERT), |
||||
array('emerg', Logger::EMERGENCY), |
||||
); |
||||
} |
||||
} |
||||
@ -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'])); |
||||
} |
||||
} |
||||
@ -0,0 +1,123 @@ |
||||
<?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 Acme; |
||||
|
||||
class Tester |
||||
{ |
||||
public function test($handler, $record) |
||||
{ |
||||
$handler->handle($record); |
||||
} |
||||
} |
||||
|
||||
function tester($handler, $record) |
||||
{ |
||||
$handler->handle($record); |
||||
} |
||||
|
||||
namespace Monolog\Processor; |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\TestCase; |
||||
use Monolog\Handler\TestHandler; |
||||
|
||||
class IntrospectionProcessorTest extends TestCase |
||||
{ |
||||
public function getHandler() |
||||
{ |
||||
$processor = new IntrospectionProcessor(); |
||||
$handler = new TestHandler(); |
||||
$handler->pushProcessor($processor); |
||||
|
||||
return $handler; |
||||
} |
||||
|
||||
public function testProcessorFromClass() |
||||
{ |
||||
$handler = $this->getHandler(); |
||||
$tester = new \Acme\Tester; |
||||
$tester->test($handler, $this->getRecord()); |
||||
list($record) = $handler->getRecords(); |
||||
$this->assertEquals(__FILE__, $record['extra']['file']); |
||||
$this->assertEquals(18, $record['extra']['line']); |
||||
$this->assertEquals('Acme\Tester', $record['extra']['class']); |
||||
$this->assertEquals('test', $record['extra']['function']); |
||||
} |
||||
|
||||
public function testProcessorFromFunc() |
||||
{ |
||||
$handler = $this->getHandler(); |
||||
\Acme\tester($handler, $this->getRecord()); |
||||
list($record) = $handler->getRecords(); |
||||
$this->assertEquals(__FILE__, $record['extra']['file']); |
||||
$this->assertEquals(24, $record['extra']['line']); |
||||
$this->assertEquals(null, $record['extra']['class']); |
||||
$this->assertEquals('Acme\tester', $record['extra']['function']); |
||||
} |
||||
|
||||
public function testLevelTooLow() |
||||
{ |
||||
$input = array( |
||||
'level' => Logger::DEBUG, |
||||
'extra' => array(), |
||||
); |
||||
|
||||
$expected = $input; |
||||
|
||||
$processor = new IntrospectionProcessor(Logger::CRITICAL); |
||||
$actual = $processor($input); |
||||
|
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
|
||||
public function testLevelEqual() |
||||
{ |
||||
$input = array( |
||||
'level' => Logger::CRITICAL, |
||||
'extra' => array(), |
||||
); |
||||
|
||||
$expected = $input; |
||||
$expected['extra'] = array( |
||||
'file' => null, |
||||
'line' => null, |
||||
'class' => 'ReflectionMethod', |
||||
'function' => 'invokeArgs', |
||||
); |
||||
|
||||
$processor = new IntrospectionProcessor(Logger::CRITICAL); |
||||
$actual = $processor($input); |
||||
|
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
|
||||
public function testLevelHigher() |
||||
{ |
||||
$input = array( |
||||
'level' => Logger::EMERGENCY, |
||||
'extra' => array(), |
||||
); |
||||
|
||||
$expected = $input; |
||||
$expected['extra'] = array( |
||||
'file' => null, |
||||
'line' => null, |
||||
'class' => 'ReflectionMethod', |
||||
'function' => 'invokeArgs', |
||||
); |
||||
|
||||
$processor = new IntrospectionProcessor(Logger::CRITICAL); |
||||
$actual = $processor($input); |
||||
|
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue