diff --git a/src/DefaultSignatureGenerator.php b/src/DefaultSignatureGenerator.php index acc0939..d17adc6 100644 --- a/src/DefaultSignatureGenerator.php +++ b/src/DefaultSignatureGenerator.php @@ -15,7 +15,7 @@ public function generate(LogRecord $record): string { $exception = $record->context['exception'] ?? null; - if (!$exception instanceof Throwable) { + if (! $exception instanceof Throwable) { return $this->generateFromMessage($record); } @@ -27,7 +27,7 @@ public function generate(LogRecord $record): string */ private function generateFromMessage(LogRecord $record): string { - return md5($record->message . json_encode($record->context)); + return md5($record->message.json_encode($record->context)); } /** @@ -36,13 +36,13 @@ private function generateFromMessage(LogRecord $record): string private function generateFromException(Throwable $exception): string { $trace = $exception->getTrace(); - $firstFrame = !empty($trace) ? $trace[0] : null; + $firstFrame = ! empty($trace) ? $trace[0] : null; return md5(implode(':', [ $exception::class, $exception->getFile(), $exception->getLine(), - $firstFrame ? ($firstFrame['file'] ?? '') . ':' . ($firstFrame['line'] ?? '') : '', + $firstFrame ? ($firstFrame['file'] ?? '').':'.($firstFrame['line'] ?? '') : '', ])); } } diff --git a/src/Formatters/GithubIssueFormatter.php b/src/Formatters/GithubIssueFormatter.php index 1f5827f..b683530 100644 --- a/src/Formatters/GithubIssueFormatter.php +++ b/src/Formatters/GithubIssueFormatter.php @@ -54,7 +54,7 @@ public function formatBatch(array $records): array private function generateSignature(LogRecord $record, ?Throwable $exception): string { if (! $exception) { - return md5($record->message . json_encode($record->context)); + return md5($record->message.json_encode($record->context)); } $trace = $exception->getTrace(); @@ -64,7 +64,7 @@ private function generateSignature(LogRecord $record, ?Throwable $exception): st $exception::class, $exception->getFile(), $exception->getLine(), - $firstFrame ? ($firstFrame['file'] ?? '') . ':' . ($firstFrame['line'] ?? '') : '', + $firstFrame ? ($firstFrame['file'] ?? '').':'.($firstFrame['line'] ?? '') : '', ])); } @@ -110,7 +110,7 @@ private function formatTitle(LogRecord $record, ?Throwable $exception = null): s private function formatContent(LogRecord $record, ?Throwable $exception): string { return Str::of('') - ->when($record->message, fn($str, $message) => $str->append("**Message:**\n{$message}\n\n")) + ->when($record->message, fn ($str, $message) => $str->append("**Message:**\n{$message}\n\n")) ->when( $exception, function (Stringable $str, Throwable $exception) { @@ -120,8 +120,8 @@ function (Stringable $str, Throwable $exception) { ); } ) - ->when(! $exception && ! empty($record->context), fn($str, $context) => $str->append("**Context:**\n```json\n" . json_encode($record->context, JSON_PRETTY_PRINT) . "\n```\n\n")) - ->when(! empty($record->extra), fn($str, $extra) => $str->append("**Extra Data:**\n```json\n" . json_encode($record->extra, JSON_PRETTY_PRINT) . "\n```\n")) + ->when(! $exception && ! empty($record->context), fn ($str, $context) => $str->append("**Context:**\n```json\n".json_encode($record->context, JSON_PRETTY_PRINT)."\n```\n\n")) + ->when(! empty($record->extra), fn ($str, $extra) => $str->append("**Extra Data:**\n```json\n".json_encode($record->extra, JSON_PRETTY_PRINT)."\n```\n")) ->toString(); } @@ -141,7 +141,7 @@ private function formatBody(LogRecord $record, string $signature, ?Throwable $ex private function cleanStackTrace(string $stackTrace): string { return collect(explode("\n", $stackTrace)) - ->filter(fn($line) => ! empty(trim($line))) + ->filter(fn ($line) => ! empty(trim($line))) ->map(function ($line) { if (trim($line) === '"}') { return ''; @@ -217,8 +217,8 @@ private function formatExceptionDetails(Throwable $exception): array return [ 'message' => $exception->getMessage(), - 'stack_trace' => $header . "\n[stacktrace]\n" . $this->cleanStackTrace($exception->getTraceAsString()), - 'full_stack_trace' => $header . "\n[stacktrace]\n" . $exception->getTraceAsString(), + 'stack_trace' => $header."\n[stacktrace]\n".$this->cleanStackTrace($exception->getTraceAsString()), + 'full_stack_trace' => $header."\n[stacktrace]\n".$exception->getTraceAsString(), ]; } diff --git a/src/GithubIssueHandlerFactory.php b/src/GithubIssueHandlerFactory.php index 149e025..4f45389 100644 --- a/src/GithubIssueHandlerFactory.php +++ b/src/GithubIssueHandlerFactory.php @@ -8,8 +8,8 @@ use Monolog\Level; use Monolog\Logger; use Naoray\LaravelGithubMonolog\Formatters\GithubIssueFormatter; -use Naoray\LaravelGithubMonolog\Handlers\SignatureDeduplicationHandler; use Naoray\LaravelGithubMonolog\Handlers\IssueLogHandler; +use Naoray\LaravelGithubMonolog\Handlers\SignatureDeduplicationHandler; class GithubIssueHandlerFactory { diff --git a/src/Handlers/IssueLogHandler.php b/src/Handlers/IssueLogHandler.php index 5687ec3..d3fa388 100644 --- a/src/Handlers/IssueLogHandler.php +++ b/src/Handlers/IssueLogHandler.php @@ -11,8 +11,11 @@ class IssueLogHandler extends AbstractProcessingHandler { private string $repo; + private string $token; + private array $labels; + private const DEFAULT_LABEL = 'github-issue-logger'; /** @@ -64,11 +67,11 @@ private function findExistingIssue(string $signature): ?array { $response = Http::withToken($this->token) ->get('https://api.github.com/search/issues', [ - 'q' => "repo:{$this->repo} is:issue is:open label:" . self::DEFAULT_LABEL . " \"Signature: {$signature}\"", + 'q' => "repo:{$this->repo} is:issue is:open label:".self::DEFAULT_LABEL." \"Signature: {$signature}\"", ]); if ($response->failed()) { - throw new \RuntimeException('Failed to search GitHub issues: ' . $response->body()); + throw new \RuntimeException('Failed to search GitHub issues: '.$response->body()); } return $response->json('items.0', null); @@ -85,7 +88,7 @@ private function commentOnIssue(int $issueNumber, GithubIssueFormatted $formatte ]); if ($response->failed()) { - throw new \RuntimeException('Failed to comment on GitHub issue: ' . $response->body()); + throw new \RuntimeException('Failed to comment on GitHub issue: '.$response->body()); } } @@ -102,7 +105,7 @@ private function createIssue(GithubIssueFormatted $formatted): void ]); if ($response->failed()) { - throw new \RuntimeException('Failed to create GitHub issue: ' . $response->body()); + throw new \RuntimeException('Failed to create GitHub issue: '.$response->body()); } } } diff --git a/src/Handlers/SignatureDeduplicationHandler.php b/src/Handlers/SignatureDeduplicationHandler.php index 1cea8e0..5aa8c3c 100644 --- a/src/Handlers/SignatureDeduplicationHandler.php +++ b/src/Handlers/SignatureDeduplicationHandler.php @@ -22,7 +22,7 @@ public function __construct( ?SignatureGenerator $signatureGenerator = null, ) { parent::__construct($handler, $deduplicationStore, $deduplicationLevel, $time, $bubble); - $this->signatureGenerator = $signatureGenerator ?? new DefaultSignatureGenerator(); + $this->signatureGenerator = $signatureGenerator ?? new DefaultSignatureGenerator; } /** @@ -49,6 +49,6 @@ protected function isDuplicate(array $store, LogRecord $record): bool */ protected function buildDeduplicationStoreEntry(LogRecord $record): string { - return $record->datetime->getTimestamp() . ':' . $this->signatureGenerator->generate($record); + return $record->datetime->getTimestamp().':'.$this->signatureGenerator->generate($record); } } diff --git a/tests/DefaultSignatureGeneratorTest.php b/tests/DefaultSignatureGeneratorTest.php index 1f9851c..b52481a 100644 --- a/tests/DefaultSignatureGeneratorTest.php +++ b/tests/DefaultSignatureGeneratorTest.php @@ -5,12 +5,12 @@ use Naoray\LaravelGithubMonolog\DefaultSignatureGenerator; beforeEach(function () { - $this->generator = new DefaultSignatureGenerator(); + $this->generator = new DefaultSignatureGenerator; }); test('generates signature from message', function () { $record = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'test', level: Level::Error, message: 'Test message', @@ -23,7 +23,7 @@ // Same message and context should generate same signature $record2 = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'different-channel', level: Level::Warning, message: 'Test message', @@ -35,7 +35,7 @@ // Different message should generate different signature $record3 = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'test', level: Level::Error, message: 'Different message', @@ -49,7 +49,7 @@ test('generates signature from exception', function () { $exception = new \Exception('Test exception'); $record = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'test', level: Level::Error, message: 'Test message', @@ -62,7 +62,7 @@ // Same exception should generate same signature $record2 = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'different-channel', level: Level::Warning, message: 'Different message', @@ -75,7 +75,7 @@ // Different exception should generate different signature $differentException = new \Exception('Different exception'); $record3 = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'test', level: Level::Error, message: 'Test message', diff --git a/tests/GithubIssueHandlerFactoryTest.php b/tests/GithubIssueHandlerFactoryTest.php index 3e5fbb6..a260aa0 100644 --- a/tests/GithubIssueHandlerFactoryTest.php +++ b/tests/GithubIssueHandlerFactoryTest.php @@ -50,10 +50,10 @@ function getDeduplicationStore(DeduplicationHandler $handler): string test('it throws exception for missing required config', function () { $factory = new GithubIssueHandlerFactory; - expect(fn() => $factory([])) + expect(fn () => $factory([])) ->toThrow(InvalidArgumentException::class, 'GitHub repository is required'); - expect(fn() => $factory(['repo' => 'test/repo'])) + expect(fn () => $factory(['repo' => 'test/repo'])) ->toThrow(InvalidArgumentException::class, 'GitHub token is required'); }); diff --git a/tests/Handlers/IssueLogHandlerTest.php b/tests/Handlers/IssueLogHandlerTest.php index 114e576..8ffd4e3 100644 --- a/tests/Handlers/IssueLogHandlerTest.php +++ b/tests/Handlers/IssueLogHandlerTest.php @@ -81,7 +81,7 @@ function createFormattedRecord(IssueLogHandler $handler, string $message = 'Test 'github.com/search/issues*' => Http::response(['message' => 'Bad credentials'], 401), ]); - expect(fn() => $this->handler->handle(createFormattedRecord($this->handler))) + expect(fn () => $this->handler->handle(createFormattedRecord($this->handler))) ->toThrow(\RuntimeException::class, 'Failed to search GitHub issues'); }); @@ -214,7 +214,7 @@ function createFormattedRecord(IssueLogHandler $handler, string $message = 'Test $record = createFormattedRecord($this->handler); - expect(fn() => $this->handler->handle($record)) + expect(fn () => $this->handler->handle($record)) ->toThrow(\RuntimeException::class, 'Failed to create GitHub issue'); }); diff --git a/tests/Handlers/SignatureDeduplicationHandlerTest.php b/tests/Handlers/SignatureDeduplicationHandlerTest.php index be0ae6a..251d138 100644 --- a/tests/Handlers/SignatureDeduplicationHandlerTest.php +++ b/tests/Handlers/SignatureDeduplicationHandlerTest.php @@ -7,10 +7,10 @@ use Naoray\LaravelGithubMonolog\Handlers\SignatureDeduplicationHandler; beforeEach(function () { - $this->deduplicationStore = sys_get_temp_dir() . '/test-dedup-' . uniqid() . '.log'; - $this->signatureGenerator = new DefaultSignatureGenerator(); + $this->deduplicationStore = sys_get_temp_dir().'/test-dedup-'.uniqid().'.log'; + $this->signatureGenerator = new DefaultSignatureGenerator; $this->handler = new SignatureDeduplicationHandler( - new NullHandler(), + new NullHandler, $this->deduplicationStore, Level::Debug, time: 60, @@ -26,7 +26,7 @@ test('deduplicates records with same signature', function () { $record1 = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'test', level: Level::Error, message: 'Test message', @@ -41,7 +41,7 @@ // Same signature should be deduplicated $record2 = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'different-channel', level: Level::Error, message: 'Test message', @@ -53,7 +53,7 @@ // Different signature should not be deduplicated $record3 = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'test', level: Level::Error, message: 'Different message', @@ -72,7 +72,7 @@ test('deduplication respects time window', function () { $record = new LogRecord( - datetime: new \DateTimeImmutable(), + datetime: new \DateTimeImmutable, channel: 'test', level: Level::Error, message: 'Test message', @@ -82,7 +82,7 @@ // Create handler with 1 second time window $handler = new SignatureDeduplicationHandler( - new NullHandler(), + new NullHandler, $this->deduplicationStore, Level::Debug, time: 1,