Test Failed
Push — master ( 25ac3b...786715 )
by Fran
02:38
created

Logger::addAwsStreamHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 14
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 19
ccs 0
cts 18
cp 0
crap 2
rs 9.7998
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\SlackHelper;
17
use PSFS\base\types\traits\SingletonTrait;
18
19
20
if (!defined('LOG_DIR')) {
21
    GeneratorHelper::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
22
    define('LOG_DIR', BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
23
}
24
25
/**
26
 * Class Logger
27
 * @package PSFS\base
28
 * Servicio de log
29
 */
30
class Logger
31
{
32
    const DEFAULT_NAMESPACE = 'PSFS';
33
    use SingletonTrait;
34
35
    /**
36
     * @var \Monolog\Logger
37
     */
38
    protected \Monolog\Logger $logger;
39
    /**
40
     * @var resource
41
     */
42
    private $stream;
43
    /**
44
     * @var UidProcessor
45
     */
46
    private $uuid;
47
    /**
48
     * @var string
49
     */
50
    protected string $logLevel;
51
52
    /**
53
     * Logger constructor.
54
     * @throws GeneratorException
55
     * @throws ConfigException
56
     * @throws \Exception
57
     */
58 1
    public function __construct()
59
    {
60 1
        $args = func_get_args();
61 1
        list($logger, $debug, $path) = $this->setup($args);
62 1
        $this->stream = fopen($path . DIRECTORY_SEPARATOR . date('Ymd') . '.log', 'ab+');
63 1
        if (false !== $this->stream && is_resource($this->stream)) {
64 1
            $this->addPushLogger($logger, $debug);
65
        } else {
66
            throw new ConfigException(t('Error creating logger'));
67
        }
68 1
        $this->logLevel = strtoupper(Config::getParam('log.level', 'NOTICE'));
69
    }
70
71 1
    public function __destruct()
72
    {
73 1
        fclose($this->stream);
74
    }
75
76
    /**
77
     * @param string $logger
78
     * @param boolean $debug
79
     * @throws \Exception
80
     */
81 1
    private function addPushLogger(string $logger, bool $debug): void
82
    {
83 1
        $this->logger = new \Monolog\Logger(strtoupper($logger));
84 1
        $this->logger->pushHandler($this->addDefaultStreamHandler($debug));
85 1
        if ($debug) {
86 1
            $phpFireLog = Config::getParam('logger.phpFire');
87 1
            if (!empty($phpFireLog)) {
88 1
                $this->logger->pushHandler(new FirePHPHandler());
89
            }
90 1
            $memoryLog = Config::getParam('logger.memory');
91 1
            if (!empty($memoryLog)) {
92 1
                $this->logger->pushProcessor(new MemoryUsageProcessor());
93
            }
94
        }
95 1
        $this->uuid = new UidProcessor();
96 1
        $this->logger->pushProcessor($this->uuid);
97
    }
98
99
    /**
100
     * @param array $args
101
     * @return array
102
     * @throws exception\GeneratorException
103
     */
104 1
    private function setup(array $args = []): array
105
    {
106 1
        $args = $args ?? [];
107 1
        $debug = Config::getParam('debug');
108 1
        $namespace = self::DEFAULT_NAMESPACE;
109 1
        if (0 !== count($args)) {
110 1
            $namespace = $args[0][0] ?? 'PSFS';
111 1
            $debug = $args[0][1] ?? true;
112
        }
113 1
        $path = $this->createLoggerPath();
114 1
        return [$this->cleanLoggerName($namespace), $debug, $path];
115
    }
116
117
    /**
118
     * @return string
119
     */
120 1
    private function setLoggerName(): string
121
    {
122 1
        $logger = Config::getParam('platform.name', self::DEFAULT_NAMESPACE);
123 1
        return $this->cleanLoggerName($logger);
124
    }
125
126
    /**
127
     * @param $logger
128
     *
129
     * @return mixed
130
     */
131 1
    private function cleanLoggerName($logger): mixed
132
    {
133 1
        $logger = str_replace(' ', '', $logger);
134 1
        return preg_replace("/\\\\/", ".", $logger);
135
    }
136
137
    /**
138
     * @return string
139
     * @throws exception\GeneratorException
140
     */
141 1
    private function createLoggerPath(): string
142
    {
143 1
        $logger = $this->setLoggerName();
144 1
        $path = Config::getParam('default.log.path', LOG_DIR) . DIRECTORY_SEPARATOR . $logger . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
145 1
        GeneratorHelper::createDir($path);
146 1
        return $path;
147
    }
148
149
    /**
150
     * @param string $msg
151
     * @param \Monolog\Level $type
152
     * @param array $context
153
     * @param boolean $force
154
     * @return bool
155
     */
156 31
    public function addLog(string $msg, \Monolog\Level $type = \Monolog\Level::Notice, array $context = [], bool $force = false)
157
    {
158 31
        return !($this->checkLogLevel($type) || $force) || $this->logger->addRecord($type, $msg, $this->addMinimalContext($context));
159
    }
160
161
    /**
162
     * @param \Monolog\Level $level
163
     * @return bool
164
     */
165 31
    private function checkLogLevel(\Monolog\Level $level = \Monolog\Level::Notice): bool
166
    {
167 31
        switch ($this->logLevel) {
168 31
            case 'DEBUG':
169
                $logPass = \Monolog\Log::Debug;
170
                break;
171 31
            case 'INFO':
172
                $logPass = \Monolog\Level::Info;
173
                break;
174
            default:
175 31
            case 'NOTICE':
176 31
                $logPass = \Monolog\Level::Notice;
177 31
                break;
178
            case 'WARNING':
179
                $logPass = \Monolog\Level::Warning;
180
                break;
181
            case 'ERROR':
182
                $logPass = \Monolog\Level::Error;
183
                break;
184
            case 'EMERGENCY':
185
                $logPass = \Monolog\Level::Emergency;
186
                break;
187
            case 'ALERT':
188
                $logPass = \Monolog\Level::Alert;
189
                break;
190
            case 'CRITICAL':
191
                $logPass = \Monolog\Level::Critical;
192
                break;
193
        }
194 31
        return $logPass <= $level;
195
    }
196
197
    /**
198
     * @param string $msg
199
     * @param int $type
200
     * @param array|null $context
201
     * @param bool $force
202
     */
203 31
    public static function log(string $msg, int $type = LOG_DEBUG, array $context = null, bool $force = false): void
204
    {
205 31
        if (null === $context) {
206 29
            $context = [];
207
        }
208 31
        if (Config::getParam('profiling.enable') && 'DEBUG' === Config::getParam('log.level', 'NOTICE')) {
209
            Inspector::stats($msg, Inspector::SCOPE_DEBUG);
210
        }
211
        switch ($type) {
212 31
            case LOG_DEBUG:
213 29
                self::getInstance()->addLog($msg, \Monolog\Level::Debug, $context, $force);
214 29
                break;
215 12
            case LOG_WARNING:
216 5
                self::getInstance()->addLog($msg, \Monolog\Level::Warning, $context, $force);
217 5
                break;
218 9
            case LOG_CRIT:
219 1
                if (Config::getParam('log.slack.hook')) {
220
                    SlackHelper::getInstance()->trace($msg, '', '', $context);
221
                }
222 1
                self::getInstance()->addLog($msg, \Monolog\Level::Critical, $context, $force);
223 1
                break;
224 9
            case LOG_ERR:
225 5
                self::getInstance()->addLog($msg, \Monolog\Level::Error, $context, $force);
226 5
                break;
227 6
            case LOG_INFO:
228 6
                self::getInstance()->addLog($msg, \Monolog\Level::Info, $context, $force);
229 6
                break;
230 1
            case LOG_EMERG:
231
                self::getInstance()->addLog($msg, \Monolog\Level::Emergency, $context, $force);
232
                break;
233 1
            case LOG_ALERT:
234
                self::getInstance()->addLog($msg, \Monolog\Level::Alert, $context, $force);
235
                break;
236
            default:
237 1
                self::getInstance()->addLog($msg, \Monolog\Level::Notice, $context, $force);
238 1
                break;
239
        }
240
    }
241
242
    /**
243
     * @param bool $debug
244
     * @throws \Exception
245
     */
246
    private function addAwsStreamHandler($debug = false)
0 ignored issues
show
Unused Code introduced by
The method addAwsStreamHandler() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
Unused Code introduced by
The parameter $debug is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

246
    private function addAwsStreamHandler(/** @scrutinizer ignore-unused */ $debug = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
247
    {
248
        $client = new \Aws\CloudWatchLogs\CloudWatchLogsClient([
0 ignored issues
show
Bug introduced by
The type Aws\CloudWatchLogs\CloudWatchLogsClient was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
249
            'region' => Config::getParam('aws.region', 'eu-west-1'),
250
            'version' => Config::getParam('aws.version', 'latest'),
251
            'credentials' => [
252
                'key' => Config::getParam('aws.key', 'your AWS key'),
253
                'secret' => Config::getParam('aws.secret', 'your AWS secret'),
254
            ],
255
        ]);
256
        $stream = new \Maxbanton\Cwh\Handler\CloudWatch(
0 ignored issues
show
Bug introduced by
The type Maxbanton\Cwh\Handler\CloudWatch was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
257
            $client,
258
            Config::getParam('aws.group_name', 'PSFS'),
259
            Config::getParam('platform.name', 'PSFS'),
260
            Config::getParam('aws.retention_days', 30),
261
            10000
262
        );
263
        $stream->setFormatter(new JsonFormatter);
264
        return $stream;
265
    }
266
267
    /**
268
     * @param bool $debug
269
     * @return StreamHandler
270
     * @throws \Exception
271
     */
272 1
    private function addDefaultStreamHandler(bool $debug = false): StreamHandler
273
    {
274
        // the default date format is "Y-m-d H:i:s"
275 1
        $dateFormat = 'Y-m-d H:i:s.u';
276
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
277 1
        $output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n";
278
        // finally, create a formatter
279 1
        $formatter = new LineFormatter($output, $dateFormat);
280 1
        $stream = new StreamHandler($this->stream, $debug ? \Monolog\Level::Debug : \Monolog\Level::Warning);
281 1
        $stream->setFormatter($formatter);
282 1
        return $stream;
283
    }
284
285
    /**
286
     * @param array $context
287
     * @return array
288
     */
289 2
    private function addMinimalContext(array $context = [])
290
    {
291 2
        $context['uri'] = null !== $_SERVER && array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : 'Unknow';
292 2
        $context['method'] = null !== $_SERVER && array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'Unknow';
293 2
        if (null !== $_SERVER && array_key_exists('HTTP_X_PSFS_UID', $_SERVER)) {
294
            $context['uid'] = $_SERVER['HTTP_X_PSFS_UID'];
295
        }
296 2
        return $context;
297
    }
298
299
    /**
300
     * @return string
301
     */
302 2
    public function getLogUid()
303
    {
304 2
        return $this->uuid->getUid();
305
    }
306
307
    /**
308
     * @return string
309
     */
310 2
    public static function getUid()
311
    {
312 2
        return self::getInstance()->getLogUid();
313
    }
314
}
315