/** * {@inheritdoc} */ public function format(array $record) : string { $record = parent::format($record); if (empty($record['datetime'])) { $record['datetime'] = gmdate('c'); } $message = ['@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName]; if (isset($record['message'])) { $message['message'] = $record['message']; } if (isset($record['channel'])) { $message['type'] = $record['channel']; $message['channel'] = $record['channel']; } if (isset($record['level_name'])) { $message['level'] = $record['level_name']; } if ($this->applicationName) { $message['type'] = $this->applicationName; } if (!empty($record['extra'])) { foreach ($record['extra'] as $key => $val) { $message[$this->extraPrefix . $key] = $val; } } if (!empty($record['context'])) { foreach ($record['context'] as $key => $val) { $message[$this->contextPrefix . $key] = $val; } } return $this->toJson($message) . "\n"; }
protected function normalize($data) { if (is_bool($data) || is_null($data)) { return var_export($data, true); } return parent::normalize($data); }
/** * {@inheritdoc} */ public function format(array $record) { $vars = parent::format($record); $output = $this->format; foreach ($vars['extra'] as $var => $val) { if (false !== strpos($output, '%extra.' . $var . '%')) { $output = str_replace('%extra.' . $var . '%', $this->stringify($val), $output); unset($vars['extra'][$var]); } } foreach ($vars['context'] as $var => $val) { if (false !== strpos($output, '%context.' . $var . '%')) { $output = str_replace('%context.' . $var . '%', $this->stringify($val), $output); unset($vars['context'][$var]); } } if ($this->ignoreEmptyContextAndExtra) { if (empty($vars['context'])) { unset($vars['context']); $output = str_replace('%context%', '', $output); } if (empty($vars['extra'])) { unset($vars['extra']); $output = str_replace('%extra%', '', $output); } } foreach ($vars as $var => $val) { if (false !== strpos($output, '%' . $var . '%')) { $output = str_replace('%' . $var . '%', $this->stringify($val), $output); } } return $output; }
/** * {@inheritdoc} */ public function format(array $record) { $record = parent::format($record); if ($this->version === self::V1) { $message = $this->formatV1($record); } else { $message = $this->formatV0($record); } return $this->toJson($message) . "\n"; }
protected function normalize($data) { if (is_bool($data) || is_null($data)) { return var_export($data, true); } if ($data instanceof \Exception) { return '[object] (' . get_class($data) . ': ' . $data->getMessage() . ' at ' . $data->getFile() . ':' . $data->getLine() . ')'; } return parent::normalize($data); }
/** * @param string $applicationName the application that sends the data, used as the "type" field of logstash * @param string $systemName the system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine * @param string $extraPrefix prefix for extra keys inside logstash "fields" * @param string $contextPrefix prefix for context keys inside logstash "fields", defaults to ctxt_ */ public function __construct($applicationName, $systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $version = self::V0) { // logstash requires a ISO 8601 format date with optional millisecond precision. parent::__construct('Y-m-d\\TH:i:s.uP'); $this->systemName = $systemName ?: gethostname(); $this->applicationName = $applicationName; $this->extraPrefix = $extraPrefix; $this->contextPrefix = $contextPrefix; $this->version = $version; }
protected function normalize($data) { if (is_bool($data) || is_null($data)) { return var_export($data, true); } if ($data instanceof \Exception) { $previousText = ''; if ($previous = $data->getPrevious()) { do { $previousText .= ', ' . get_class($previous) . ': ' . $previous->getMessage() . ' at ' . $previous->getFile() . ':' . $previous->getLine(); } while ($previous = $previous->getPrevious()); } return '[object] (' . get_class($data) . ': ' . $data->getMessage() . ' at ' . $data->getFile() . ':' . $data->getLine() . $previousText . ')'; } return parent::normalize($data); }
/** * {@inheritdoc} */ public function format(array $record) { $vars = parent::format($record); $output = $this->format; foreach ($vars['extra'] as $var => $val) { if (false !== strpos($output, '%extra.' . $var . '%')) { $output = str_replace('%extra.' . $var . '%', $this->stringify($val), $output); unset($vars['extra'][$var]); } } foreach ($vars['context'] as $var => $val) { if (false !== strpos($output, '%context.' . $var . '%')) { $output = str_replace('%context.' . $var . '%', $this->stringify($val), $output); unset($vars['context'][$var]); } } if ($this->ignoreEmptyContextAndExtra) { if (empty($vars['context'])) { unset($vars['context']); $output = str_replace('%context%', '', $output); } if (empty($vars['extra'])) { unset($vars['extra']); $output = str_replace('%extra%', '', $output); } } foreach ($vars as $var => $val) { if (false !== strpos($output, '%' . $var . '%')) { $output = str_replace('%' . $var . '%', $this->stringify($val), $output); } } // remove leftover %extra.xxx% and %context.xxx% if any if (false !== strpos($output, '%')) { $output = preg_replace('/%(?:extra|context)\\..+?%/', '', $output); } return $output; }
/** * * {@inheritdoc} * */ public function format(array $record) { $record = parent::format($record); $message = array('@timestamp' => $record['datetime'], '@message' => $record['message'], '@tags' => array($record['channel']), '@source' => $this->systemName); if ($this->applicationName) { $message['@type'] = $this->applicationName; } $message['@fields'] = array(); $message['@fields']['channel'] = $record['channel']; $message['@fields']['level'] = $record['level']; if (isset($record['extra']['server'])) { $message['@source_host'] = $record['extra']['server']; } if (isset($record['extra']['url'])) { $message['@source_path'] = $record['extra']['url']; } foreach ($record['extra'] as $key => $val) { $message['@fields'][$this->extraPrefix . $key] = $val; } foreach ($record['context'] as $key => $val) { $message['@fields'][$this->contextPrefix . $key] = $val; } return json_encode($message) . "\n"; }
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); }
public function testExceptionTraceWithArgs() { if (defined('HHVM_VERSION')) { $this->markTestSkipped('Not supported in HHVM since it detects errors differently'); } // This happens i.e. in React promises or Guzzle streams where stream wrappers are registered // and no file or line are included in the trace because it's treated as internal function set_error_handler(function ($errno, $errstr, $errfile, $errline) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); }); try { // This will contain $resource and $wrappedResource as arguments in the trace item $resource = fopen('php://memory', 'rw+'); fwrite($resource, 'test_resource'); $wrappedResource = new TestStreamFoo($resource); // Just do something stupid with a resource/wrapped resource as argument array_keys($wrappedResource); } catch (\Exception $e) { restore_error_handler(); } $formatter = new NormalizerFormatter(); $record = array('context' => array('exception' => $e)); $result = $formatter->format($record); $this->assertRegExp('%"resource":"\\[resource\\]"%', $result['context']['exception']['trace'][0]); if (version_compare(PHP_VERSION, '5.5.0', '>=')) { $pattern = '%"wrappedResource":"\\[object\\] \\(Monolog\\\\\\\\Formatter\\\\\\\\TestStreamFoo: \\)"%'; } else { $pattern = '%\\\\"resource\\\\":null%'; } // Tests that the wrapped resource is ignored while encoding, only works for PHP <= 5.4 $this->assertRegExp($pattern, $result['context']['exception']['trace'][0]); }