1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * TSysLogRoute class file |
||||
5 | * |
||||
6 | * @author Brad Anderson <[email protected]> |
||||
7 | * @link https://github.com/pradosoft/prado |
||||
8 | * @license https://github.com/pradosoft/prado/blob/master/LICENSE |
||||
9 | */ |
||||
10 | |||||
11 | namespace Prado\Util; |
||||
12 | |||||
13 | use Prado\Exceptions\TConfigurationException; |
||||
14 | use Prado\Exceptions\TLogException; |
||||
15 | use Prado\Prado; |
||||
16 | use Prado\TPropertyValue; |
||||
17 | |||||
18 | /** |
||||
19 | * TSysLogRoute class. |
||||
20 | * |
||||
21 | * Sends the log to the syslog. |
||||
22 | * |
||||
23 | * @author Brad Anderson <[email protected]> |
||||
24 | * @since 4.3.0 |
||||
25 | * @link https://www.php.net/manual/en/function.openlog.php |
||||
26 | * @link https://www.php.net/manual/en/function.syslog.php |
||||
27 | */ |
||||
28 | class TSysLogRoute extends TLogRoute |
||||
29 | { |
||||
30 | /** |
||||
31 | * @var false|string The Prefix for openlog() |
||||
32 | */ |
||||
33 | private string|false $_sysLogPrefix = false; |
||||
34 | |||||
35 | /** |
||||
36 | * @var ?int The flags for openlog(), default null for `LOG_ODELAY | LOG_PID` |
||||
37 | */ |
||||
38 | private ?int $_sysLogFlags = null; |
||||
39 | |||||
40 | /** |
||||
41 | * @var int The facility for openlog(). |
||||
42 | */ |
||||
43 | private int $_facility = LOG_USER; |
||||
44 | |||||
45 | /** |
||||
46 | * @param array $logs list of log messages |
||||
47 | * @param bool $final is the final flush |
||||
48 | * @param array $meta the meta data for the logs. |
||||
49 | * @throws TLogException When failing to write to syslog. |
||||
50 | */ |
||||
51 | protected function processLogs(array $logs, bool $final, array $meta) |
||||
52 | { |
||||
53 | openlog($this->getSysLogPrefix(), $this->getSysLogFlags(), $this->getFacility()); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
54 | foreach ($logs as $log) { |
||||
55 | if (syslog($this->translateLogLevel($log[TLogger::LOG_LEVEL]), $this->formatLogMessage($log)) === false) { |
||||
56 | throw new TLogException('syslogroute_log_failed'); |
||||
57 | } |
||||
58 | } |
||||
59 | closelog(); |
||||
60 | } |
||||
61 | |||||
62 | /** |
||||
63 | * Translates a PRADO log level attribute into one understood by syslog |
||||
64 | * @param int $level prado log level |
||||
65 | * @return int syslog priority |
||||
66 | */ |
||||
67 | protected static function translateLogLevel($level) |
||||
68 | { |
||||
69 | switch ($level) { |
||||
70 | case TLogger::PROFILE: |
||||
71 | case TLogger::PROFILE_BEGIN: |
||||
72 | case TLogger::PROFILE_END: |
||||
73 | case TLogger::DEBUG: |
||||
74 | return LOG_DEBUG; |
||||
75 | case TLogger::INFO: |
||||
76 | return LOG_INFO; |
||||
77 | case TLogger::NOTICE: |
||||
78 | return LOG_NOTICE; |
||||
79 | case TLogger::WARNING: |
||||
80 | return LOG_WARNING; |
||||
81 | case TLogger::ERROR: |
||||
82 | return LOG_ERR; |
||||
83 | case TLogger::ALERT: |
||||
84 | return LOG_ALERT; |
||||
85 | case TLogger::FATAL: |
||||
86 | return LOG_CRIT; |
||||
87 | default: |
||||
88 | return LOG_INFO; |
||||
89 | } |
||||
90 | } |
||||
91 | |||||
92 | /** |
||||
93 | * @return string The prefix for syslog. Defaults to false |
||||
94 | */ |
||||
95 | public function getSysLogPrefix(): string|false |
||||
96 | { |
||||
97 | return $this->_sysLogPrefix; |
||||
0 ignored issues
–
show
The expression
return $this->_sysLogPrefix could also return false which is incompatible with the documented return type string . Did you maybe forget to handle an error condition?
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled. ![]() |
|||||
98 | } |
||||
99 | |||||
100 | /** |
||||
101 | * @param string $value the prefix for the syslog, via openlog |
||||
102 | */ |
||||
103 | public function setSysLogPrefix($value) |
||||
104 | { |
||||
105 | $value = TPropertyValue::ensureString($value); |
||||
106 | if ($value === '') { |
||||
107 | $value = false; |
||||
108 | } |
||||
109 | $this->_sysLogPrefix = $value; |
||||
110 | } |
||||
111 | |||||
112 | /** |
||||
113 | * @return int The options for syslog. Defaults to LOG_ODELAY | LOG_PID |
||||
114 | */ |
||||
115 | public function getSysLogFlags() |
||||
116 | { |
||||
117 | return ($this->_sysLogFlags !== null) ? $this->_sysLogFlags : LOG_ODELAY | LOG_PID; |
||||
118 | } |
||||
119 | |||||
120 | /** |
||||
121 | * This sets the `openlog` flags. It can be an integer, a string or an array of strings. |
||||
122 | * As a string, the delimiters are ',' and '|' acting identically. |
||||
123 | * |
||||
124 | * By setting to null, this will default to `LOG_ODELAY | LOG_PID`. |
||||
125 | * @param null|int|string|string[] $value the options for syslog |
||||
126 | * @return static The current object. |
||||
127 | * @throw TConfigurationException When the Flags are not valid. |
||||
128 | */ |
||||
129 | public function setSysLogFlags($value): static |
||||
130 | { |
||||
131 | static $_flagsMap = [ |
||||
132 | 'LOG_CONS' => LOG_CONS, // Errors to console |
||||
133 | 'LOG_NDELAY' => LOG_NDELAY, // open immediately |
||||
134 | 'LOG_ODELAY' => LOG_ODELAY, // delay opening until a log |
||||
135 | 'LOG_PERROR' => LOG_PERROR, // Print to STDERR as well. |
||||
136 | 'LOG_PID' => LOG_PID, // include ProcessID |
||||
137 | ]; |
||||
138 | |||||
139 | if ($value === null || is_int($value)) { |
||||
140 | $invalidFlags = ~array_reduce($_flagsMap, function ($flags, $flag) { |
||||
141 | return $flags | $flag; |
||||
142 | }, 0); |
||||
143 | if ($invalidFlags & ((int) $value)) { |
||||
144 | throw new TConfigurationException('syslogroute_bad_flags', '0x' . dechex($value)); |
||||
0 ignored issues
–
show
It seems like
$value can also be of type null ; however, parameter $num of dechex() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
145 | } |
||||
146 | $this->_sysLogFlags = $value; |
||||
147 | } else { |
||||
148 | if (!is_array($value)) { |
||||
149 | $value = preg_split('/[|,]/', strtoupper($value)); |
||||
150 | } else { |
||||
151 | $value = array_map('strtoupper', $value); |
||||
152 | } |
||||
153 | $options = array_map('trim', $value); |
||||
154 | $this->_sysLogFlags = 0; |
||||
155 | while (count($options)) { |
||||
156 | $option = array_pop($options); |
||||
157 | if (isset($_flagsMap[$option])) { |
||||
158 | $this->_sysLogFlags |= $_flagsMap[$option]; |
||||
159 | } |
||||
160 | } |
||||
161 | } |
||||
162 | return $this; |
||||
163 | } |
||||
164 | |||||
165 | /** |
||||
166 | * @return int The facility for syslog. |
||||
167 | */ |
||||
168 | public function getFacility(): int |
||||
169 | { |
||||
170 | return $this->_facility; |
||||
171 | } |
||||
172 | |||||
173 | /** |
||||
174 | * @param int|string $value the options for syslog |
||||
175 | * @return static The current object. |
||||
176 | */ |
||||
177 | public function setFacility($value): static |
||||
178 | { |
||||
179 | static $_facilitiesMap = [ |
||||
180 | 'LOG_AUTH' => LOG_AUTH, // 0x20 |
||||
181 | 'LOG_CRON' => LOG_CRON, // 0x48 |
||||
182 | 'LOG_DAEMON' => LOG_DAEMON, // 0x18 |
||||
183 | 'LOG_KERN' => LOG_KERN, // 0x00 |
||||
184 | 'LOG_LOCAL0' => LOG_LOCAL0, // 0x80 |
||||
185 | 'LOG_LOCAL1' => LOG_LOCAL1, // 0x88 |
||||
186 | 'LOG_LOCAL2' => LOG_LOCAL2, // 0x90 |
||||
187 | 'LOG_LOCAL3' => LOG_LOCAL3, // 0x98 |
||||
188 | 'LOG_LOCAL4' => LOG_LOCAL4, // 0xa0 |
||||
189 | 'LOG_LOCAL5' => LOG_LOCAL5, // 0xa8 |
||||
190 | 'LOG_LOCAL6' => LOG_LOCAL6, // 0xb0 |
||||
191 | 'LOG_LOCAL7' => LOG_LOCAL7, // 0xb8 |
||||
192 | 'LOG_LPR' => LOG_LPR, // 0x30 |
||||
193 | 'LOG_MAIL' => LOG_MAIL, // 0x10 |
||||
194 | 'LOG_NEWS' => LOG_NEWS, // 0x38 |
||||
195 | 'LOG_SYSLOG' => LOG_SYSLOG, // 0x28 |
||||
196 | 'LOG_USER' => LOG_USER, // 0x08 |
||||
197 | 'LOG_UUCP' => LOG_UUCP, // 0x40 |
||||
198 | ]; |
||||
199 | if (defined('LOG_AUTHPRIV')) { |
||||
200 | $_facilitiesMap['LOG_AUTH'] = LOG_AUTHPRIV; |
||||
201 | } |
||||
202 | |||||
203 | if (is_int($value)) { |
||||
204 | if (defined('LOG_AUTHPRIV') && $value === LOG_AUTH) { |
||||
205 | $value = LOG_AUTHPRIV; |
||||
206 | } |
||||
207 | |||||
208 | if (array_search($value, $_facilitiesMap) === false) { |
||||
209 | throw new TConfigurationException('syslogroute_bad_facility', '0x' . dechex($value)); |
||||
210 | } |
||||
211 | } else { |
||||
212 | $value = trim(strtoupper($value)); |
||||
213 | if (isset($_facilitiesMap[$value])) { |
||||
214 | $value = $_facilitiesMap[$value]; |
||||
215 | } else { |
||||
216 | throw new TConfigurationException('syslogroute_bad_facility', '0x' . dechex($value)); |
||||
0 ignored issues
–
show
$value of type string is incompatible with the type integer expected by parameter $num of dechex() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
217 | } |
||||
218 | } |
||||
219 | $this->_facility = $value; |
||||
220 | |||||
221 | return $this; |
||||
222 | } |
||||
223 | |||||
224 | /** |
||||
225 | * {@inheritdoc} |
||||
226 | */ |
||||
227 | public function formatLogMessage(array $log): string |
||||
228 | { |
||||
229 | if (!is_string($log[TLogger::LOG_MESSAGE])) { |
||||
230 | if ($log[TLogger::LOG_MESSAGE] instanceof \Exception || $log[TLogger::LOG_MESSAGE] instanceof \Throwable) { |
||||
231 | $log[TLogger::LOG_MESSAGE] = (string) $log[TLogger::LOG_MESSAGE]; |
||||
232 | } else { |
||||
233 | $log[TLogger::LOG_MESSAGE] = \Prado\Util\TVarDumper::dump($log[TLogger::LOG_MESSAGE]); |
||||
234 | } |
||||
235 | } |
||||
236 | |||||
237 | $prefix = $this->getLogPrefix($log); |
||||
238 | |||||
239 | return $prefix . '[' . static::getLevelName($log[TLogger::LOG_LEVEL]) . '][' . $log[TLogger::LOG_CATEGORY] . '] ' . $log[TLogger::LOG_MESSAGE]; |
||||
0 ignored issues
–
show
The method
Prado\Util\TLogRoute::getLevelName() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
240 | } |
||||
241 | } |
||||
242 |