3 namespace Friendica\Util\Logger;
5 use Friendica\Network\HTTPException\InternalServerErrorException;
6 use Friendica\Util\Introspection;
10 * A Logger instance for syslogging (fast, but simple)
11 * @see http://php.net/manual/en/function.syslog.php
13 class SyslogLogger extends AbstractLogger
15 const IDENT = 'Friendica';
18 * Translates LogLevel log levels to syslog log priorities.
21 private $logLevels = [
22 LogLevel::DEBUG => LOG_DEBUG,
23 LogLevel::INFO => LOG_INFO,
24 LogLevel::NOTICE => LOG_NOTICE,
25 LogLevel::WARNING => LOG_WARNING,
26 LogLevel::ERROR => LOG_ERR,
27 LogLevel::CRITICAL => LOG_CRIT,
28 LogLevel::ALERT => LOG_ALERT,
29 LogLevel::EMERGENCY => LOG_EMERG,
33 * Translates log priorities to string outputs
36 private $logToString = [
39 LOG_NOTICE => 'NOTICE',
40 LOG_WARNING => 'WARNING',
42 LOG_CRIT => 'CRITICAL',
44 LOG_EMERG => 'EMERGENCY'
48 * Indicates what logging options will be used when generating a log message
49 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
56 * Used to specify what type of program is logging the message
57 * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters
64 * The minimum loglevel at which this logger will be triggered
71 * @param string $level The minimum loglevel at which this logger will be triggered
72 * @param int $logOpts Indicates what logging options will be used when generating a log message
73 * @param int $logFacility Used to specify what type of program is logging the message
77 public function __construct($channel, Introspection $introspection, $level = LogLevel::NOTICE, $logOpts = LOG_PID, $logFacility = LOG_USER)
79 parent::__construct($channel, $introspection);
80 $this->logOpts = $logOpts;
81 $this->logFacility = $logFacility;
82 $this->logLevel = $this->mapLevelToPriority($level);
83 $this->introspection->addClasses(array(self::class));
87 * Adds a new entry to the syslog
90 * @param string $message
91 * @param array $context
93 * @throws InternalServerErrorException if the syslog isn't available
95 protected function addEntry($level, $message, $context = [])
97 $logLevel = $this->mapLevelToPriority($level);
99 if ($logLevel > $this->logLevel) {
103 $formattedLog = $this->formatLog($logLevel, $message, $context);
104 $this->write($logLevel, $formattedLog);
108 * Maps the LogLevel (@see LogLevel ) to a SysLog priority (@see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters )
110 * @param string $level A LogLevel
112 * @return int The SysLog priority
114 * @throws \Psr\Log\InvalidArgumentException If the loglevel isn't valid
116 public function mapLevelToPriority($level)
118 if (!array_key_exists($level, $this->logLevels)) {
119 throw new \InvalidArgumentException(sprintf('The level "%s" is not valid.', $level));
122 return $this->logLevels[$level];
128 public function close()
134 * Writes a message to the syslog
135 * @see http://php.net/manual/en/function.syslog.php#refsect1-function.syslog-parameters
137 * @param int $priority The Priority
138 * @param string $message The message of the log
140 * @throws InternalServerErrorException if syslog cannot be used
142 private function write($priority, $message)
144 if (!openlog(self::IDENT, $this->logOpts, $this->logFacility)) {
145 throw new InternalServerErrorException('Can\'t open syslog for ident "' . $this->channel . '" and facility "' . $this->logFacility . '""');
148 $this->syslogWrapper($priority, $message);
152 * Formats a log record for the syslog output
154 * @param int $level The loglevel/priority
155 * @param string $message The message
156 * @param array $context The context of this call
158 * @return string the formatted syslog output
160 private function formatLog($level, $message, $context = [])
162 $record = $this->introspection->getRecord();
163 $record = array_merge($record, ['uid' => $this->logUid]);
166 $logMessage .= $this->channel . ' ';
167 $logMessage .= '[' . $this->logToString[$level] . ']: ';
168 $logMessage .= $this->psrInterpolate($message, $context) . ' ';
169 $logMessage .= @json_encode($context) . ' - ';
170 $logMessage .= @json_encode($record);
176 * A syslog wrapper to make syslog functionality testable
178 * @param int $level The syslog priority
179 * @param string $entry The message to send to the syslog function
181 protected function syslogWrapper($level, $entry)
183 syslog($level, $entry);