Skip to content

Commit dc4e805

Browse files
author
kEERill
committed
[upd] Добавлено больше гибкости для логирования
1 parent 6dc1e1c commit dc4e805

File tree

7 files changed

+152
-11
lines changed

7 files changed

+152
-11
lines changed

config/kafka-consumer.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
'global_middleware' => [],
55

66
'processors' => [],
7-
7+
8+
'log_channel' => env('KAFKA_CONSUMER_LOG_CHANNEL', 'null'),
9+
810
'consumer_options' => [
911
/** options for consumer with name `default` */
1012
'default' => [
@@ -19,6 +21,6 @@
1921
| Array of middleware.
2022
*/
2123
'middleware' => [],
22-
]
23-
]
24+
],
25+
],
2426
];

src/Commands/KafkaConsumeCommand.php

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
use Ensi\LaravelPhpRdKafka\KafkaFacade;
66
use Ensi\LaravelPhpRdKafkaConsumer\ConsumerOptions;
77
use Ensi\LaravelPhpRdKafkaConsumer\HighLevelConsumer;
8+
use Ensi\LaravelPhpRdKafkaConsumer\Logger\ConsumerLoggerFactory;
9+
use Ensi\LaravelPhpRdKafkaConsumer\Logger\ConsumerLoggerInterface;
810
use Ensi\LaravelPhpRdKafkaConsumer\ProcessorData;
911
use Illuminate\Console\Command;
10-
use Illuminate\Support\Facades\Log;
1112
use Symfony\Component\Console\Command\SignalableCommandInterface;
1213
use Throwable;
1314

@@ -54,29 +55,31 @@ public function handleSignal(int $signal, int|false $previousExitCode = 0): int|
5455
/**
5556
* Execute the console command.
5657
*/
57-
public function handle(HighLevelConsumer $highLevelConsumer): int
58+
public function handle(HighLevelConsumer $highLevelConsumer, ConsumerLoggerFactory $loggerFactory): int
5859
{
5960
$this->consumer = $highLevelConsumer;
6061
$topicKey = $this->argument('topic-key');
6162
$consumer = $this->argument('consumer');
6263

64+
$logger = $loggerFactory->make($topicKey, $consumer);
65+
6366
$processorData = $this->findMatchedProcessor($topicKey, $consumer);
6467
if (is_null($processorData)) {
65-
$this->error("Processor for topic-key \"$topicKey\" and consumer \"$consumer\" is not found");
68+
$this->errorMessage($logger, "Processor for topic-key \"$topicKey\" and consumer \"$consumer\" is not found");
6669
$this->line('Processors are set in /config/kafka-consumer.php');
6770

6871
return 1;
6972
}
7073

7174
if (!class_exists($processorData->class)) {
72-
$this->error("Processor class \"$processorData->class\" is not found");
75+
$this->errorMessage($logger, "Processor class \"$processorData->class\" is not found");
7376
$this->line('Processors are set in /config/kafka-consumer.php');
7477

7578
return 1;
7679
}
7780

7881
if (!$processorData->hasValidType()) {
79-
$this->error("Invalid processor type \"$processorData->type\", supported types are: " . implode(',', $processorData->getSupportedTypes()));
82+
$this->errorMessage($logger, "Invalid processor type \"$processorData->type\", supported types are: " . implode(',', $processorData->getSupportedTypes()));
8083

8184
return 1;
8285
}
@@ -97,9 +100,7 @@ public function handle(HighLevelConsumer $highLevelConsumer): int
97100
->for($consumer)
98101
->listen($topicName, $processorData, $consumerOptions);
99102
} catch (Throwable $e) {
100-
Log::error($e->getMessage(), ['exception' => $e]);
101-
102-
$this->error('An error occurred while listening to the topic: '. $e->getMessage(). ' '. $e->getFile() . '::' . $e->getLine());
103+
$this->errorThrowable($logger, $e);
103104

104105
return 1;
105106
}
@@ -136,4 +137,16 @@ protected function collectMiddleware(array $processorMiddleware): array
136137
)
137138
);
138139
}
140+
141+
private function errorThrowable(ConsumerLoggerInterface $logger, Throwable $e): void
142+
{
143+
$logger->error($e->getMessage(), ['exception' => $e]);
144+
$this->error('An error occurred while listening to the topic: '. $e->getMessage(). ' '. $e->getFile() . '::' . $e->getLine());
145+
}
146+
147+
private function errorMessage(ConsumerLoggerInterface $logger, string $message): void
148+
{
149+
$logger->error($message);
150+
$this->error($message);
151+
}
139152
}

src/Logger/ConsumerLogger.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Ensi\LaravelPhpRdKafkaConsumer\Logger;
4+
5+
use Psr\Log\AbstractLogger;
6+
use Psr\Log\LoggerInterface;
7+
use Stringable;
8+
9+
final class ConsumerLogger extends AbstractLogger implements ConsumerLoggerInterface
10+
{
11+
public function __construct(
12+
protected LoggerInterface $logger,
13+
protected string $topicKey,
14+
protected string $consumer,
15+
) {
16+
}
17+
18+
public function getTopicKey(): string
19+
{
20+
return $this->topicKey;
21+
}
22+
23+
public function getConsumer(): string
24+
{
25+
return $this->consumer;
26+
}
27+
28+
public function getLogger(): LoggerInterface
29+
{
30+
return $this->logger;
31+
}
32+
33+
public function log($level, Stringable|string $message, array $context = []): void
34+
{
35+
$context = array_merge($context, [
36+
'topic_key' => $this->topicKey,
37+
'consumer' => $this->consumer,
38+
]);
39+
40+
$this->logger->log($level, $message, $context);
41+
}
42+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Ensi\LaravelPhpRdKafkaConsumer\Logger;
4+
5+
use Illuminate\Support\Facades\Log;
6+
use Psr\Log\LoggerInterface;
7+
use Psr\Log\NullLogger;
8+
9+
final class ConsumerLoggerFactory
10+
{
11+
public function make(string $topicKey, string $consumer): ConsumerLoggerInterface
12+
{
13+
return new ConsumerLogger(
14+
$this->makeLogger(),
15+
$topicKey,
16+
$consumer
17+
);
18+
}
19+
20+
private function makeLogger(): LoggerInterface
21+
{
22+
$channel = config('kafka-consumer.log_channel', 'null');
23+
24+
if (empty($channel) || $channel == 'null') {
25+
return new NullLogger();
26+
}
27+
28+
return Log::channel($channel);
29+
}
30+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Ensi\LaravelPhpRdKafkaConsumer\Logger;
4+
5+
use Psr\Log\LoggerInterface;
6+
7+
interface ConsumerLoggerInterface extends LoggerInterface
8+
{
9+
public function getLogger(): LoggerInterface;
10+
11+
public function getTopicKey(): string;
12+
13+
public function getConsumer(): string;
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
use Ensi\LaravelPhpRdKafkaConsumer\Logger\ConsumerLoggerFactory;
4+
use Psr\Log\NullLogger;
5+
6+
test('test create consumer logger from factory', function (?string $channel) {
7+
config()->set('kafka-consumer.log_channel', $channel);
8+
9+
$consumerLogger = (new ConsumerLoggerFactory())
10+
->make('products', 'default');
11+
12+
expect($consumerLogger->getLogger())
13+
->toBeInstanceOf(NullLogger::class)
14+
->and($consumerLogger->getTopicKey())
15+
->toBe('products')
16+
->and($consumerLogger->getConsumer())
17+
->toBe('default');
18+
})->with([null, 'null']);

tests/ConsumerLoggerTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
use _PHPStan_01e5828ef\Psr\Log\LogLevel;
4+
use Ensi\LaravelPhpRdKafkaConsumer\Logger\ConsumerLogger;
5+
use Psr\Log\NullLogger;
6+
7+
test('merging context when call log', function () {
8+
$logger = mock(NullLogger::class)
9+
->makePartial();
10+
11+
$consumerLogger = new ConsumerLogger($logger, 'products', 'default');
12+
$consumerLogger->log(LogLevel::NOTICE, 'Test message', ['foo' => 'bar']);
13+
14+
$logger->shouldHaveReceived('log', function ($level, $message, array $context = []) {
15+
return $level == LogLevel::NOTICE
16+
&& $message === 'Test message'
17+
&& count($context) == 3
18+
&& $context['topic_key'] === 'products'
19+
&& $context['consumer'] === 'default'
20+
&& $context['foo'] == 'bar';
21+
});
22+
});

0 commit comments

Comments
 (0)