Adding SyslogLogger
This commit is contained in:
		
					parent
					
						
							
								8e0355bec3
							
						
					
				
			
			
				commit
				
					
						9c5e0ae415
					
				
			
		
					 4 changed files with 271 additions and 29 deletions
				
			
		| 
						 | 
				
			
			@ -214,6 +214,10 @@ return [
 | 
			
		|||
		// If activated, all hashtags will point to the local server.
 | 
			
		||||
		'local_tags' => false,
 | 
			
		||||
 | 
			
		||||
		// logger_adapter (String)
 | 
			
		||||
		// Sets the logging adapter of Friendica globally (monolog, syslog)
 | 
			
		||||
		'logger_adapter' => 'syslog',
 | 
			
		||||
 | 
			
		||||
		// max_batch_queue (Integer)
 | 
			
		||||
		// Maximum number of batched queue items for a single contact before subsequent messages are discarded.
 | 
			
		||||
		'max_batch_queue' => 1000,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,8 @@ use Friendica\Core\Config\Configuration;
 | 
			
		|||
use Friendica\Core\Logger;
 | 
			
		||||
use Friendica\Network\HTTPException\InternalServerErrorException;
 | 
			
		||||
use Friendica\Util\Logger\FriendicaDevelopHandler;
 | 
			
		||||
use Friendica\Util\Logger\FriendicaIntrospectionProcessor;
 | 
			
		||||
use Friendica\Util\Logger\Introspection;
 | 
			
		||||
use Friendica\Util\Logger\SyslogLogger;
 | 
			
		||||
use Friendica\Util\Logger\WorkerLogger;
 | 
			
		||||
use Friendica\Util\Profiler;
 | 
			
		||||
use Monolog;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,27 +38,39 @@ class LoggerFactory
 | 
			
		|||
	 * @param Configuration $config  The config
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return LoggerInterface The PSR-3 compliant logger instance
 | 
			
		||||
	 * @throws InternalServerErrorException
 | 
			
		||||
	 */
 | 
			
		||||
	public static function create($channel, Configuration $config)
 | 
			
		||||
	{
 | 
			
		||||
		$loggerTimeZone = new \DateTimeZone('UTC');
 | 
			
		||||
		Monolog\Logger::setTimezone($loggerTimeZone);
 | 
			
		||||
		$introspector = new Introspection(LogLevel::DEBUG, self::$ignoreClassList);
 | 
			
		||||
		switch ($config->get('system', 'logger_adapter', 'monolog')) {
 | 
			
		||||
			case 'syslog':
 | 
			
		||||
				$level = $config->get('system', 'loglevel');
 | 
			
		||||
 | 
			
		||||
		$logger = new Monolog\Logger($channel);
 | 
			
		||||
		$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
 | 
			
		||||
		$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
 | 
			
		||||
		$logger->pushProcessor(new Monolog\Processor\UidProcessor());
 | 
			
		||||
		$logger->pushProcessor(new FriendicaIntrospectionProcessor(LogLevel::DEBUG, self::$ignoreClassList));
 | 
			
		||||
				$logger = new SyslogLogger($channel, $introspector, $level);
 | 
			
		||||
				break;
 | 
			
		||||
			case 'monolog':
 | 
			
		||||
			default:
 | 
			
		||||
				$loggerTimeZone = new \DateTimeZone('UTC');
 | 
			
		||||
				Monolog\Logger::setTimezone($loggerTimeZone);
 | 
			
		||||
 | 
			
		||||
		$debugging = $config->get('system', 'debugging');
 | 
			
		||||
		$stream    = $config->get('system', 'logfile');
 | 
			
		||||
		$level     = $config->get('system', 'loglevel');
 | 
			
		||||
				$logger = new Monolog\Logger($channel);
 | 
			
		||||
				$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
 | 
			
		||||
				$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
 | 
			
		||||
				$logger->pushProcessor(new Monolog\Processor\UidProcessor());
 | 
			
		||||
				$logger->pushProcessor($introspector);
 | 
			
		||||
 | 
			
		||||
		if ($debugging) {
 | 
			
		||||
			$loglevel = self::mapLegacyConfigDebugLevel((string)$level);
 | 
			
		||||
			static::addStreamHandler($logger, $stream, $loglevel);
 | 
			
		||||
		} else {
 | 
			
		||||
			static::addVoidHandler($logger);
 | 
			
		||||
				$debugging = $config->get('system', 'debugging');
 | 
			
		||||
				$stream    = $config->get('system', 'logfile');
 | 
			
		||||
				$level     = $config->get('system', 'loglevel');
 | 
			
		||||
 | 
			
		||||
				if ($debugging) {
 | 
			
		||||
					$loglevel = self::mapLegacyConfigDebugLevel((string)$level);
 | 
			
		||||
					static::addStreamHandler($logger, $stream, $loglevel);
 | 
			
		||||
				} else {
 | 
			
		||||
					static::addVoidHandler($logger);
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Logger::init($logger);
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +90,7 @@ class LoggerFactory
 | 
			
		|||
	 * @param Configuration $config  The config
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return LoggerInterface The PSR-3 compliant logger instance
 | 
			
		||||
	 * @throws InternalServerErrorException
 | 
			
		||||
	 */
 | 
			
		||||
	public static function createDev($channel, Configuration $config)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +109,7 @@ class LoggerFactory
 | 
			
		|||
		$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
 | 
			
		||||
		$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
 | 
			
		||||
		$logger->pushProcessor(new Monolog\Processor\UidProcessor());
 | 
			
		||||
		$logger->pushProcessor(new FriendicaIntrospectionProcessor(LogLevel::DEBUG, self::$ignoreClassList));
 | 
			
		||||
		$logger->pushProcessor(new Introspection(LogLevel::DEBUG, self::$ignoreClassList));
 | 
			
		||||
 | 
			
		||||
		$logger->pushHandler(new FriendicaDevelopHandler($developerIp));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ use Monolog\Processor\ProcessorInterface;
 | 
			
		|||
 * Based on the class IntrospectionProcessor without the "class" information
 | 
			
		||||
 * @see IntrospectionProcessor
 | 
			
		||||
 */
 | 
			
		||||
class FriendicaIntrospectionProcessor implements ProcessorInterface
 | 
			
		||||
class Introspection implements ProcessorInterface
 | 
			
		||||
{
 | 
			
		||||
	private $level;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +42,22 @@ class FriendicaIntrospectionProcessor implements ProcessorInterface
 | 
			
		|||
		if ($record['level'] < $this->level) {
 | 
			
		||||
			return $record;
 | 
			
		||||
		}
 | 
			
		||||
		// we should have the call source now
 | 
			
		||||
		$record['extra'] = array_merge(
 | 
			
		||||
			$record['extra'],
 | 
			
		||||
			$this->getRecord()
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		return $record;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Returns the introspection record of the current call
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return array
 | 
			
		||||
	 */
 | 
			
		||||
	public function getRecord()
 | 
			
		||||
	{
 | 
			
		||||
		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
 | 
			
		||||
 | 
			
		||||
		$i = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -53,17 +68,11 @@ class FriendicaIntrospectionProcessor implements ProcessorInterface
 | 
			
		|||
 | 
			
		||||
		$i += $this->skipStackFramesCount;
 | 
			
		||||
 | 
			
		||||
		// we should have the call source now
 | 
			
		||||
		$record['extra'] = array_merge(
 | 
			
		||||
			$record['extra'],
 | 
			
		||||
			[
 | 
			
		||||
				'file'      => isset($trace[$i - 1]['file']) ? basename($trace[$i - 1]['file']) : null,
 | 
			
		||||
				'line'      => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null,
 | 
			
		||||
				'function'  => isset($trace[$i]['function']) ? $trace[$i]['function'] : null,
 | 
			
		||||
			]
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		return $record;
 | 
			
		||||
		return [
 | 
			
		||||
			'file' => isset($trace[$i - 1]['file']) ? basename($trace[$i - 1]['file']) : null,
 | 
			
		||||
			'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null,
 | 
			
		||||
			'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null,
 | 
			
		||||
		];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
							
								
								
									
										215
									
								
								src/Util/Logger/SyslogLogger.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								src/Util/Logger/SyslogLogger.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,215 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Friendica\Util\Logger;
 | 
			
		||||
 | 
			
		||||
use Friendica\Network\HTTPException\InternalServerErrorException;
 | 
			
		||||
use Psr\Log\InvalidArgumentException;
 | 
			
		||||
use Psr\Log\LoggerInterface;
 | 
			
		||||
use Psr\Log\LogLevel;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A Logger instance for syslogging (fast, but simple)
 | 
			
		||||
 * @see http://php.net/manual/en/function.syslog.php
 | 
			
		||||
 */
 | 
			
		||||
class SyslogLogger implements LoggerInterface
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * Translates LogLevel log levels to syslog log priorities.
 | 
			
		||||
	 */
 | 
			
		||||
	private $logLevels = [
 | 
			
		||||
		LogLevel::DEBUG     => LOG_DEBUG,
 | 
			
		||||
		LogLevel::INFO      => LOG_INFO,
 | 
			
		||||
		LogLevel::NOTICE    => LOG_NOTICE,
 | 
			
		||||
		LogLevel::WARNING   => LOG_WARNING,
 | 
			
		||||
		LogLevel::ERROR     => LOG_ERR,
 | 
			
		||||
		LogLevel::CRITICAL  => LOG_CRIT,
 | 
			
		||||
		LogLevel::ALERT     => LOG_ALERT,
 | 
			
		||||
		LogLevel::EMERGENCY => LOG_EMERG,
 | 
			
		||||
	];
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The standard ident of the syslog (added to each message)
 | 
			
		||||
	 * @var string
 | 
			
		||||
	 */
 | 
			
		||||
	private $ident;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Indicates what logging options will be used when generating a log message
 | 
			
		||||
	 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
 | 
			
		||||
	 *
 | 
			
		||||
	 * @var int
 | 
			
		||||
	 */
 | 
			
		||||
	private $logOpts;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Used to specify what type of program is logging the message
 | 
			
		||||
	 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
 | 
			
		||||
	 *
 | 
			
		||||
	 * @var int
 | 
			
		||||
	 */
 | 
			
		||||
	private $logFacility;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The minimum loglevel at which this logger will be triggered
 | 
			
		||||
	 * @var int
 | 
			
		||||
	 */
 | 
			
		||||
	private $logLevel;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The Introspector for the current call
 | 
			
		||||
	 * @var Introspection
 | 
			
		||||
	 */
 | 
			
		||||
	private $introspection;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param string $channel     The channel (Syslog ident)
 | 
			
		||||
	 * @param string $level    The minimum loglevel at which this logger will be triggered
 | 
			
		||||
	 * @param int    $logOpts     Indicates what logging options will be used when generating a log message
 | 
			
		||||
	 * @param int    $logFacility Used to specify what type of program is logging the message
 | 
			
		||||
	 *
 | 
			
		||||
	 * @throws InternalServerErrorException if the loglevel isn't valid
 | 
			
		||||
	 */
 | 
			
		||||
	public function __construct($channel, Introspection $introspection, $level = LogLevel::NOTICE, $logOpts = LOG_PID, $logFacility = LOG_USER)
 | 
			
		||||
	{
 | 
			
		||||
		$this->ident = $channel;
 | 
			
		||||
		$this->logOpts = $logOpts;
 | 
			
		||||
		$this->logFacility = $logFacility;
 | 
			
		||||
		$this->logLevel = $this->mapLevelToPriority($level);
 | 
			
		||||
		$this->introspection = $introspection;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Maps the LogLevel (@see LogLevel ) to a SysLog priority (@see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters )
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param string $level A LogLevel
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return int The SysLog priority
 | 
			
		||||
	 *
 | 
			
		||||
	 * @throws \Psr\Log\InvalidArgumentException If the loglevel isn't valid
 | 
			
		||||
	 */
 | 
			
		||||
	public function mapLevelToPriority($level)
 | 
			
		||||
	{
 | 
			
		||||
		if (!array_key_exists($level, $this->logLevels)) {
 | 
			
		||||
			throw new InvalidArgumentException('LogLevel \'' . $level . '\' isn\'t valid.');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return $this->logLevels[$level];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Writes a message to the syslog
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param int    $priority The Priority ( @see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters )
 | 
			
		||||
	 * @param string $message The message of the log
 | 
			
		||||
	 * @throws InternalServerErrorException if syslog cannot be used
 | 
			
		||||
	 */
 | 
			
		||||
	private function write($priority, $message)
 | 
			
		||||
	{
 | 
			
		||||
		if (!openlog($this->ident, $this->logOpts, $this->logFacility)) {
 | 
			
		||||
			throw new InternalServerErrorException('Can\'t open syslog for ident "' . $this->ident . '" and facility "' . $this->logFacility . '""');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		syslog($priority, $message);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function close()
 | 
			
		||||
	{
 | 
			
		||||
		closelog();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private function formatLog($level, $message, $context = [])
 | 
			
		||||
	{
 | 
			
		||||
		$logMessage  = '';
 | 
			
		||||
 | 
			
		||||
		$logMessage .= $this->ident . ' ';
 | 
			
		||||
		$logMessage .= '[' . $level . ']: ';
 | 
			
		||||
		$logMessage .= $message . ' ';
 | 
			
		||||
		$logMessage .= json_encode($context) . ' - ';
 | 
			
		||||
		$logMessage .= json_encode($this->introspection->getRecord());
 | 
			
		||||
 | 
			
		||||
		return $logMessage;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private function addEntry($level, $message, $context = [])
 | 
			
		||||
	{
 | 
			
		||||
		if ($level >= $this->logLevel) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		$formattedLog = $this->formatLog($level, $message, $context);
 | 
			
		||||
		$this->write($level, $formattedLog);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function emergency($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_EMERG, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function alert($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_ALERT, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function critical($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_CRIT, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function error($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_ERR, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function warning($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_WARNING, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function notice($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_NOTICE, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function info($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_INFO, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function debug($message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$this->addEntry(LOG_DEBUG, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@inheritdoc}
 | 
			
		||||
	 */
 | 
			
		||||
	public function log($level, $message, array $context = array())
 | 
			
		||||
	{
 | 
			
		||||
		$logLevel = $this->mapLevelToPriority($level);
 | 
			
		||||
		$this->addEntry($logLevel, $message, $context);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue