Passed
Branch master (9e4d0d)
by Fran
03:08
created

Logger::setup()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 5
nop 2
dl 0
loc 15
rs 8.8571
c 0
b 0
f 0
ccs 13
cts 13
cp 1
crap 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 17 and the first side effect is on line 16.

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\SingletonTrait;
13
14
15 1
if (!defined("LOG_DIR")) {
16
    Config::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
17
    define("LOG_DIR", BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
18
}
19
20
/**
21
 * Class Logger
22
 * @package PSFS\base
23
 * Servicio de log
24
 */
25
class Logger
26
{
27
    const DEFAULT_NAMESPACE = 'PSFS';
28
    use SingletonTrait;
29
    /**
30
     * @var \Monolog\Logger
31
     */
32
    protected $logger;
33
    /**
34
     * @var resource
35
     */
36
    private $stream;
37
    /**
38
     * @var string
39
     */
40
    protected $log_level;
41
42
    /**
43
     * @internal param string $path
44
     */
45 2
    public function __construct()
46
    {
47 2
        $config = Config::getInstance();
48 2
        $args = func_get_args();
49 2
        list($logger, $debug, $path) = $this->setup($config, $args);
50 2
        $this->stream = fopen($path . DIRECTORY_SEPARATOR . date("Ymd") . ".log", "a+");
51 2
        $this->addPushLogger($logger, $debug, $config);
52 2
        $this->log_level = Config::getInstance()->get('log.level') ?: 'info';
53 2
    }
54
55
    /**
56
     * Destruye el recurso
57
     */
58
    public function __destroy()
59
    {
60
        fclose($this->stream);
61
    }
62
63
    /**
64
     * Default log method
65
     * @param string $msg
66
     * @param array $context
67
     * @return bool
68
     */
69 1
    public function defaultLog($msg = '', $context = [])
70
    {
71 1
        return $this->logger->addNotice($msg, $this->addMinimalContext($context));
72
    }
73
74
    /**
75
     * Método que escribe un log de información
76
     * @param string $msg
77
     * @param array $context
78
     *
79
     * @return bool
80
     */
81 2
    public function infoLog($msg = '', $context = [])
82
    {
83 2
        return $this->logger->addInfo($msg, $this->addMinimalContext($context));
84
    }
85
86
    /**
87
     * Método que escribe un log de Debug
88
     * @param string $msg
89
     * @param array $context
90
     *
91
     * @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...
92
     */
93 11
    public function debugLog($msg = '', $context = [])
94
    {
95 11
        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...
96
    }
97
98
    /**
99
     * Método que escribe un log de Error
100
     * @param $msg
101
     * @param array $context
102
     *
103
     * @return bool
104
     */
105 4
    public function errorLog($msg, $context = [])
106
    {
107 4
        return $this->logger->addError($msg, $this->addMinimalContext($context));
108
    }
109
110
    /**
111
     * Método que escribe un log de Warning
112
     * @param $msg
113
     * @param array $context
114
     * @return bool
115
     */
116 1
    public function warningLog($msg, $context = [])
117
    {
118 1
        return $this->logger->addWarning($msg, $this->addMinimalContext($context));
119
    }
120
121
    /**
122
     * Método que añade los push processors
123
     * @param string $logger
124
     * @param boolean $debug
125
     * @param Config $config
126
     */
127 2
    private function addPushLogger($logger, $debug, Config $config)
128
    {
129 2
        $this->logger = new Monolog(strtoupper($logger));
130 2
        $this->logger->pushHandler($this->addDefaultStreamHandler($debug));
131 2
        if ($debug) {
132 1
            $phpFireLog = $config->get("logger.phpFire");
133 1
            if (!empty($phpFireLog)) {
134
                $this->logger->pushHandler(new FirePHPHandler());
135
            }
136 1
            $memoryLog = $config->get("logger.memory");
137 1
            if (!empty($memoryLog)) {
138 1
                $this->logger->pushProcessor(new MemoryUsageProcessor());
139 1
            }
140 1
        }
141 2
        $this->logger->pushProcessor(new UidProcessor());
142 2
    }
143
144
    /**
145
     * Método que inicializa el Logger
146
     * @param Config $config
147
     * @param array $args
148
     *
149
     * @return array
150
     */
151 2
    private function setup(Config $config, array $args = array())
152
    {
153 2
        $debug = $config->getDebugMode();
154 2
        $namespace = self::DEFAULT_NAMESPACE;
155 2
        if (0 !== count($args)) {
156 2
            if (array_key_exists(0, $args) && array_key_exists(0, $args[0])) {
157 1
                $namespace = $args[0][0];
158 1
            }
159 2
            if (array_key_exists(0, $args) && array_key_exists(1, $args[0])) {
160 1
                $debug = $args[0][1];
161 1
            }
162 2
        }
163 2
        $path = $this->createLoggerPath($config);
164 2
        return array($this->cleanLoggerName($namespace), $debug, $path);
165
    }
166
167
    /**
168
     * Método que construye el nombre del logger
169
     * @param Config $config
170
     *
171
     * @return string
172
     */
173 2
    private function setLoggerName(Config $config)
174
    {
175 2
        $logger = $config->get("platform_name") ?: self::DEFAULT_NAMESPACE;
176 2
        $logger = $this->cleanLoggerName($logger);
177
178 2
        return $logger;
179
    }
180
181
    /**
182
     * Método para limpiar el nombre del logger
183
     * @param $logger
184
     *
185
     * @return mixed
186
     */
187 2
    private function cleanLoggerName($logger)
188
    {
189 2
        $logger = str_replace(' ', '', $logger);
190 2
        $logger = preg_replace('/\\\/', ".", $logger);
191
192 2
        return $logger;
193
    }
194
195
    /**
196
     * Método que crea el path del logger
197
     * @param Config $config
198
     *
199
     * @return string
200
     */
201 2
    private function createLoggerPath(Config $config)
202
    {
203 2
        $logger = $this->setLoggerName($config);
204 2
        $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...
205 2
        Config::createDir($path);
206
207 2
        return $path;
208
    }
209
210
    /**
211
     * Static method to trace logs
212
     * @param string $msg
213
     * @param int $type
214
     * @param array $context
215
     */
216 11
    public static function log($msg, $type = LOG_DEBUG, $context = [])
217
    {
218
        switch ($type) {
219 11
            case LOG_DEBUG:
220 11
                Logger::getInstance()->debugLog($msg, $context);
221 11
                break;
222 5
            case LOG_WARNING:
223 1
                Logger::getInstance()->warningLog($msg, $context);
224 1
                break;
225 5
            case LOG_CRIT:
226 5
            case LOG_ERR:
227 4
                Logger::getInstance()->errorLog($msg, $context);
228 4
                break;
229 2
            case LOG_INFO:
230 2
                Logger::getInstance()->infoLog($msg, $context);
231 2
                break;
232 1
            default:
233 1
                Logger::getInstance()->defaultLog($msg, $context);
234 1
                break;
235 1
        }
236 11
    }
237
238
    /**
239
     * Add the default stream handler
240
     * @param bool $debug
241
     * @return StreamHandler
242
     */
243 2
    private function addDefaultStreamHandler($debug = false)
244
    {
245
        // the default date format is "Y-m-d H:i:s"
246 2
        $dateFormat = "Y-m-d H:i:s.u";
247
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
248 2
        $output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n";
249
        // finally, create a formatter
250 2
        $formatter = new LineFormatter($output, $dateFormat);
251 2
        $stream = new StreamHandler($this->stream, $debug ? Monolog::DEBUG : Monolog::WARNING);
252 2
        $stream->setFormatter($formatter);
253 2
        return $stream;
254
    }
255
256
    /**
257
     * Add a minimum context to the log
258
     * @param array $context
259
     * @return array
260
     */
261 5
    private function addMinimalContext(array $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...
262
    {
263 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...
264 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...
265 5
        return $context;
266
    }
267
}
268