Fix Object parsing for Logging
[friendica.git/.git] / src / Util / Logger / AbstractLogger.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Util\Logger;
23
24 use Friendica\Util\Introspection;
25 use Friendica\Util\Strings;
26 use Psr\Log\LoggerInterface;
27 use Psr\Log\LogLevel;
28
29 /**
30  * This class contains all necessary dependencies and calls for Friendica
31  * Every new Logger should extend this class and define, how addEntry() works
32  *
33  * Additional information for each Logger, who extends this class:
34  * - Introspection
35  * - UID for each call
36  * - Channel of the current call (i.e. index, worker, daemon, ...)
37  */
38 abstract class AbstractLogger implements LoggerInterface
39 {
40         /**
41          * The output channel of this logger
42          * @var string
43          */
44         protected $channel;
45
46         /**
47          * The Introspection for the current call
48          * @var Introspection
49          */
50         protected $introspection;
51
52         /**
53          * The UID of the current call
54          * @var string
55          */
56         protected $logUid;
57
58         /**
59          * Adds a new entry to the log
60          *
61          * @param int    $level
62          * @param string $message
63          * @param array  $context
64          *
65          * @return void
66          */
67         abstract protected function addEntry($level, $message, $context = []);
68
69         /**
70          * @param string        $channel       The output channel
71          * @param Introspection $introspection The introspection of the current call
72          *
73          * @throws \Exception
74          */
75         public function __construct($channel, Introspection $introspection)
76         {
77                 $this->channel       = $channel;
78                 $this->introspection = $introspection;
79                 $this->logUid        = Strings::getRandomHex(6);
80         }
81
82         /**
83          * Simple interpolation of PSR-3 compliant replacements ( variables between '{' and '}' )
84          * @see https://www.php-fig.org/psr/psr-3/#12-message
85          *
86          * @param string $message
87          * @param array  $context
88          *
89          * @return string the interpolated message
90          */
91         protected function psrInterpolate($message, array $context = array())
92         {
93                 $replace = [];
94                 foreach ($context as $key => $value) {
95                         // check that the value can be casted to string
96                         if (!is_array($value) && (!is_object($value) || method_exists($value, '__toString'))) {
97                                 $replace['{' . $key . '}'] = $value;
98                         } elseif (is_array($value)) {
99                                 $replace['{' . $key . '}'] = @json_encode($value);
100                         }
101                 }
102
103                 return strtr($message, $replace);
104         }
105
106         /**
107          * JSON Encodes an complete array including objects with "__toString()" methods
108          *
109          * @param array $input an Input Array to encode
110          *
111          * @return false|string The json encoded output of the array
112          */
113         protected function jsonEncodeArray(array $input)
114         {
115                 $output = [];
116
117                 foreach ($input as $key => $value) {
118                         if (is_object($value) && method_exists($value, '__toString')) {
119                                 $output[$key] = $value->__toString();
120                         } else {
121                                 $output[$key] = $value;
122                         }
123                 }
124
125                 return @json_encode($output);
126         }
127
128         /**
129          * {@inheritdoc}
130          */
131         public function emergency($message, array $context = array())
132         {
133                 $this->addEntry(LogLevel::EMERGENCY, (string) $message, $context);
134         }
135
136         /**
137          * {@inheritdoc}
138          */
139         public function alert($message, array $context = array())
140         {
141                 $this->addEntry(LogLevel::ALERT, (string) $message, $context);
142         }
143
144         /**
145          * {@inheritdoc}
146          */
147         public function critical($message, array $context = array())
148         {
149                 $this->addEntry(LogLevel::CRITICAL, (string) $message, $context);
150         }
151
152         /**
153          * {@inheritdoc}
154          */
155         public function error($message, array $context = array())
156         {
157                 $this->addEntry(LogLevel::ERROR, (string) $message, $context);
158         }
159
160         /**
161          * {@inheritdoc}
162          */
163         public function warning($message, array $context = array())
164         {
165                 $this->addEntry(LogLevel::WARNING, (string) $message, $context);
166         }
167
168         /**
169          * {@inheritdoc}
170          */
171         public function notice($message, array $context = array())
172         {
173                 $this->addEntry(LogLevel::NOTICE, (string) $message, $context);
174         }
175
176         /**
177          * {@inheritdoc}
178          */
179         public function info($message, array $context = array())
180         {
181                 $this->addEntry(LogLevel::INFO, (string) $message, $context);
182         }
183
184         /**
185          * {@inheritdoc}
186          */
187         public function debug($message, array $context = array())
188         {
189                 $this->addEntry(LogLevel::DEBUG, (string) $message, $context);
190         }
191
192         /**
193          * {@inheritdoc}
194          */
195         public function log($level, $message, array $context = array())
196         {
197                 $this->addEntry($level, (string) $message, $context);
198         }
199 }