web: Abruf-Protokoll der RSS-Feeds — Reader-Dienst, gemeldete Abonnenten, Admin-Bericht, Panel (Roadmap 3.1)
- feed_fetches: jeder Feed-Abruf mit Art, Schlüssel, Portal, Sprache, erkanntem Reader (config/feeds.php, FeedReaderIdentifier), vom Dienst gemeldeter Abonnentenzahl und gekürztem User-Agent — keine IP. Schreiben per defer() nach der Antwort, auch bei Cache-Treffer. - Aufbewahrung 395 Tage über press-releases:purge-events; FEED_FETCHES_RECORDED_SINCE. - Admin ▸ Reports ▸ Indexierung & Abrufe: Block „Abrufe der RSS-Feeds" (Summen je Feed-Art, je Reader-Dienst, meistabgerufene Feeds; FeedFetchReport, Verdichtung in PHP für MySQL und SQLite). - Panel „Auslieferung": Abrufe je Feed in 30 Tagen; RSS-Seite nennt die Zählung ohne IP. - Tests: FeedFetchLogTest (5), IndexStatusCheckTest erweitert. - dev/2026-09-01: Nachtrag Protokoll Teil 11, Roadmap 3.1; 0.7 gilt auch für Crawler- und Feed-Log. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
ff75159b8f
commit
fc700677ff
18 changed files with 794 additions and 13 deletions
47
database/factories/FeedFetchFactory.php
Normal file
47
database/factories/FeedFetchFactory.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\FeedFetch;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<FeedFetch>
|
||||
*/
|
||||
class FeedFetchFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'feed' => FeedFetch::FEED_PORTAL,
|
||||
'feed_key' => null,
|
||||
'portal' => 'presseecho',
|
||||
'language' => 'de',
|
||||
'reader' => 'feedly',
|
||||
'subscribers' => 3,
|
||||
'user_agent' => 'Feedly/1.0 (+http://www.feedly.com/fetcher.html; 3 subscribers; like FeedFetcher-Google)',
|
||||
];
|
||||
}
|
||||
|
||||
public function category(string $slug): static
|
||||
{
|
||||
return $this->state(['feed' => FeedFetch::FEED_CATEGORY, 'feed_key' => $slug]);
|
||||
}
|
||||
|
||||
public function newsroom(string $slug): static
|
||||
{
|
||||
return $this->state(['feed' => FeedFetch::FEED_NEWSROOM, 'feed_key' => $slug]);
|
||||
}
|
||||
|
||||
public function reader(?string $reader, ?int $subscribers = null, ?string $userAgent = null): static
|
||||
{
|
||||
return $this->state([
|
||||
'reader' => $reader,
|
||||
'subscribers' => $subscribers,
|
||||
'user_agent' => $userAgent ?? (($reader ?? 'unknown').'-fetcher/1.0'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* Abruf-Protokoll der RSS-Feeds (Roadmap 3.1): jeder Abruf eines Feeds mit
|
||||
* Art (portal, category, newsroom), Schlüssel (Kategorie- bzw. Firmen-Slug),
|
||||
* Portal, Sprache, erkanntem Reader-Dienst, der vom Dienst gemeldeten
|
||||
* Abonnentenzahl und gekürztem User-Agent.
|
||||
*
|
||||
* Reines Append-Log ohne Personenbezug: keine IP-Adresse. Abonnenten sind
|
||||
* eine Angabe des Reader-Dienstes (z. B. „Feedly/1.0 (12 subscribers)"),
|
||||
* keine eigene Zählung.
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('feed_fetches', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('feed', 20);
|
||||
$table->string('feed_key', 191)->nullable();
|
||||
$table->string('portal', 20);
|
||||
$table->string('language', 5);
|
||||
$table->string('reader', 40)->nullable();
|
||||
$table->unsignedInteger('subscribers')->nullable();
|
||||
$table->string('user_agent', 255);
|
||||
$table->timestamp('created_at')->nullable();
|
||||
|
||||
$table->index(['feed', 'feed_key', 'created_at'], 'ff_feed_key_created_idx');
|
||||
$table->index(['reader', 'created_at'], 'ff_reader_created_idx');
|
||||
$table->index('created_at', 'ff_created_idx');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('feed_fetches');
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue