Skip to content

Commit e1f5bc4

Browse files
committed
Update SF
1 parent 67c3923 commit e1f5bc4

9 files changed

Lines changed: 160 additions & 260 deletions

File tree

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
"require": {
66
"php": "^8.2",
77
"monolog/monolog": "^3",
8-
"open-telemetry/opentelemetry-logger-monolog": "^1.0"
8+
"open-telemetry/opentelemetry-logger-monolog": "^1.0.0"
99
},
1010
"require-dev": {
1111
"vimeo/psalm": "^5.26.1",
1212
"illuminate/support": "^9.19",
13-
"symfony/http-kernel": "^6.1",
13+
"symfony/http-kernel": "^7.2",
1414
"symfony/dependency-injection": "^6.1",
15-
"symfony/config": "^6.1",
15+
"symfony/config": "^7.2",
1616
"aws/aws-sdk-php": "^3.231",
1717
"guzzlehttp/guzzle": "^7.4"
1818
},
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Gotphoto\Logging;
6+
7+
use Monolog\Formatter\NormalizerFormatter;
8+
9+
/**
10+
* @internal
11+
*/
12+
class ExceptionNormalizerFormatter extends NormalizerFormatter
13+
{
14+
/** @var array<string, array<callable(\Throwable):array<string, array<array-key, string>|int|string>>> */
15+
private readonly array $exceptionContextProviderMap;
16+
17+
/**
18+
* @param array<string, array<callable(\Throwable):array<string, array<array-key, string>|int|string>>> $exceptionContextProviderMap
19+
*/
20+
public function __construct(array $exceptionContextProviderMap = [], ?string $dateFormat = null)
21+
{
22+
$this->exceptionContextProviderMap = $exceptionContextProviderMap;
23+
parent::__construct($dateFormat);
24+
}
25+
26+
protected function normalizeException(\Throwable $e, int $depth = 0): array
27+
{
28+
$data = parent::normalizeException($e, $depth);
29+
30+
$exceptionProviders = $this->getExceptionContexts($e);
31+
32+
foreach ($exceptionProviders as $exceptionProvider) {
33+
$additionalContext = $exceptionProvider($e);
34+
if (!empty($additionalContext) && isset($data['context']) && is_array($data['context'])) {
35+
$data['context'] = ($data['context'] ?? []) + $additionalContext;
36+
}
37+
}
38+
39+
return $data;
40+
}
41+
42+
/**
43+
* @return array<callable(\Throwable):array<string, array<array-key, string>|int|string>>
44+
*/
45+
protected function getExceptionContexts(\Throwable $e): array
46+
{
47+
if (isset($this->exceptionContextProviderMap[\get_class($e)])) {
48+
return $this->exceptionContextProviderMap[\get_class($e)];
49+
}
50+
$exceptionContexts = [];
51+
foreach (array_keys($this->exceptionContextProviderMap) as $className) {
52+
if ($e instanceof $className) {
53+
$exceptionContexts = array_merge($exceptionContexts + $this->exceptionContextProviderMap[$className]);
54+
}
55+
}
56+
57+
return $exceptionContexts;
58+
}
59+
}

src/Formatter.php

Lines changed: 0 additions & 157 deletions
This file was deleted.

src/Laravel/LaravelLoggerCreating.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44

55
namespace Gotphoto\Logging\Laravel;
66

7-
use App\Lib\Log\OtelFormatter;
87
use Aws\Exception\AwsException;
98
use Gotphoto\Logging\ExceptionContext\AwsExceptionContext;
109
use Gotphoto\Logging\ExceptionContext\GuzzleRequestExceptionContext;
11-
use Gotphoto\Logging\Formatter;
12-
use Gotphoto\Logging\NewrelicProcessor;
10+
use Gotphoto\Logging\LogstashFormatter;
1311
use GuzzleHttp\Exception\RequestException;
1412
use Illuminate\Support\Facades\App;
1513
use Monolog\Handler\StreamHandler;
@@ -40,7 +38,6 @@ public function __invoke(array $config)
4038
$stream = $config['stream_to'] ?? 'php://stderr';
4139

4240
$log = new Logger($channel);
43-
$log->pushProcessor(new NewrelicProcessor());
4441
$log->pushProcessor(new PsrLogMessageProcessor());
4542

4643
foreach ($processors as $processor) {
@@ -51,23 +48,25 @@ public function __invoke(array $config)
5148

5249
$handler = $streamHandler;
5350
$env = App::environment();
51+
/** @psalm-suppress MixedArgumentTypeCoercion */
5452
$handler->setFormatter(
55-
new Formatter($appName, (is_string($env) ? $env : "undefined"), array_merge($exceptionContexts, [
53+
new LogstashFormatter($appName, (is_string($env) ? $env : "undefined"), array_merge($exceptionContexts, [
5654
RequestException::class => [new GuzzleRequestExceptionContext()],
5755
AwsException::class => [new AwsExceptionContext()],
58-
]))
56+
])),
5957
);
6058
$log->pushHandler($handler);
6159

6260
$otelHandler = new Handler(
6361
Globals::loggerProvider(),
64-
LogLevel::INFO
62+
LogLevel::INFO,
6563
);
64+
/** @psalm-suppress ArgumentTypeCoercion */
6665
$otelHandler->setFormatter(
6766
new \Gotphoto\Logging\OtelFormatter([
6867
RequestException::class => [new GuzzleRequestExceptionContext()],
6968
AwsException::class => [new AwsExceptionContext()],
70-
])
69+
]),
7170
);
7271
$log->pushHandler($otelHandler);
7372

src/LogstashFormatter.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Gotphoto\Logging;
6+
7+
use Monolog\Formatter\NormalizerFormatter;
8+
use Monolog\LogRecord;
9+
10+
final class LogstashFormatter extends ExceptionNormalizerFormatter
11+
{
12+
/**
13+
* @var string the name of the system for the Logstash log message, used to fill the @source field
14+
*/
15+
protected string $systemName;
16+
17+
/**
18+
* @param string $applicationName the application that sends the data, used as the "type"
19+
* field of logstash
20+
* @param string $environment current environment
21+
* @param string|null $systemName the system/machine name, used as the "source" field of
22+
* logstash, defaults to the hostname of the machine
23+
* @param array<string, array<callable(\Throwable):array<string, array<array-key, string>|int|string>>> $exceptionContextProviderMap
24+
*/
25+
public function __construct(
26+
protected string $applicationName,
27+
protected string $environment,
28+
protected array $exceptionContextProviderMap = [],
29+
?string $systemName = null,
30+
) {
31+
// logstash requires a ISO 8601 format date with optional millisecond precision.
32+
parent::__construct($exceptionContextProviderMap, 'Y-m-d\TH:i:s.uP');
33+
$this->systemName = $systemName === null ? gethostname() : $systemName;
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function format(LogRecord $record): string
40+
{
41+
/** @var array{timestamp: int, datetime: string, extra?:array, context?:array} $data */
42+
$data = parent::format($record);
43+
/** @psalm-suppress RiskyTruthyFalsyComparison this is okay null or empty string */
44+
if (empty($data['datetime'])) {
45+
$data['datetime'] = gmdate('c');
46+
}
47+
$message = [
48+
'@timestamp' => $data['datetime'],
49+
'@version' => 1,
50+
'timestamp' => $data['timestamp'],
51+
'host' => $this->systemName,
52+
'environment' => $this->environment,
53+
];
54+
unset($data['datetime'], $data['timestamp']);
55+
if ($this->applicationName) {
56+
$message['app'] = $this->applicationName;
57+
}
58+
$message += $data;
59+
if (isset($message['extra'])) {
60+
$message['extra'] = (object)$message['extra'];
61+
}
62+
if (isset($message['context'])) {
63+
$message['context'] = (object)$message['context'];
64+
}
65+
66+
return $this->toJson($message) . "\n";
67+
}
68+
69+
public function formatBatch(array $records)
70+
{
71+
/** @var array $records */
72+
$records = parent::formatBatch($records);
73+
74+
return $this->toJson($records, true);
75+
}
76+
}

src/NewrelicProcessor.php

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)