Download plugins/DeviceDetectorCache/Commands/WarmDeviceDetectorCache.php from Leon4gr45/matomo: direct link, hf CLI and curl.
- Browser
- Download file 7.13 kB
-
https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/DeviceDetectorCache/Commands/WarmDeviceDetectorCache.php
- Command line
-
hf download hf://spaces/Leon4gr45/matomo/plugins/DeviceDetectorCache/Commands/WarmDeviceDetectorCache.php
-
curl -L -o WarmDeviceDetectorCache.php https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/DeviceDetectorCache/Commands/WarmDeviceDetectorCache.php
7.13 kB
| /** | |
| * Matomo - free/libre analytics platform | |
| * | |
| * @link https://matomo.org | |
| * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | |
| */ | |
| namespace Piwik\Plugins\DeviceDetectorCache\Commands; | |
| use Piwik\Container\StaticContainer; | |
| use Piwik\Date; | |
| use Piwik\Piwik; | |
| use Piwik\Plugin\ConsoleCommand; | |
| use Piwik\Plugins\DeviceDetectorCache\CachedEntry; | |
| use Piwik\Plugins\DeviceDetectorCache\Configuration; | |
| class WarmDeviceDetectorCache extends ConsoleCommand | |
| { | |
| public const COMMAND_NAME = 'device-detector-cache:warm-cache'; | |
| /** | |
| * @var Configuration | |
| */ | |
| private $config; | |
| public function __construct($name = null) | |
| { | |
| parent::__construct($name); | |
| $this->config = StaticContainer::get(Configuration::class); | |
| } | |
| protected function configure() | |
| { | |
| $this->setName(self::COMMAND_NAME); | |
| $this->setDescription('Cached device detector information based on access log'); | |
| } | |
| private function printupdate($count) | |
| { | |
| if ($this->getOutput()->isVerbose()) { | |
| $mem = round(memory_get_peak_usage() / 1024 / 1024); | |
| $now = Date::now()->getDatetime(); | |
| $this->getOutput()->writeln("Count: " . $count . ' Mem:' . $mem . 'MB Date: ' . $now); | |
| } | |
| } | |
| private function log($message) | |
| { | |
| if ($this->getOutput()->isVerbose()) { | |
| $mem = round(memory_get_peak_usage() / 1024 / 1024); | |
| $now = Date::now()->getDatetime(); | |
| $this->getOutput()->writeln($message . ' Mem:' . $mem . 'MB Date: ' . $now); | |
| } | |
| } | |
| protected function doExecute(): int | |
| { | |
| $userAgents = []; | |
| $output = $this->getOutput(); | |
| $regex = $this->config->getAccessLogRegex(); | |
| $numEntriesToCache = $this->config->getNumEntriesToCache(); | |
| $matchEntry = $this->config->getRegexMatchEntry(); | |
| $path = $this->config->getAccessLogPath(); | |
| $path = trim($path); | |
| $this->log('caching up to ' . $numEntriesToCache . ' entries'); | |
| $this->log('reading from file ' . $path); | |
| $this->log('used regex ' . $regex . ' with index ' . $matchEntry); | |
| if (empty($numEntriesToCache)) { | |
| $output->writeln('No entries are supposed to be cached. Stopping command'); | |
| return self::SUCCESS; | |
| } | |
| if (!file_exists($path)) { | |
| throw new \Exception('Configured access log path does not exist: "' . $path . '"'); | |
| } | |
| $count = 0; | |
| $numLinesToProcess = StaticContainer::get('DeviceDetectorCacheNumLinesToScan'); | |
| $numLinesProcessed = 0; | |
| $handle = fopen($path, "r"); | |
| if ($handle) { | |
| while (($line = fgets($handle)) !== false) { | |
| $numLinesProcessed++; | |
| if ($numLinesProcessed >= $numLinesToProcess) { | |
| break;// we read max 5M lines to prevent in running for too long time | |
| } | |
| if (empty($line)) { | |
| continue; | |
| } | |
| preg_match($regex, $line, $matches); | |
| if ( | |
| !empty($matches[$matchEntry]) | |
| && strlen($matches[$matchEntry]) > 5 | |
| && strlen($matches[$matchEntry]) < 700 | |
| ) { | |
| $useragent = $matches[$matchEntry]; | |
| if (!isset($userAgents[$useragent])) { | |
| $userAgents[$useragent] = 1; | |
| $count = count($userAgents); | |
| if ($count % 10000 === 0) { | |
| $this->printupdate($count); | |
| } | |
| } else { | |
| $userAgents[$useragent] = $userAgents[$useragent] + 1; | |
| } | |
| } | |
| $line = null; | |
| unset($line); | |
| $matches = null; | |
| unset($matches); | |
| if ($numLinesProcessed % 10 === 0) { | |
| usleep(300); // slightly slow down disk usage to avoid running eg into some EBS limit | |
| } | |
| if ($numLinesProcessed % 1000 === 0) { | |
| usleep(10000); // every 10K lines sleep for a 10ms to not max out CPU as much | |
| } | |
| } | |
| fclose($handle); | |
| } else { | |
| throw new \Exception('Error opening file. Maybe no read permission? Path: ' . $path); | |
| } | |
| $this->log("parsed file: " . $numLinesProcessed . " lines"); | |
| $this->printupdate($count); | |
| arsort($userAgents, SORT_NATURAL); | |
| if (empty($userAgents)) { | |
| $output->writeln('No user agents found'); | |
| return self::SUCCESS; | |
| } | |
| $this->log($count . ' user agents found'); | |
| $this->log("writing files"); | |
| $i = 0; | |
| $numRequestsDetected = 0; | |
| $ignoreUserAgentsWithLessRequestsThan = StaticContainer::get('DeviceDetectorCacheIgnoreUserAgentsWithLessThanXRequests'); | |
| foreach ($userAgents as $agent => $val) { | |
| if ($i >= $numEntriesToCache) { | |
| $output->writeln('stopping because number of configured entries were cached'); | |
| break; | |
| } | |
| if ($val < $ignoreUserAgentsWithLessRequestsThan) { | |
| $output->writeln('stopping because remaining user agents have only few requests'); | |
| // we don't cache user agents that happened less than 9 times or less as it's so rare it's not really worth caching it and we rather do it on demand | |
| break; | |
| } | |
| $i++; | |
| $numRequestsDetected += $val; // useful to detect hit ratio | |
| if ($i % 5000 === 0) { | |
| $this->printupdate( | |
| 'written files so far: ' . $i . ' detecting that many requests: ' . $numRequestsDetected | |
| ); | |
| } | |
| if ($i <= 10) { | |
| $this->log('Found user agent ' . $agent . ' count: ' . $val); | |
| } | |
| CachedEntry::writeToCache($agent, []); | |
| // sleep 2ms to let CPU do something else | |
| // this will make things about 10m slower for 200K entries but at least sudden CPU increase for instance | |
| // can be prevented when there are only few CPUs available | |
| // note: roughly per minute we write around 5K entries | |
| usleep(2000); | |
| } | |
| $output->writeln('Written ' . $i . ' cache entries to file.'); | |
| $output->writeln('The hit ratio will be roughly ' . Piwik::getPercentageSafe($numRequestsDetected, $numLinesToProcess) . '%'); | |
| $numCacheFilesExist = CachedEntry::getNumEntriesInCacheDir(); | |
| $output->writeln($numCacheFilesExist . ' cached files exist'); | |
| if ($numCacheFilesExist > $numEntriesToCache) { | |
| $numEntriesToDelete = $numCacheFilesExist - $numEntriesToCache; | |
| $output->writeln('Need to delete ' . $numEntriesToDelete . ' files'); | |
| CachedEntry::deleteLeastAccessedFiles($numEntriesToDelete); | |
| $output->writeln('done deleting files'); | |
| } | |
| return self::SUCCESS; | |
| } | |
| } | |