Completed
Push — master ( c877ec...c350e4 )
by Fran
04:32
created

Logger::defaultLog()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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