Completed
Push — master ( c350e4...2fe906 )
by Fran
08:21
created

Logger::errorLog()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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