19
19
* Minimalist PSR-3 logger designed to write in stdout, stderr or any other stream.
20
20
*
21
21
* @author Kévin Dunglas <dunglas@gmail.com>
22
- *
23
- * @see http://www.php-fig.org/psr/psr-3/
24
22
*/
25
23
final class Logger extends AbstractLogger
26
24
{
27
- /**
28
- * @var array
29
- */
30
- private static $ defaultLevelToStream = array (
25
+ private static $ defaultOutputByLevel = array (
31
26
LogLevel::EMERGENCY => 'php://stderr ' ,
32
27
LogLevel::ALERT => 'php://stderr ' ,
33
28
LogLevel::CRITICAL => 'php://stderr ' ,
34
29
LogLevel::ERROR => 'php://stderr ' ,
35
- LogLevel::WARNING => 'php://stdout ' ,
36
- LogLevel::NOTICE => ' php://stdout ' ,
37
- LogLevel::INFO => ' php://stdout ' ,
30
+ LogLevel::WARNING => 'php://stderr ' ,
31
+ LogLevel::NOTICE => false ,
32
+ LogLevel::INFO => false ,
38
33
LogLevel::DEBUG => false ,
39
34
);
40
-
41
- private $ levelToStream ;
42
- private $ formatPattern ;
43
-
44
- /**
45
- * @var bool
46
- */
35
+ private $ outputByLevel ;
36
+ private $ format ;
37
+ private $ dateFormat ;
47
38
private $ errored = false ;
39
+ private $ handles = array ();
48
40
49
- /**
50
- * @param array $levelToStream
51
- * @param string $formatPattern
52
- */
53
- public function __construct (array $ levelToStream = array (), $ formatPattern = '[%s] %s ' )
41
+ public function __construct (array $ outputByLevel = array (), $ format = '[%s] %s ' , $ dateFormat = \DateTime::RFC3339 )
54
42
{
55
- $ this ->levelToStream = $ levelToStream + self ::$ defaultLevelToStream ;
56
- $ this ->formatPattern = $ formatPattern ;
43
+ $ this ->outputByLevel = $ outputByLevel + self ::$ defaultOutputByLevel ;
44
+ $ this ->format = $ format ;
45
+ $ this ->dateFormat = $ dateFormat ;
46
+ }
47
+
48
+ public function __destruct ()
49
+ {
50
+ foreach ($ this ->handles as $ handle ) {
51
+ fclose ($ handle );
52
+ }
57
53
}
58
54
59
55
/**
60
56
* {@inheritdoc}
61
57
*/
62
58
public function log ($ level , $ message , array $ context = array ())
63
59
{
64
- if (!isset ($ this ->levelToStream [$ level ])) {
60
+ if (!isset ($ this ->outputByLevel [$ level ])) {
65
61
throw new InvalidArgumentException (sprintf ('The log level "%s" does not exist. ' , $ level ));
66
62
}
67
63
68
64
if (!$ this ->errored ) {
69
65
$ this ->errored = in_array ($ level , array (LogLevel::EMERGENCY , LogLevel::ALERT , LogLevel::CRITICAL , LogLevel::ERROR ));
70
66
}
71
67
72
- if ($ this ->levelToStream [$ level ]) {
73
- file_put_contents ($ this ->levelToStream [$ level ], sprintf ($ this ->formatPattern , $ level , $ this ->interpolate ($ message , $ context )).PHP_EOL , FILE_APPEND );
68
+ if ($ stream = $ this ->outputByLevel [$ level ]) {
69
+ if (!isset ($ this ->handles [$ stream ])) {
70
+ $ this ->handles [$ stream ] = fopen ($ stream , 'a ' );
71
+ }
72
+
73
+ fwrite ($ this ->handles [$ stream ], sprintf ($ this ->format , $ level , $ this ->interpolate ($ message , $ context )).PHP_EOL );
74
74
}
75
75
}
76
76
@@ -87,24 +87,33 @@ public function hasErrored()
87
87
/**
88
88
* Interpolates context values into the message placeholders.
89
89
*
90
- * @author PHP Framework Interoperability Group
90
+ * @author Jordi Boggiano <j.boggiano@seld.be>
91
+ *
92
+ * @see https://github.com/Seldaek/monolog/blob/master/src/Monolog/Processor/PsrLogMessageProcessor.php
91
93
*
92
94
* @param string $message
93
- * @param array $context
94
95
*
95
96
* @return string
96
97
*/
<
6377
/td>97
98
private function interpolate ($ message , array $ context )
98
99
{
99
- // build a replacement array with braces around the context keys
100
- $ replace = array ();
100
+ if (false === strpos ($ message , '{ ' )) {
101
+ return $ message ;
102
+ }
103
+
104
+ $ replacements = array ();
101
105
foreach ($ context as $ key => $ val ) {
102
- if (!is_array ($ val ) && (!is_object ($ val ) || method_exists ($ val , '__toString ' ))) {
103
- $ replace [sprintf ('{%s} ' , $ key )] = $ val ;
106
+ if (null === $ val || \is_scalar ($ val ) || (\is_object ($ val ) && \method_exists ($ val , '__toString ' ))) {
107
+ $ replacements ["{ {$ key }} " ] = $ val ;
108
+ } elseif ($ val instanceof \DateTimeInterface) {
109
+ $ replacements ["{ {$ key }} " ] = $ val ->format ($ this ->dateFormat );
110
+ } elseif (is_object ($ val )) {
111
+ $ replacements ["{ {$ key }} " ] = '[object ' .\get_class ($ val ).'] ' ;
112
+ } else {
113
+ $ replacements ["{ {$ key }} " ] = '[ ' .\gettype ($ val ).'] ' ;
104
114
}
105
115
}
106
116
107
- // interpolate replacement values into the message and return
108
- return strtr ($ message , $ replace );
117
+ return strtr ($ message , $ replacements );
109
118
}
110
119
}
0 commit comments