Passed
Push — master ( 4a30ca...c0bf7f )
by Fran
03:52
created

Logger   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 246
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 9

Test Coverage

Coverage 97.89%

Importance

Changes 0
Metric Value
dl 0
loc 246
ccs 93
cts 95
cp 0.9789
rs 8.8
c 0
b 0
f 0
wmc 36
lcom 3
cbo 9

15 Methods

Rating   Name   Duplication   Size   Complexity  
A defaultLog() 0 4 1
A infoLog() 0 4 1
A debugLog() 0 4 2
A errorLog() 0 4 1
A warningLog() 0 4 1
B setup() 0 15 6
A setLoggerName() 0 7 2
A cleanLoggerName() 0 7 1
A createLoggerPath() 0 8 1
B log() 0 21 6
A addDefaultStreamHandler() 0 12 2
A __construct() 0 9 1
A __destruct() 0 4 1
A addPushLogger() 0 16 4
B addMinimalContext() 0 9 6
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 18 and the first side effect is on line 17.

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.

Loading history...
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\SingletonTrait;
14
15
16
if (!defined("LOG_DIR")) {
17
    GeneratorHelper::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
18
    define("LOG_DIR", BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
19
}
20
21
/**
22
 * Class Logger
23
 * @package PSFS\base
24
 * Servicio de log
25
 */
26
class Logger
27
{
28
    const DEFAULT_NAMESPACE = 'PSFS';
29
    use SingletonTrait;
30
    /**
31
     * @var \Monolog\Logger
32
     */
33
    protected $logger;
34
    /**
35
     * @var resource
36
     */
37
    private $stream;
38
    /**
39
     * @var string
40
     */
41
    protected $log_level;
42
43
    /**
44
     * @internal param string $path
45
     */
46 1
    public function __construct()
47
    {
48 1
        $config = Config::getInstance();
49 1
        $args = func_get_args();
50 1
        list($logger, $debug, $path) = $this->setup($config, $args);
51 1
        $this->stream = fopen($path . DIRECTORY_SEPARATOR . date("Ymd") . ".log", "a+");
52 1
        $this->addPushLogger($logger, $debug, $config);
53 1
        $this->log_level = Config::getParam('log.level', 'info');
54 1
    }
55
56
    /**
57
     * Destruye el recurso
58
     */
59 1
    public function __destruct()
60
    {
61 1
        fclose($this->stream);
62 1
    }
63
64
    /**
65
     * Default log method
66
     * @param string $msg
67
     * @param array $context
68
     * @return bool
69
     */
70 1
    public function defaultLog($msg = '', $context = [])
71
    {
72 1
        return $this->logger->addNotice($msg, $this->addMinimalContext($context));
73
    }
74
75
    /**
76
     * Método que escribe un log de información
77
     * @param string $msg
78
     * @param array $context
79
     *
80
     * @return bool
81
     */
82 2
    public function infoLog($msg = '', $context = [])
83
    {
84 2
        return $this->logger->addInfo($msg, $this->addMinimalContext($context));
85
    }
86
87
    /**
88
     * Método que escribe un log de Debug
89
     * @param string $msg
90
     * @param array $context
91
     *
92
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
93
     */
94 15
    public function debugLog($msg = '', $context = [])
95
    {
96 15
        return ($this->log_level === 'debug') ? $this->logger->addDebug($msg, $this->addMinimalContext($context)) : null;
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
97
    }
98
99
    /**
100
     * Método que escribe un log de Error
101
     * @param $msg
102
     * @param array $context
103
     *
104
     * @return bool
105
     */
106 4
    public function errorLog($msg, $context = [])
107
    {
108 4
        return $this->logger->addError($msg, $this->addMinimalContext($context));
109
    }
110
111
    /**
112
     * Método que escribe un log de Warning
113
     * @param $msg
114
     * @param array $context
115
     * @return bool
116
     */
117 1
    public function warningLog($msg, $context = [])
118
    {
119 1
        return $this->logger->addWarning($msg, $this->addMinimalContext($context));
120
    }
121
122
    /**
123
     * Método que añade los push processors
124
     * @param string $logger
125
     * @param boolean $debug
126
     * @param Config $config
127
     */
128 1
    private function addPushLogger($logger, $debug, Config $config)
129
    {
130 1
        $this->logger = new Monolog(strtoupper($logger));
131 1
        $this->logger->pushHandler($this->addDefaultStreamHandler($debug));
132 1
        if ($debug) {
133 1
            $phpFireLog = $config->get("logger.phpFire");
134 1
            if (!empty($phpFireLog)) {
135 1
                $this->logger->pushHandler(new FirePHPHandler());
136 1
            }
137 1
            $memoryLog = $config->get("logger.memory");
138 1
            if (!empty($memoryLog)) {
139 1
                $this->logger->pushProcessor(new MemoryUsageProcessor());
140 1
            }
141 1
        }
142 1
        $this->logger->pushProcessor(new UidProcessor());
143 1
    }
144
145
    /**
146
     * Método que inicializa el Logger
147
     * @param Config $config
148
     * @param array $args
149
     *
150
     * @return array
151
     */
152 1
    private function setup(Config $config, array $args = array())
153
    {
154 1
        $debug = $config->getDebugMode();
155 1
        $namespace = self::DEFAULT_NAMESPACE;
156 1
        if (0 !== count($args)) {
157 1
            if (array_key_exists(0, $args) && array_key_exists(0, $args[0])) {
158 1
                $namespace = $args[0][0];
159 1
            }
160 1
            if (array_key_exists(0, $args) && array_key_exists(1, $args[0])) {
161 1
                $debug = $args[0][1];
162 1
            }
163 1
        }
164 1
        $path = $this->createLoggerPath($config);
165 1
        return array($this->cleanLoggerName($namespace), $debug, $path);
166
    }
167
168
    /**
169
     * Método que construye el nombre del logger
170
     * @param Config $config
171
     *
172
     * @return string
173
     */
174 1
    private function setLoggerName(Config $config)
175
    {
176 1
        $logger = $config->get("platform_name") ?: self::DEFAULT_NAMESPACE;
177 1
        $logger = $this->cleanLoggerName($logger);
178
179 1
        return $logger;
180
    }
181
182
    /**
183
     * Método para limpiar el nombre del logger
184
     * @param $logger
185
     *
186
     * @return mixed
187
     */
188 1
    private function cleanLoggerName($logger)
189
    {
190 1
        $logger = str_replace(' ', '', $logger);
191 1
        $logger = preg_replace('/\\\/', ".", $logger);
192
193 1
        return $logger;
194
    }
195
196
    /**
197
     * Método que crea el path del logger
198
     * @param Config $config
199
     *
200
     * @return string
201
     */
202 1
    private function createLoggerPath(Config $config)
203
    {
204 1
        $logger = $this->setLoggerName($config);
205 1
        $path = LOG_DIR . DIRECTORY_SEPARATOR . $logger . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 124 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
206 1
        GeneratorHelper::createDir($path);
207
208 1
        return $path;
209
    }
210
211
    /**
212
     * Static method to trace logs
213
     * @param string $msg
214
     * @param int $type
215
     * @param array $context
216
     */
217 15
    public static function log($msg, $type = LOG_DEBUG, $context = [])
218
    {
219
        switch ($type) {
220 15
            case LOG_DEBUG:
221 15
                Logger::getInstance()->debugLog($msg, $context);
222 15
                break;
223 5
            case LOG_WARNING:
224 1
                Logger::getInstance()->warningLog($msg, $context);
225 1
                break;
226 5
            case LOG_CRIT:
227 5
            case LOG_ERR:
228 4
                Logger::getInstance()->errorLog($msg, $context);
229 4
                break;
230 2
            case LOG_INFO:
231 2
                Logger::getInstance()->infoLog($msg, $context);
232 2
                break;
233 1
            default:
234 1
                Logger::getInstance()->defaultLog($msg, $context);
235 1
                break;
236 1
        }
237 15
    }
238
239
    /**
240
     * Add the default stream handler
241
     * @param bool $debug
242
     * @return StreamHandler
243
     */
244 1
    private function addDefaultStreamHandler($debug = false)
245
    {
246
        // the default date format is "Y-m-d H:i:s"
247 1
        $dateFormat = "Y-m-d H:i:s.u";
248
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
249 1
        $output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n";
250
        // finally, create a formatter
251 1
        $formatter = new LineFormatter($output, $dateFormat);
252 1
        $stream = new StreamHandler($this->stream, $debug ? Monolog::DEBUG : Monolog::WARNING);
253 1
        $stream->setFormatter($formatter);
254 1
        return $stream;
255
    }
256
257
    /**
258
     * Add a minimum context to the log
259
     * @param array $context
260
     * @return array
261
     */
262 5
    private function addMinimalContext($context = [])
0 ignored issues
show
Coding Style introduced by
addMinimalContext uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
263
    {
264 5
        if(!is_array($context)) {
265
            $context = [];
266
        }
267 5
        $context['uri'] = null !== $_SERVER && array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : 'Unknow';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
268 5
        $context['method'] = null !== $_SERVER && array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'Unknow';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 135 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
269 5
        return $context;
270
    }
271
}
272