StandardLogFormatter::logResponseCode()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace VM\RequestLogger\Services;
6
7
use Error;
8
use Exception;
9
use Psr\Http\Message\ResponseInterface as Response;
10
use Psr\Http\Message\ServerRequestInterface as Request;
11
use Psr\Http\Message\StreamInterface as Body;
12
use Psr\Http\Message\UriInterface as Uri;
13
use Psr\Log\LoggerInterface;
14
use Throwable;
15
use VM\RequestLogger\Interfaces\LogMessageFormatter;
16
17
class StandardLogFormatter implements LogMessageFormatter
18
{
19
    public const MESSAGE_ERROR = 1;
20
    public const MESSAGE_ERROR_TRACE = 2;
21
    public const MESSAGE_EXCEPTION = 4;
22
    public const MESSAGE_EXCEPTION_TRACE = 8;
23
    public const MESSAGE_REQUEST_URI = 16;
24
    public const MESSAGE_REQUEST_BODY = 32;
25
    public const MESSAGE_REQUEST_HEADERS = 64;
26
    public const MESSAGE_RESPONSE_CODE = 128;
27
    public const MESSAGE_RESPONSE_BODY = 256;
28
    public const MESSAGE_RESPONSE_HEADERS = 512;
29
30
    private $logger;
31
    private $logLevel;
32
    private $logLevelMappings;
33
34 7
    public function __construct(
35
        LoggerInterface $logger,
36
        ?LogLevel $logLevel = null,
37
        $logLevelMappings = []
38
    ) {
39 7
        $this->logger = $logger;
40 7
        $this->logLevel = $logLevel ?? new LogLevel(LogLevel::LEVEL_NOTICE);
41
42
        $defaultLogLevelMappings = [
43 7
            self::MESSAGE_ERROR => new LogLevel(LogLevel::LEVEL_CRITICAL),
44 7
            self::MESSAGE_ERROR_TRACE => new LogLevel(LogLevel::LEVEL_ERROR),
45 7
            self::MESSAGE_EXCEPTION => new LogLevel(LogLevel::LEVEL_CRITICAL),
46 7
            self::MESSAGE_EXCEPTION_TRACE => new LogLevel(LogLevel::LEVEL_ERROR),
47 7
            self::MESSAGE_REQUEST_URI => new LogLevel(LogLevel::LEVEL_NOTICE),
48 7
            self::MESSAGE_REQUEST_BODY => new LogLevel(LogLevel::LEVEL_DEBUG),
49 7
            self::MESSAGE_REQUEST_HEADERS => new LogLevel(LogLevel::LEVEL_INFO),
50 7
            self::MESSAGE_RESPONSE_CODE => new LogLevel(LogLevel::LEVEL_NOTICE),
51 7
            self::MESSAGE_RESPONSE_BODY => new LogLevel(LogLevel::LEVEL_DEBUG),
52 7
            self::MESSAGE_RESPONSE_HEADERS => new LogLevel(LogLevel::LEVEL_INFO),
53
        ];
54 7
        $this->logLevelMappings = array_replace_recursive($defaultLogLevelMappings, $logLevelMappings);
55 7
    }
56
57 3
    public function logError(Error $e): void
58
    {
59 3
        $this->logErrorMessage($e, self::MESSAGE_ERROR);
60 3
        $this->logTrace($e, self::MESSAGE_ERROR_TRACE);
61 3
    }
62
63 1
    public function logException(Exception $e): void
64
    {
65 1
        $this->logErrorMessage($e, self::MESSAGE_EXCEPTION);
66 1
        $this->logTrace($e, self::MESSAGE_EXCEPTION_TRACE);
67 1
    }
68
69 1
    public function logRequest(Request $request): void
70
    {
71 1
        $this->logRequestUri($request->getUri());
72 1
        $this->logRequestHeaders($request->getHeaders());
73 1
        $this->logRequestBody($request->getBody());
74 1
    }
75
76 1
    public function logResponse(Response $response): void
77
    {
78 1
        $this->logResponseCode($response->getStatusCode());
79 1
        $this->logResponseHeaders($response->getHeaders());
80 1
        $this->logResponseBody($response->getBody());
81 1
    }
82
83 1
    private function logRequestBody(Body $body): void
84
    {
85 1
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[self::MESSAGE_REQUEST_BODY])) {
86 1
            $this->logAs(self::MESSAGE_REQUEST_BODY, "request-body: {$body->__toString()}");
87
        }
88 1
    }
89
90 1
    private function logRequestHeaders(array $headers): void
91
    {
92 1
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[self::MESSAGE_REQUEST_HEADERS])) {
93 1
            $this->logAs(self::MESSAGE_REQUEST_HEADERS, "request-headers: {$this->escapeArray($headers)}");
94
        }
95 1
    }
96
97 1
    private function logRequestUri(Uri $uri): void
98
    {
99 1
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[self::MESSAGE_REQUEST_URI])) {
100 1
            $host = $uri->getHost();
101 1
            $path = $uri->getPath();
102 1
            $queryString = $uri->getQuery();
103 1
            if (!empty($queryString)) {
104 1
                $path .= '?' . $uri->getQuery();
105
            }
106 1
            $time = (new \DateTime())->format(\DateTime::ISO8601);
107 1
            $this->logAs(self::MESSAGE_REQUEST_URI, "[{$time}][{$host}]: {$path}");
108
        }
109 1
    }
110
111 1
    private function logResponseCode(int $code): void
112
    {
113 1
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[self::MESSAGE_RESPONSE_CODE])) {
114 1
            $this->logAs(self::MESSAGE_RESPONSE_CODE, "response-code: {$code}");
115
        }
116 1
    }
117
118 1
    private function logResponseBody(Body $body): void
119
    {
120 1
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[self::MESSAGE_RESPONSE_BODY])) {
121 1
            $this->logAs(self::MESSAGE_RESPONSE_BODY, "response-body: {$body->__toString()}");
122
        }
123 1
    }
124
125 1
    private function logResponseHeaders(array $headers): void
126
    {
127 1
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[self::MESSAGE_RESPONSE_HEADERS])) {
128 1
            $this->logAs(self::MESSAGE_RESPONSE_HEADERS, "response-headers: {$this->escapeArray($headers)}");
129
        }
130 1
    }
131
132 4
    private function logErrorMessage(Throwable $e, int $type): void
133
    {
134 4
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[$type])) {
135 3
            $this->logAs(self::MESSAGE_ERROR, "RequestLogger caught " . get_class($e) . ": {$e->getMessage()}");
136
        }
137 4
    }
138
139 4
    private function logTrace(Throwable $e, int $type): void
140
    {
141 4
        if ($this->logLevel->shouldLogFor($this->logLevelMappings[$type])) {
142 2
            $this->logAs(self::MESSAGE_ERROR_TRACE, "trace:\n" . $e->getTraceAsString());
143
        }
144 4
    }
145
146 5
    private function logAs(int $logType, string $contents): void
147
    {
148 5
        $logHandler = $this->logLevelMappings[$logType]->toString();
149 5
        $this->logger->$logHandler($contents);
150 5
    }
151
152 2
    private function escapeArray(array $data): string
153
    {
154 2
        return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
155
    }
156
}
157