From 178e542c40181c1f171f9e8140e9abb5c658800f Mon Sep 17 00:00:00 2001 From: Dominik Pfennig <dominik@suma-ev.de> Date: Wed, 21 Sep 2016 15:03:29 +0200 Subject: [PATCH] =?UTF-8?q?Die=20Daten=20dar=C3=BCber,=20welche=20Suchmasc?= =?UTF-8?q?hinen=20abgefragt=20wurden=20und=20wie=20viele=20geantwortet=20?= =?UTF-8?q?haben=20werden=20ins=20Redis=20geschrieben.=20Mit=20einem=20ent?= =?UTF-8?q?sprechenden=20Cronjob=20werden=20diese=20auch=20in=20eine=20Log?= =?UTF-8?q?=20Datei=20geschrieben?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Commands/LogRotate.php | 119 +++++++++++++++++++++++++++++ app/Console/Kernel.php | 3 +- app/MetaGer.php | 38 +++++++-- app/Models/Searchengine.php | 1 - 4 files changed, 152 insertions(+), 9 deletions(-) create mode 100644 app/Console/Commands/LogRotate.php diff --git a/app/Console/Commands/LogRotate.php b/app/Console/Commands/LogRotate.php new file mode 100644 index 000000000..091e6b77d --- /dev/null +++ b/app/Console/Commands/LogRotate.php @@ -0,0 +1,119 @@ +<?php + +namespace App\Console\Commands; + +use Illuminate\Console\Command; +use Redis; + +class LogRotate extends Command +{ + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'log:rotate'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Dieses Kommando bezieht alle Log-Einträge aus dem Redis System und exportiert diese in entsprechende Dateien.'; + + /** + * Create a new command instance. + * + * @return void + */ + public function __construct() + { + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + # Wir extrahieren die Logs mit den Daten der einzelnen Suchmaschinen: + # In den Daten ist festgehalten, wie oft eine jede Suchmaschine abgefragt wurde + # und wie häufig diese geantwortet hat: + $this->extractSearchEngineLogs(); + } + + private function extractSearchEngineLogs() + { + $redis = Redis::connection('redisLogs'); + # Hier legen wir das Ergebnis ab: + # [ + # 'fastbot' => [ + # '' + # ] + # ] + $searchEngineLogs = ['recent' => [], 'overall' => []]; + try { + # Wir benötigen zunächst die Namen aller Suchmaschinen: + $sumasFile = config_path() . "/sumas.xml"; + $xml = simplexml_load_file($sumasFile); + $xml = $xml->xpath("suma"); + $sumaNames = []; + foreach ($xml as $suma) { + $searchEngineLogs['recent'][$suma["name"]->__toString()] = ["requests" => 0, "answered" => 0]; + } + #Auslesen/hinzufügen der Daten: + foreach ($searchEngineLogs['recent'] as $name => $values) { + $searchEngineLogs['recent'][$name]["requests"] = $redis->getset('logs.engines.requests.' . $name, 0); + $searchEngineLogs['recent'][$name]["answered"] = $redis->getset('logs.engines.answered.' . $name, 0); + } + + $filePath = "/var/log/metager/"; + # Wir haben nun die aktuellen daten und müssen diese noch mit den aktuellen Kombinieren: + # Hierbei behalten wir die Daten, seid dem letzten Rotate so wie sie sind und verknüpfen diese mit einer gesamt Statistik. + if (file_exists($filePath . "engine.log") && is_readable($filePath . "engine.log")) { + $oldData = file_get_contents($filePath . "engine.log"); + # JSON Decode + $oldData = json_decode($oldData, true); + if (isset($oldData['overall'])) { + $searchEngineLogs['overall'] = $oldData['overall']; + } + } + + # Jetzt fügen wir zu den Gesamtdaten die zuletzt erfassten hinzu: + foreach ($searchEngineLogs['recent'] as $name => $values) { + if (isset($searchEngineLogs['overall'][$name]["requests"])) { + $searchEngineLogs['overall'][$name]["requests"] += $values["requests"]; + } else { + $searchEngineLogs['overall'][$name]["requests"] = $values["requests"]; + } + if (isset($searchEngineLogs['overall'][$name]["answered"])) { + $searchEngineLogs['overall'][$name]["answered"] += $values["answered"]; + } else { + $searchEngineLogs['overall'][$name]["answered"] = $values["answered"]; + } + } + + # Ins JSON Format umwandeln: + $searchEngineLogs = json_encode($searchEngineLogs, JSON_PRETTY_PRINT); + + # Und in die Datei sichern + if (((file_exists($filePath . "engine.log") && is_writable($filePath . "engine.log")) || (!file_exists($filePath . "engine.log") && is_writable($filePath))) && file_put_contents($filePath . "engine.log", $searchEngineLogs) !== false) { + $this->info("Logs der Suchmaschinen erfolgreich exportiert."); + return; + } else { + # Der Schreibvorgang war nicht erfolgreich. Wir packen die Daten zurück + foreach (json_decode($searchEngineLogs, true) as $name => $values) { + $redis->incrby('logs.engines.requests.' . $name, $values["requests"]); + $redis->incrby('logs.engines.answered.' . $name, $values["answered"]); + } + $this->info("Konnte die Datei \"$filePath" . "engine.log\" nicht erstellen. Keine Rechte."); + return; + } + + } catch (\ErrorException $e) { + return; + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 71c519d32..1ef2005a1 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -13,7 +13,7 @@ class Kernel extends ConsoleKernel * @var array */ protected $commands = [ - // Commands\Inspire::class, + Commands\LogRotate::class, ]; /** @@ -24,6 +24,7 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { + $schedule->command('log:rotate')->everyMinute(); // $schedule->command('inspire') // ->hourly(); } diff --git a/app/MetaGer.php b/app/MetaGer.php index 57f6cb295..91b12586d 100644 --- a/app/MetaGer.php +++ b/app/MetaGer.php @@ -524,19 +524,20 @@ class MetaGer */ # Wir zählen die Suchmaschinen, die durch den Cache beantwortet wurden: - $enginesToLoad = 0; + $enginesToLoad = []; $canBreak = false; foreach ($engines as $engine) { if ($engine->cached) { - $enginesToLoad--; if ($overtureEnabled && ($engine->name === "overture" || $engine->name === "overtureAds")) { $canBreak = true; } + } else { + # Das Array zählt einerseits die Suchmaschinen, auf die wir warten und andererseits + # welche Suchmaschinen nicht rechtzeitig geantwortet haben. + $enginesToLoad[$engine->name] = false; } } - $enginesToLoad += count($engines); - $this->waitForResults($enginesToLoad, $overtureEnabled, $canBreak); $this->retrieveResults($engines); @@ -616,6 +617,10 @@ class MetaGer { $loadedEngines = 0; $timeStart = microtime(true); + + # Auf wie viele Suchmaschinen warten wir? + $engineCount = count($enginesToLoad); + while (true) { $time = (microtime(true) - $timeStart) * 1000; $loadedEngines = intval(Redis::hlen('search.' . $this->getHashCode())); @@ -625,12 +630,12 @@ class MetaGer # Abbruchbedingung if ($time < 500) { - if (($enginesToLoad === 0 || $loadedEngines >= $enginesToLoad) && $canBreak) { + if (($engineCount === 0 || $loadedEngines >= $engineCount) && $canBreak) { break; } } elseif ($time >= 500 && $time < $this->time) { - if (($enginesToLoad === 0 || ($loadedEngines / ($enginesToLoad * 1.0)) >= 0.8) && $canBreak) { + if (($engineCount === 0 || ($loadedEngines / ($engineCount * 1.0)) >= 0.8) && $canBreak) { break; } @@ -639,6 +644,13 @@ class MetaGer } usleep(50000); } + + # Wir haben nun so lange wie möglich gewartet. Wir registrieren nun noch die Suchmaschinen, die geanwortet haben. + $answered = Redis::hgetall('search.' . $this->getHashCode()); + foreach ($answered as $key => $value) { + $enginesToLoad[$key] = true; + } + $this->enginesToLoad = $enginesToLoad; } public function retrieveResults($engines) @@ -940,7 +952,19 @@ class MetaGer $useragent = str_replace(" ", "", $useragent); $logEntry .= " time=" . round((microtime(true) - $this->starttime), 2) . " serv=" . $this->fokus; $logEntry .= " search=" . $this->eingabe; - $redis->rpush('logs.search', $logEntry); + + # 2 Arten von Logs in einem wird die Anzahl der Abfragen an eine Suchmaschine gespeichert und in der anderen + # die Anzahl, wie häufig diese Ergebnisse geliefert hat. + $enginesToLoad = $this->enginesToLoad; + $redis->pipeline(function ($pipe) use ($enginesToLoad, $logEntry) { + $pipe->rpush('logs.search', $logEntry); + foreach ($this->enginesToLoad as $name => $answered) { + $pipe->incr('logs.engines.requests.' . $name); + if ($answered) { + $pipe->incr('logs.engines.answered.' . $name); + } + } + }); } catch (\Exception $e) { return; } diff --git a/app/Models/Searchengine.php b/app/Models/Searchengine.php index 4d8b75fb2..60946a9fd 100644 --- a/app/Models/Searchengine.php +++ b/app/Models/Searchengine.php @@ -178,7 +178,6 @@ abstract class Searchengine } } - if ($body !== "") { $this->loadResults($body); $this->getNext($metager, $body); -- GitLab