Passed
Pull Request — master (#793)
by Def
13:43
created

DbLogger::log()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 1
b 0
f 0
nc 8
nop 2
dl 0
loc 12
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Logger;
6
7
use Psr\Log\LoggerInterface as PsrLoggerInterface;
8
use Psr\Log\LogLevel;
9
use Throwable;
10
use Yiisoft\Db\Exception\NotSupportedException;
11
use Yiisoft\Db\Logger\Context\ConnectionContext;
12
use Yiisoft\Db\Logger\Context\QueryContext;
13
use Yiisoft\Db\Logger\Context\TransactionContext;
14
15
class DbLogger implements DbLoggerInterface
16
{
17
18
    private const DEFAULT_LOG_LEVEL = LogLevel::DEBUG;
19
20
    private static array $LOG_LEVELS = [
21
        DbLoggerEvent::CONNECTION_BEGIN => LogLevel::INFO,
22
        DbLoggerEvent::CONNECTION_END => LogLevel::DEBUG,
23
        DbLoggerEvent::CONNECTION_ERROR => LogLevel::ERROR,
24
25
        DbLoggerEvent::TRANSACTION_BEGIN_TRANS => LogLevel::DEBUG,
26
        DbLoggerEvent::TRANSACTION_BEGIN_SAVEPOINT => LogLevel::DEBUG,
27
        DbLoggerEvent::TRANSACTION_BEGIN_NESTED_ERROR => LogLevel::DEBUG,
28
29
        DbLoggerEvent::TRANSACTION_COMMIT => LogLevel::DEBUG,
30
        DbLoggerEvent::TRANSACTION_RELEASE_SAVEPOINT => LogLevel::DEBUG,
31
        DbLoggerEvent::TRANSACTION_COMMIT_NESTED_ERROR => LogLevel::INFO,
32
33
        DbLoggerEvent::TRANSACTION_ROLLBACK => LogLevel::INFO,
34
        DbLoggerEvent::TRANSACTION_ROLLBACK_SAVEPOINT => LogLevel::DEBUG,
35
        DbLoggerEvent::TRANSACTION_ROLLBACK_NESTED_ERROR => LogLevel::INFO,
36
37
        DbLoggerEvent::TRANSACTION_SET_ISOLATION_LEVEL => LogLevel::DEBUG,
38
        DbLoggerEvent::TRANSACTION_ROLLBACK_ON_LEVEL => LogLevel::ERROR,
39
40
        DbLoggerEvent::QUERY => LogLevel::INFO,
41
    ];
42
43
    public function __construct(protected PsrLoggerInterface $logger)
44
    {
45
    }
46
47
    public function log(string $logEvent, ContextInterface $context): void
48
    {
49
        if ($context instanceof ConnectionContext) {
50
            $this->logConnection($logEvent, $context->getMethodName(), $context->getDsn());
51
        }
52
53
        if ($context instanceof TransactionContext) {
54
            $this->logTransaction($logEvent, $context->getIsolationLevel(), $context->getLevel(), $context->getMethodName(), $context->getException());
55
        }
56
57
        if ($context instanceof QueryContext) {
58
            $this->logger->log(self::$LOG_LEVELS[$logEvent] ?? self::DEFAULT_LOG_LEVEL, $context->getRawSql(), [$context->getCategory()]);
59
        }
60
    }
61
62
    public function setLevel(string $logEvent, string $level): void
63
    {
64
        self::$LOG_LEVELS[$logEvent] = $level;
65
    }
66
67
    private function logConnection(string $logEvent, string $methodName, string $dsn): void
68
    {
69
        $logLevel = self::$LOG_LEVELS[$logEvent] ?? self::DEFAULT_LOG_LEVEL;
70
        $message = match ($logEvent) {
71
            DbLoggerEvent::CONNECTION_BEGIN, DbLoggerEvent::CONNECTION_ERROR =>
72
                'Opening DB connection: ' . $dsn,
73
            DbLoggerEvent::CONNECTION_END => 'Closing DB connection: ' . $dsn . ' ' . $methodName,
74
        };
75
        $this->logger->log($logLevel, $message);
76
    }
77
78
    private function logTransaction(string $logType, string|null $isolationLevel, int $level, string $methodName, ?Throwable $exception = null): void
79
    {
80
        $logLevel = self::$LOG_LEVELS[$logType] ?? self::DEFAULT_LOG_LEVEL;
81
82
        if ($logType === DbLoggerEvent::TRANSACTION_ROLLBACK_ON_LEVEL) {
83
            $this->logger->log($logLevel, (string)$exception, [$methodName]);
84
            return;
85
        }
86
87
        $message = match ($logType) {
88
            DbLoggerEvent::TRANSACTION_BEGIN_TRANS => 'Begin transaction' . ($isolationLevel ? ' with isolation level ' . $isolationLevel : '') . ' ' . $methodName,
89
            DbLoggerEvent::TRANSACTION_BEGIN_SAVEPOINT => 'Set savepoint ' . $level . ' ' . $methodName,
90
            DbLoggerEvent::TRANSACTION_BEGIN_NESTED_ERROR => 'Transaction not started: nested transaction not supported ' . $methodName,
91
92
            DbLoggerEvent::TRANSACTION_COMMIT => 'Commit transaction ' . $methodName,
93
            DbLoggerEvent::TRANSACTION_RELEASE_SAVEPOINT => 'Release savepoint ' . $level . ' ' . $methodName,
94
            DbLoggerEvent::TRANSACTION_COMMIT_NESTED_ERROR => 'Transaction not committed: nested transaction not supported ' . $methodName,
95
96
            DbLoggerEvent::TRANSACTION_ROLLBACK => 'Roll back transaction ' . $methodName,
97
            DbLoggerEvent::TRANSACTION_ROLLBACK_SAVEPOINT => 'Roll back to savepoint ' . $level . ' ' . $methodName,
98
            DbLoggerEvent::TRANSACTION_ROLLBACK_NESTED_ERROR => 'Transaction not rolled back: nested transaction not supported ' . $methodName,
99
100
            DbLoggerEvent::TRANSACTION_SET_ISOLATION_LEVEL => 'Setting transaction isolation level to ' . $level . ' ' . $methodName,
101
        };
102
        $this->logger->log($logLevel, $message);
103
    }
104
}
105