11<?php
22
3+ /*
4+ * This file is part of the Koded package.
5+ *
6+ * (c) Mihail Binev <mihail@kodeart.com>
7+ *
8+ * Please view the LICENSE distributed with this source code
9+ * for the full copyright and license information.
10+ *
11+ */
12+
313namespace Koded \Logging ;
414
5- use DateTime ;
6- use DateTimeZone ;
7- use Koded \Logging \Processors \{ ErrorLog , Processor };
15+ use Koded \Logging \Processors \{Cli , Processor };
816use Psr \Log \LoggerTrait ;
917use Throwable ;
1018
1624 *
1725 * CONFIGURATION PARAMETERS (Log class)
1826 *
27+ * - deferred (bool) [optional], default: false
28+ * A flag to set the Log instance how to dump messages.
29+ * Set to TRUE if you want to process all accumulated messages
30+ * at shutdown time. Otherwise, the default behavior is to process
31+ * the message immediately after the LoggerInterface method is called.
32+ *
1933 * - loggers (array)
2034 * An array of log processors. Every processor is defined in array with it's own
2135 * configuration parameters, but ALL must have the following:
2236 *
23- * - class (string) [required]
24- * The name of the log processor class.
25- * Can create multiple same instances with different config
26- * parameters.
37+ * - class (string) [required]
38+ * The name of the log processor class.
39+ * Can create multiple same instances with different config
40+ * parameters.
2741 *
28- * - levels (integer) [optional], default: -1 (for all levels)
29- * Packed integer for bitwise comparison. See the constants in this
30- * class.
42+ * - levels (integer) [optional], default: -1 (for all levels)
43+ * Packed integer for bitwise comparison. See the constants in this
44+ * class.
3145 *
32- * Example: Log::INFO | Log::ERROR | Log::ALERT
33- * Processor with these log levels will store only
34- * info, error and warning type messages.
46+ * Example: Log::INFO | Log::ERROR | Log::ALERT
47+ * Processor with these log levels will store only
48+ * info, error and warning type messages.
3549 *
36- * - dateformat (string) [optional], default: d/m/Y H:i:s
50+ * - dateformat (string) [optional], default: d/m/Y H:i:s.u
3751 * The date format for the log message.
3852 *
3953 * - timezone (string) [optional], default: UTC
4054 * The desired timezone for the DateTimeZone object.
4155 *
4256 *
4357 * CONFIGURATION PARAMETERS (Processor class)
44- * Every processor has it's own specific parameters (with the above directives) .
58+ * Every processor may have it's own specific parameters.
4559 *
4660 */
4761class Log implements Logger
4862{
49-
5063 use LoggerTrait;
5164
65+ /**
66+ * @var bool Flag to control the messages processing
67+ */
68+ private $ deferred = false ;
69+
5270 /**
5371 * @var string The date format for the message.
5472 */
@@ -76,26 +94,28 @@ class Log implements Logger
7694 */
7795 public function __construct (array $ settings )
7896 {
79- $ this ->dateFormat = $ settings ['dateformat ' ] ?? 'd/m/Y H:i:s ' ;
80- $ this ->timezone = $ settings ['timezone ' ] ?? $ this ->timezone ;
97+ $ this ->deferred = (bool )($ settings ['deferred ' ] ?? false );
98+ $ this ->dateFormat = (string )($ settings ['dateformat ' ] ?? 'd/m/Y H:i:s.u ' );
99+ $ this ->timezone = (string )($ settings ['timezone ' ] ?? $ this ->timezone );
81100
82- // Build and attach all requested processors
83- foreach ($ settings ['loggers ' ] ?? [] as $ processor ) {
101+ foreach ((array )($ settings ['loggers ' ] ?? []) as $ processor ) {
84102 $ this ->attach (new $ processor ['class ' ]($ processor ));
85103 }
104+
105+ if ($ this ->deferred ) {
106+ register_shutdown_function ([$ this , 'process ' ]);
107+ }
86108 }
87109
88- /**
89- * {@inheritdoc}
90- */
91- public function register ()
110+ public function attach (Processor $ processor ): Logger
92111 {
93- register_shutdown_function ([$ this , 'process ' ]);
112+ if (0 !== $ processor ->levels ()) {
113+ $ this ->processors [spl_object_hash ($ processor )] = $ processor ;
114+ }
115+
116+ return $ this ;
94117 }
95118
96- /**
97- * {@inheritdoc}
98- */
99119 public function log ($ level , $ message , array $ context = [])
100120 {
101121 try {
@@ -106,38 +126,35 @@ public function log($level, $message, array $context = [])
106126 $ level = -1 ;
107127 }
108128
109- $ microtime = microtime (true );
110-
111129 $ this ->messages [] = [
112- 'level ' => $ level ,
130+ 'level ' => $ level ,
113131 'levelname ' => $ levelname ,
114- 'message ' => $ this ->formatMessage ($ message , $ context ),
115- 'timestamp ' => (
116- (new DateTime (null , new DateTimeZone ('UTC ' )))
117- ->setTimestamp ($ microtime )
118- ->format ($ this ->dateFormat )
119- ) . substr (sprintf ('%.6F ' , $ microtime ), -7 )
132+ 'message ' => $ this ->formatMessage ($ message , $ context ),
133+ 'timestamp ' => date_create_immutable ('now ' , timezone_open ($ this ->timezone ))->format ($ this ->dateFormat ),
120134 ];
135+
136+ $ this ->deferred || $ this ->process ();
121137 }
122138
123139 /**
124- * {@inheritdoc}
140+ * Parses the message as in the interface specification.
141+ *
142+ * @param string|object $message A string or object that implements __toString
143+ * @param array $params [optional] Arbitrary data with key-value pairs replacements
144+ *
145+ * @return string
125146 */
126- public function exception ( Throwable $ e , Processor $ processor = null )
147+ private function formatMessage ( $ message , array $ params = []): string
127148 {
128- $ syslog = $ processor ?? new ErrorLog ([]);
129- $ message = $ e ->getMessage () . PHP_EOL . ' -- [Trace]: ' . $ e ->getTraceAsString ();
149+ $ replacements = [];
150+ foreach ($ params as $ k => $ v ) {
151+ $ replacements ['{ ' . $ k . '} ' ] = $ v ;
152+ }
130153
131- $ this ->attach ($ syslog );
132- $ this ->alert ($ message );
133- $ this ->process ();
134- $ this ->detach ($ syslog );
154+ return strtr ((string )$ message , $ replacements );
135155 }
136156
137- /**
138- * {@inheritdoc}
139- */
140- public function process ()
157+ public function process (): void
141158 {
142159 foreach ($ this ->processors as $ processor ) {
143160 $ processor ->update ($ this ->messages );
@@ -146,51 +163,20 @@ public function process()
146163 $ this ->messages = [];
147164 }
148165
149- /**
150- * Add a log processor in the stack.
151- *
152- * @param Processor $processor Logger processor instance
153- *
154- * @return Log
155- */
156- public function attach (Processor $ processor ): Log
166+ public function exception (Throwable $ e , Processor $ processor = null ): void
157167 {
158- if (0 !== $ processor ->levels ()) {
159- $ this ->processors [spl_object_hash ($ processor )] = $ processor ;
160- }
168+ $ logger = $ processor ?? new Cli ([]);
169+ $ message = $ e ->getMessage () . PHP_EOL . ' -- [Trace]: ' . $ e ->getTraceAsString ();
161170
162- return $ this ;
171+ $ this ->attach ($ logger )->critical ($ message );
172+ $ this ->process ();
173+ $ this ->detach ($ logger );
163174 }
164175
165- /**
166- * Detach a log processor from registered processors.
167- *
168- * @param Processor $processor The log processor to detach from the stack.
169- *
170- * @return Log
171- */
172- public function detach (Processor $ processor ): Log
176+ public function detach (Processor $ processor ): Logger
173177 {
174178 unset($ this ->processors [spl_object_hash ($ processor )]);
175179
176180 return $ this ;
177181 }
178-
179- /**
180- * Parses the message as in the interface specification.
181- *
182- * @param string|object $message A string or object that implements __toString
183- * @param array $context [optional] Arbitrary data with key-value pairs replacements
184- *
185- * @return string
186- */
187- private function formatMessage ($ message , array $ context = []): string
188- {
189- $ replacements = [];
190- foreach ($ context as $ k => $ v ) {
191- $ replacements ['{ ' . $ k . '} ' ] = $ v ;
192- }
193-
194- return strtr ((string )$ message , $ replacements );
195- }
196182}
0 commit comments