1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
namespace PSFS\base; |
4
|
|
|
|
5
|
|
|
use Monolog\Formatter\LineFormatter; |
6
|
|
|
use Monolog\Handler\FirePHPHandler; |
7
|
|
|
use Monolog\Handler\StreamHandler; |
8
|
|
|
use Monolog\Logger as Monolog; |
9
|
|
|
use Monolog\Processor\MemoryUsageProcessor; |
10
|
|
|
use Monolog\Processor\UidProcessor; |
11
|
|
|
use PSFS\base\config\Config; |
12
|
|
|
use PSFS\base\types\helpers\GeneratorHelper; |
13
|
|
|
use PSFS\base\types\helpers\Inspector; |
14
|
|
|
use PSFS\base\types\traits\SingletonTrait; |
15
|
|
|
|
16
|
|
|
|
17
|
|
|
if (!defined("LOG_DIR")) { |
18
|
|
|
GeneratorHelper::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs'); |
19
|
|
|
define("LOG_DIR", BASE_DIR . DIRECTORY_SEPARATOR . 'logs'); |
20
|
|
|
} |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Class Logger |
24
|
|
|
* @package PSFS\base |
25
|
|
|
* Servicio de log |
26
|
|
|
*/ |
27
|
|
|
class Logger |
28
|
|
|
{ |
29
|
|
|
const DEFAULT_NAMESPACE = 'PSFS'; |
30
|
|
|
use SingletonTrait; |
31
|
|
|
/** |
32
|
|
|
* @var \Monolog\Logger |
33
|
|
|
*/ |
34
|
|
|
protected $logger; |
35
|
|
|
/** |
36
|
|
|
* @var resource |
37
|
|
|
*/ |
38
|
|
|
private $stream; |
39
|
|
|
/** |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
protected $log_level; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @internal param string $path |
46
|
|
|
*/ |
47
|
2 |
|
public function __construct() |
48
|
|
|
{ |
49
|
2 |
|
$config = Config::getInstance(); |
50
|
2 |
|
$args = func_get_args(); |
51
|
2 |
|
list($logger, $debug, $path) = $this->setup($config, $args); |
52
|
2 |
|
$this->stream = fopen($path . DIRECTORY_SEPARATOR . date("Ymd") . ".log", "a+"); |
53
|
2 |
|
$this->addPushLogger($logger, $debug, $config); |
54
|
2 |
|
$this->log_level = Config::getParam('log.level', 'info'); |
55
|
2 |
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Destruye el recurso |
59
|
|
|
*/ |
60
|
1 |
|
public function __destruct() |
61
|
|
|
{ |
62
|
1 |
|
fclose($this->stream); |
63
|
1 |
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Default log method |
67
|
|
|
* @param string $msg |
68
|
|
|
* @param array $context |
69
|
|
|
* @return bool |
70
|
|
|
*/ |
71
|
1 |
|
public function defaultLog($msg = '', $context = []) |
72
|
|
|
{ |
73
|
1 |
|
return $this->logger->addNotice($msg, $this->addMinimalContext($context)); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Método que escribe un log de información |
78
|
|
|
* @param string $msg |
79
|
|
|
* @param array $context |
80
|
|
|
* |
81
|
|
|
* @return bool |
82
|
|
|
*/ |
83
|
3 |
|
public function infoLog($msg = '', $context = []) |
84
|
|
|
{ |
85
|
3 |
|
return $this->logger->addInfo($msg, $this->addMinimalContext($context)); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Método que escribe un log de Debug |
90
|
|
|
* @param string $msg |
91
|
|
|
* @param array $context |
92
|
|
|
* |
93
|
|
|
* @return bool |
94
|
|
|
*/ |
95
|
18 |
|
public function debugLog($msg = '', $context = []) |
96
|
|
|
{ |
97
|
18 |
|
return ($this->log_level === 'debug') ? $this->logger->addDebug($msg, $this->addMinimalContext($context)) : null; |
|
|
|
|
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Método que escribe un log de Error |
102
|
|
|
* @param $msg |
103
|
|
|
* @param array $context |
104
|
|
|
* |
105
|
|
|
* @return bool |
106
|
|
|
*/ |
107
|
3 |
|
public function errorLog($msg, $context = []) |
108
|
|
|
{ |
109
|
3 |
|
return $this->logger->addError($msg, $this->addMinimalContext($context)); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Método que escribe un log de Warning |
114
|
|
|
* @param $msg |
115
|
|
|
* @param array $context |
116
|
|
|
* @return bool |
117
|
|
|
*/ |
118
|
2 |
|
public function warningLog($msg, $context = []) |
119
|
|
|
{ |
120
|
2 |
|
return $this->logger->addWarning($msg, $this->addMinimalContext($context)); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Método que añade los push processors |
125
|
|
|
* @param string $logger |
126
|
|
|
* @param boolean $debug |
127
|
|
|
* @param Config $config |
128
|
|
|
*/ |
129
|
2 |
|
private function addPushLogger($logger, $debug, Config $config) |
130
|
|
|
{ |
131
|
2 |
|
$this->logger = new Monolog(strtoupper($logger)); |
132
|
2 |
|
$this->logger->pushHandler($this->addDefaultStreamHandler($debug)); |
133
|
2 |
|
if ($debug) { |
134
|
1 |
|
$phpFireLog = $config->get("logger.phpFire"); |
135
|
1 |
|
if (!empty($phpFireLog)) { |
136
|
1 |
|
$this->logger->pushHandler(new FirePHPHandler()); |
137
|
|
|
} |
138
|
1 |
|
$memoryLog = $config->get("logger.memory"); |
139
|
1 |
|
if (!empty($memoryLog)) { |
140
|
1 |
|
$this->logger->pushProcessor(new MemoryUsageProcessor()); |
141
|
|
|
} |
142
|
|
|
} |
143
|
2 |
|
$this->logger->pushProcessor(new UidProcessor()); |
144
|
2 |
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Método que inicializa el Logger |
148
|
|
|
* @param Config $config |
149
|
|
|
* @param array $args |
150
|
|
|
* |
151
|
|
|
* @return array |
152
|
|
|
*/ |
153
|
2 |
|
private function setup(Config $config, array $args = array()) |
154
|
|
|
{ |
155
|
2 |
|
$debug = $config->getDebugMode(); |
156
|
2 |
|
$namespace = self::DEFAULT_NAMESPACE; |
157
|
2 |
|
if (0 !== count($args)) { |
158
|
2 |
|
if (array_key_exists(0, $args) && array_key_exists(0, $args[0])) { |
159
|
1 |
|
$namespace = $args[0][0]; |
160
|
|
|
} |
161
|
2 |
|
if (array_key_exists(0, $args) && array_key_exists(1, $args[0])) { |
162
|
1 |
|
$debug = $args[0][1]; |
163
|
|
|
} |
164
|
|
|
} |
165
|
2 |
|
$path = $this->createLoggerPath($config); |
166
|
2 |
|
return array($this->cleanLoggerName($namespace), $debug, $path); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* Método que construye el nombre del logger |
171
|
|
|
* @param Config $config |
172
|
|
|
* |
173
|
|
|
* @return string |
174
|
|
|
*/ |
175
|
2 |
|
private function setLoggerName(Config $config) |
176
|
|
|
{ |
177
|
2 |
|
$logger = $config->get("platform_name") ?: self::DEFAULT_NAMESPACE; |
178
|
2 |
|
$logger = $this->cleanLoggerName($logger); |
179
|
|
|
|
180
|
2 |
|
return $logger; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Método para limpiar el nombre del logger |
185
|
|
|
* @param $logger |
186
|
|
|
* |
187
|
|
|
* @return mixed |
188
|
|
|
*/ |
189
|
2 |
|
private function cleanLoggerName($logger) |
190
|
|
|
{ |
191
|
2 |
|
$logger = str_replace(' ', '', $logger); |
192
|
2 |
|
$logger = preg_replace('/\\\/', ".", $logger); |
193
|
|
|
|
194
|
2 |
|
return $logger; |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Método que crea el path del logger |
199
|
|
|
* @param Config $config |
200
|
|
|
* |
201
|
|
|
* @return string |
202
|
|
|
*/ |
203
|
2 |
|
private function createLoggerPath(Config $config) |
204
|
|
|
{ |
205
|
2 |
|
$logger = $this->setLoggerName($config); |
206
|
2 |
|
$path = LOG_DIR . DIRECTORY_SEPARATOR . $logger . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m'); |
|
|
|
|
207
|
2 |
|
GeneratorHelper::createDir($path); |
208
|
|
|
|
209
|
2 |
|
return $path; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Static method to trace logs |
214
|
|
|
* @param string $msg |
215
|
|
|
* @param int $type |
216
|
|
|
* @param array $context |
217
|
|
|
*/ |
218
|
18 |
|
public static function log($msg, $type = LOG_DEBUG, $context = []) |
219
|
|
|
{ |
220
|
18 |
|
if(Config::getParam('profiling.enable')) { |
221
|
|
|
Inspector::stats($msg); |
222
|
|
|
} |
223
|
|
|
switch ($type) { |
224
|
18 |
|
case LOG_DEBUG: |
225
|
18 |
|
Logger::getInstance()->debugLog($msg, $context); |
226
|
18 |
|
break; |
227
|
5 |
|
case LOG_WARNING: |
228
|
2 |
|
Logger::getInstance()->warningLog($msg, $context); |
229
|
2 |
|
break; |
230
|
5 |
|
case LOG_CRIT: |
231
|
5 |
|
case LOG_ERR: |
232
|
3 |
|
Logger::getInstance()->errorLog($msg, $context); |
233
|
3 |
|
break; |
234
|
3 |
|
case LOG_INFO: |
235
|
3 |
|
Logger::getInstance()->infoLog($msg, $context); |
236
|
3 |
|
break; |
237
|
|
|
default: |
238
|
1 |
|
Logger::getInstance()->defaultLog($msg, $context); |
239
|
1 |
|
break; |
240
|
|
|
} |
241
|
18 |
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Add the default stream handler |
245
|
|
|
* @param bool $debug |
246
|
|
|
* @return StreamHandler |
247
|
|
|
*/ |
248
|
2 |
|
private function addDefaultStreamHandler($debug = false) |
249
|
|
|
{ |
250
|
|
|
// the default date format is "Y-m-d H:i:s" |
251
|
2 |
|
$dateFormat = "Y-m-d H:i:s.u"; |
252
|
|
|
// the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n" |
253
|
2 |
|
$output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n"; |
254
|
|
|
// finally, create a formatter |
255
|
2 |
|
$formatter = new LineFormatter($output, $dateFormat); |
256
|
2 |
|
$stream = new StreamHandler($this->stream, $debug ? Monolog::DEBUG : Monolog::WARNING); |
257
|
2 |
|
$stream->setFormatter($formatter); |
258
|
2 |
|
return $stream; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Add a minimum context to the log |
263
|
|
|
* @param array $context |
264
|
|
|
* @return array |
265
|
|
|
*/ |
266
|
5 |
|
private function addMinimalContext($context = []) |
|
|
|
|
267
|
|
|
{ |
268
|
5 |
|
if(!is_array($context)) { |
269
|
|
|
$context = []; |
270
|
|
|
} |
271
|
5 |
|
$context['uri'] = null !== $_SERVER && array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : 'Unknow'; |
|
|
|
|
272
|
5 |
|
$context['method'] = null !== $_SERVER && array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'Unknow'; |
|
|
|
|
273
|
5 |
|
return $context; |
274
|
|
|
} |
275
|
|
|
} |
276
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.