Passed
Pull Request — master (#9)
by
unknown
02:05
created

PsrSqlLogger::getLoggerCallable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Abacaphiliac\Doctrine;
4
5
use Doctrine\DBAL\Logging\SQLLogger;
6
use Psr\Log\LoggerInterface;
7
use Psr\Log\LogLevel;
8
9
class PsrSqlLogger implements SQLLogger
10
{
11
    /** @var LoggerInterface */
12
    private $logger;
13
14
    /** @var float */
15
    private $start;
16
17
    /** @var callable */
18
    private $startQueryCallable;
19
20
    /** @var string */
21
    private $queryId;
22
23
    /** @var string */
24
    private $defaultLogLevel;
25
26
    /** @var array|null */
27
    private $logLevelMapping;
28
29 7
    public function __construct(LoggerInterface $logger, string $defaultLogLevel = LogLevel::INFO, array $logLevelMapping = null)
30
    {
31 7
        $this->logger = $logger;
32 7
        $this->defaultLogLevel = $defaultLogLevel;
33 7
        $this->logLevelMapping = $logLevelMapping;
34 7
        $this->startQueryCallable = $this->getStartQueryCallable($defaultLogLevel);
35 7
    }
36
37 7
    private function getStartQueryCallable(string $level) : callable
38
    {
39 7
        $callable = $this->getLoggerCallable($level);
40
41 7
        if (!\is_callable($callable)) {
42 1
            throw new \InvalidArgumentException(sprintf(
43 1
                '%s::%s" is not callable',
44 1
                LoggerInterface::class,
45 1
                $this->defaultLogLevel
46
            ));
47
        }
48
49 7
        return $callable;
50
    }
51
52 7
    private function getLoggerCallable(string $level) : array
53
    {
54 7
        return [$this->logger, $level];
55
    }
56
57 6
    public function startQuery($sql, array $params = null, array $types = null)
58
    {
59 6
        $this->queryId = \uniqid('', true);
60
61 6
        $this->start = \microtime(true);
62
63 6
        call_user_func($this->startQueryCallable, 'Query started', \array_merge(
64 6
            $this->getStartQueryContext($sql, $params, $types),
65
            [
66 6
                'query_id' => $this->queryId,
67
            ]
68
        ));
69 6
    }
70
71 6
    protected function getStartQueryContext($sql, array $params = null, array $types = null)
72
    {
73
        return [
74 6
            'sql' => $sql,
75 6
            'types' => $types,
76
        ];
77
    }
78
79 4
    public function stopQuery()
80
    {
81 4
        $stop = \microtime(true);
82 4
        $durationInSeconds = $stop - $this->start;
83
84 4
        \call_user_func($this->getStopQueryCallable($durationInSeconds), 'Query finished', [
85 4
            'query_id' => $this->queryId,
86 4
            'start' => $this->start,
87 4
            'stop' => $stop,
88 4
            'duration_μs' => $durationInSeconds,
89
        ]);
90 4
    }
91
92 4
    private function getStopQueryCallable(float $durationInSeconds): callable
93
    {
94 4
        return $this->getLoggerCallable($this->getApplicableLogLevel($durationInSeconds));
95
    }
96
97 4
    private function getApplicableLogLevel(float $durationInSeconds): string
98
    {
99 4
        return is_array($this->logLevelMapping) ? $this->determineApplicableLogLevel($durationInSeconds) : $this->defaultLogLevel;
100
    }
101
102 1
    private function determineApplicableLogLevel(float $durationInSeconds) : string
103
    {
104 1
        $durationInMilliseconds = $durationInSeconds * 1000;
105 1
        $durations = array_values($this->logLevelMapping); //Acquire a common / non-associative array
106 1
        $durations[] = $durationInMilliseconds; //Append the incoming query duration in milliseconds to the array of duration thresholds
107
108 1
        asort($durations, SORT_NUMERIC); //Sort the array from low to high: the provided duration will end up somewhere between the thresholds
109 1
        $durations = array_values($durations); //A re-index is required after sorting
110
111 1
        $key = array_search($durationInMilliseconds, $durations, true); //Determine at which position the duration ended up after sorting
112
113 1
        $logLevels = array_keys($this->logLevelMapping);
114
115 1
        return $logLevels[$key - 1]; //Now take the "previous" key
116
    }
117
}
118