Passed
Push — master ( 786715...5dce3b )
by Fran
02:39
created

Logger   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 174
Duplicated Lines 0 %

Test Coverage

Coverage 95.16%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 59
c 6
b 0
f 0
dl 0
loc 174
ccs 59
cts 62
cp 0.9516
rs 10
wmc 25

11 Methods

Rating   Name   Duplication   Size   Complexity  
A addPushLogger() 0 16 4
A setup() 0 11 2
A createLoggerPath() 0 6 1
A getUid() 0 3 1
A log() 0 14 6
A __construct() 0 11 3
A setLoggerName() 0 4 1
A getLogUid() 0 3 1
A __destruct() 0 3 1
A addLog() 0 3 3
A addDefaultStreamHandler() 0 11 2
1
<?php
2
3
namespace PSFS\base;
4
5
use Monolog\Formatter\JsonFormatter;
6
use Monolog\Formatter\LineFormatter;
7
use Monolog\Handler\FirePHPHandler;
8
use Monolog\Handler\StreamHandler;
9
use Monolog\Processor\MemoryUsageProcessor;
10
use Monolog\Processor\UidProcessor;
11
use PSFS\base\config\Config;
12
use PSFS\base\exception\ConfigException;
13
use PSFS\base\exception\GeneratorException;
14
use PSFS\base\types\helpers\GeneratorHelper;
15
use PSFS\base\types\helpers\Inspector;
16
use PSFS\base\types\helpers\LogHelper;
17
use PSFS\base\types\helpers\SlackHelper;
18
use PSFS\base\types\traits\SingletonTrait;
19
20
21
if (!defined('LOG_DIR')) {
22
    GeneratorHelper::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
23
    define('LOG_DIR', BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
24
}
25
26
/**
27
 * Class Logger
28
 * @package PSFS\base
29
 * Servicio de log
30
 */
31
class Logger
32
{
33
    const DEFAULT_NAMESPACE = 'PSFS';
34
    use SingletonTrait;
35
36
    /**
37
     * @var \Monolog\Logger
38
     */
39
    protected \Monolog\Logger $logger;
40
    /**
41
     * @var resource
42
     */
43
    private $stream;
44
    /**
45
     * @var UidProcessor
46
     */
47
    private $uuid;
48
    /**
49
     * @var string
50
     */
51
    protected string $logLevel;
52
53
    /**
54
     * Logger constructor.
55
     * @throws GeneratorException
56
     * @throws ConfigException
57
     * @throws \Exception
58
     */
59 1
    public function __construct()
60
    {
61 1
        $args = func_get_args();
62 1
        list($logger, $debug, $path) = $this->setup($args);
63 1
        $this->stream = fopen($path . DIRECTORY_SEPARATOR . date('Ymd') . '.log', 'ab+');
64 1
        if (false !== $this->stream && is_resource($this->stream)) {
65 1
            $this->addPushLogger($logger, $debug);
66
        } else {
67
            throw new ConfigException(t('Error creating logger'));
68
        }
69 1
        $this->logLevel = strtoupper(Config::getParam('log.level', 'NOTICE'));
70
    }
71
72 1
    public function __destruct()
73
    {
74 1
        fclose($this->stream);
75
    }
76
77
    /**
78
     * @param string $logger
79
     * @param boolean $debug
80
     * @throws \Exception
81
     */
82 1
    private function addPushLogger(string $logger, bool $debug): void
83
    {
84 1
        $this->logger = new \Monolog\Logger(strtoupper($logger));
85 1
        $this->logger->pushHandler($this->addDefaultStreamHandler($debug));
86 1
        if ($debug) {
87 1
            $phpFireLog = Config::getParam('logger.phpFire');
88 1
            if (!empty($phpFireLog)) {
89 1
                $this->logger->pushHandler(new FirePHPHandler());
90
            }
91 1
            $memoryLog = Config::getParam('logger.memory');
92 1
            if (!empty($memoryLog)) {
93 1
                $this->logger->pushProcessor(new MemoryUsageProcessor());
94
            }
95
        }
96 1
        $this->uuid = new UidProcessor();
97 1
        $this->logger->pushProcessor($this->uuid);
98
    }
99
100
    /**
101
     * @param array $args
102
     * @return array
103
     * @throws exception\GeneratorException
104
     */
105 1
    private function setup(array $args = []): array
106
    {
107 1
        $args = $args ?? [];
108 1
        $debug = Config::getParam('debug');
109 1
        $namespace = self::DEFAULT_NAMESPACE;
110 1
        if (0 !== count($args)) {
111 1
            $namespace = $args[0][0] ?? 'PSFS';
112 1
            $debug = $args[0][1] ?? true;
113
        }
114 1
        $path = $this->createLoggerPath();
115 1
        return [LogHelper::cleanLoggerName($namespace), $debug, $path];
116
    }
117
118
    /**
119
     * @return string
120
     */
121 1
    private function setLoggerName(): string
122
    {
123 1
        $logger = Config::getParam('platform.name', self::DEFAULT_NAMESPACE);
124 1
        return LogHelper::cleanLoggerName($logger);
125
    }
126
127
    /**
128
     * @return string
129
     * @throws exception\GeneratorException
130
     */
131 1
    private function createLoggerPath(): string
132
    {
133 1
        $logger = $this->setLoggerName();
134 1
        $path = Config::getParam('default.log.path', LOG_DIR) . DIRECTORY_SEPARATOR . $logger . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
135 1
        GeneratorHelper::createDir($path);
136 1
        return $path;
137
    }
138
139
    /**
140
     * @param string $msg
141
     * @param \Monolog\Level $type
142
     * @param array $context
143
     * @param boolean $force
144
     * @return bool
145
     */
146 31
    public function addLog(string $msg, \Monolog\Level $type = \Monolog\Level::Notice, array $context = [], bool $force = false)
147
    {
148 31
        return !(LogHelper::checkLogLevel($this->logLevel, $type) || $force) || $this->logger->addRecord($type, $msg, LogHelper::addMinimalContext($context));
149
    }
150
151
    /**
152
     * @param string $msg
153
     * @param int $type
154
     * @param array|null $context
155
     * @param bool $force
156
     */
157 31
    public static function log(string $msg, int $type = LOG_DEBUG, array $context = null, bool $force = false): void
158
    {
159 31
        if (null === $context) {
160 29
            $context = [];
161
        }
162 31
        if (Config::getParam('profiling.enable') && 'DEBUG' === Config::getParam('log.level', 'NOTICE')) {
163
            Inspector::stats($msg, Inspector::SCOPE_DEBUG);
164
        }
165 31
        $level = LogHelper::calculateLogLevel($type);
166 31
        if (in_array($level, [\Monolog\Level::Critical, \Monolog\Level::Error, \Monolog\Level::Emergency]) &&
167 31
            strlen(Config::getParam('log.slack.hook', '')) > 0) {
168
            SlackHelper::getInstance()->trace($msg, '', '', $context);
169
        }
170 31
        self::getInstance()->addLog($msg, \Monolog\Level::Notice, $context, $force);
171
    }
172
173
    /**
174
     * @param bool $debug
175
     * @return StreamHandler
176
     * @throws \Exception
177
     */
178 1
    private function addDefaultStreamHandler(bool $debug = false): StreamHandler
179
    {
180
        // the default date format is "Y-m-d H:i:s"
181 1
        $dateFormat = 'Y-m-d H:i:s.u';
182
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
183 1
        $output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n";
184
        // finally, create a formatter
185 1
        $formatter = new LineFormatter($output, $dateFormat);
186 1
        $stream = new StreamHandler($this->stream, $debug ? \Monolog\Level::Debug : \Monolog\Level::Warning);
187 1
        $stream->setFormatter($formatter);
188 1
        return $stream;
189
    }
190
191
    /**
192
     * @return string
193
     */
194 2
    public function getLogUid()
195
    {
196 2
        return $this->uuid->getUid();
197
    }
198
199
    /**
200
     * @return string
201
     */
202 2
    public static function getUid()
203
    {
204 2
        return self::getInstance()->getLogUid();
205
    }
206
}
207