From 9cecc47b8bce64f31c3b22d2f722a4ee2dcb8aa8 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Tue, 28 Apr 2026 18:47:04 +0200 Subject: [PATCH] 6 - Log structured success entry on PollFediverseAction with url count and duration --- .../src/Actions/PollFediverseAction.php | 48 ++++++++++++------- .../tests/Feature/PollFediverseActionTest.php | 24 ++++++++++ 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/packages/Lvl0/FediDiscover/src/Actions/PollFediverseAction.php b/packages/Lvl0/FediDiscover/src/Actions/PollFediverseAction.php index 11d8767..34cadb5 100644 --- a/packages/Lvl0/FediDiscover/src/Actions/PollFediverseAction.php +++ b/packages/Lvl0/FediDiscover/src/Actions/PollFediverseAction.php @@ -5,6 +5,7 @@ namespace Lvl0\FediDiscover\Actions; use Carbon\CarbonImmutable; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; use Lvl0\FediDiscover\Clients\FediverseClientFactory; use Lvl0\FediDiscover\Events\UrlDiscovered; @@ -18,22 +19,26 @@ public function __construct(private FediverseClientFactory $factory) {} public function execute(Instance $instance): void { + $start = microtime(true); + $client = $this->factory->for($instance); $posts = $client->fetchPostsSince($instance, $instance->last_seen_id); - $posts->each(function (FediversePost $post) use ($instance) { - try { - $this->processLinks($post, $instance); - } catch (Throwable $e) { - Log::warning('fedi-discover:processLinks failed', [ - 'instance_id' => $instance->id, - 'instance_url' => $instance->url, - 'post_url' => $post->selfUrl, - 'exception' => $e::class, - 'message' => $e->getMessage(), - ]); - } - }); + $urlCount = $posts + ->map(function (FediversePost $post) use ($instance) { + try { + return $this->processLinks($post, $instance); + } catch (Throwable $e) { + Log::warning('fedi-discover:processLinks failed', [ + 'instance_id' => $instance->id, + 'instance_url' => $instance->url, + 'post_url' => $post->selfUrl, + 'exception' => $e::class, + 'message' => $e->getMessage(), + ]); + } + }) + ->sum(); if ($posts->isNotEmpty()) { $instance->last_seen_id = $posts->first()->cursorId; @@ -41,21 +46,27 @@ public function execute(Instance $instance): void $instance->last_polled_at = now(); $instance->save(); + + Log::info('fedi-discover:poll succeeded', [ + 'instance_id' => $instance->id, + 'url_count' => $urlCount, + 'duration_ms' => (int) round((microtime(true) - $start) * 1000), + ]); } - private function processLinks(FediversePost $post, Instance $instance): void + private function processLinks(FediversePost $post, Instance $instance): int { if ($post->body === null) { - return; + return 0; } $linksFound = preg_match_all('~https?://[^\s<>"\'()\[\]]+~', $post->body, $matches); if ($linksFound === 0) { - return; + return 0; } - collect($matches[0]) + return collect($matches[0]) ->map(fn (string $u) => rtrim($u, '.,;:!?')) ->filter(fn (string $u) => filter_var($u, FILTER_VALIDATE_URL) !== false) ->filter(fn (string $u) => parse_url($u, PHP_URL_HOST) !== parse_url($instance->url, PHP_URL_HOST)) @@ -66,6 +77,7 @@ private function processLinks(FediversePost $post, Instance $instance): void discoveredAt: CarbonImmutable::now(), postUrl: $post->selfUrl, postBody: $post->body, - )); + )) + ->count(); } } diff --git a/packages/Lvl0/FediDiscover/tests/Feature/PollFediverseActionTest.php b/packages/Lvl0/FediDiscover/tests/Feature/PollFediverseActionTest.php index 231e16c..8524fb4 100644 --- a/packages/Lvl0/FediDiscover/tests/Feature/PollFediverseActionTest.php +++ b/packages/Lvl0/FediDiscover/tests/Feature/PollFediverseActionTest.php @@ -7,6 +7,7 @@ use Carbon\CarbonImmutable; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Log; use Lvl0\FediDiscover\Actions\PollFediverseAction; use Lvl0\FediDiscover\Clients\FediverseClientFactory; use Lvl0\FediDiscover\Clients\FediverseClientInterface; @@ -198,6 +199,29 @@ public function test_it_leaves_last_seen_id_unchanged_when_no_posts_are_returned $this->assertSame('500', $instance->fresh()->last_seen_id); } + public function test_poll_logs_a_structured_success_entry_with_url_count_and_duration(): void + { + Log::spy(); + Event::fake([UrlDiscovered::class]); + + $instance = $this->makeInstance(); + + $this->pollInstance($instance, [ + new FediversePost('1', 'https://mastodon.social/@alice/1', 'See https://example.com/one and https://other.example/two'), + new FediversePost('2', 'https://mastodon.social/@bob/2', 'Also https://example.com/three'), + ]); + + Log::shouldHaveReceived('info') + ->once() + ->withArgs(function (string $message, array $context) use ($instance): bool { + return $message === 'fedi-discover:poll succeeded' + && $context['instance_id'] === $instance->id + && $context['url_count'] === 3 + && isset($context['duration_ms']) + && $context['duration_ms'] >= 0; + }); + } + /** * @param array $posts */