%PDF- %PDF-
Direktori : /www/varak.net/nextcloud.varak.net/apps/logreader/lib/Controller/ |
Current File : /www/varak.net/nextcloud.varak.net/apps/logreader/lib/Controller/LogController.php |
<?php /** * SPDX-FileCopyrightText: 2016-2023 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2015 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ namespace OCA\LogReader\Controller; use OCA\LogReader\Log\LogIteratorFactory; use OCA\LogReader\Log\SearchFilter; use OCA\LogReader\Service\SettingsService; use OCA\LogReader\Settings\Admin; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; use Psr\Log\LoggerInterface; /** * Class LogController * * @package OCA\LogReader\Controller */ class LogController extends Controller { public function __construct($appName, IRequest $request, private LogIteratorFactory $logIteratorFactory, private SettingsService $settingsService, private LoggerInterface $logger, ) { parent::__construct($appName, $request); } /** * @param string $query * @param int $count * @param int $offset * @return JSONResponse */ #[AuthorizedAdminSetting(settings: Admin::class)] public function get($query = '', $count = 50, $offset = 0): JSONResponse { $logType = $this->settingsService->getLoggingType(); // we only support web access when `log_type` is set to `file` (the default) if ($logType !== 'file') { $this->logger->debug('File-based logging must be enabled to access logs from the Web UI.'); return new JSONResponse([], Http::STATUS_FAILED_DEPENDENCY); } $iterator = $this->logIteratorFactory->getLogIterator($this->settingsService->getShownLevels()); if ($query !== '') { $iterator = new \LimitIterator($iterator, 0, 100000); // limit the number of message we search to avoid huge search times $iterator->rewind(); $iterator = new SearchFilter($iterator, $query); $iterator->rewind(); return $this->responseFromIterator($iterator, $count, $offset); } return $this->responseFromIterator($iterator, $count, $offset); } /** * @brief Gets the last item in the log, bypassing any cache. * @return mixed */ private function getLastItem() { $iterator = $this->logIteratorFactory->getLogIterator($this->settingsService->getShownLevels()); $iterator->next(); return $iterator->current(); } /** * @brief Use to poll for new log messages since $lastReqId. * * @note There is a possible race condition, when the user loads the * logging page when a request isn't finished and this specific request * is the last request in the log, then new messages of this request * won't be polled. This is because there is no reliable way to identify * a log message, so we have to use the reqid: * - the key of the iterator will change when a new message is saved * - a combination of reqid and counting the messages for that specific reqid * will work in some cases but not when there are more than 50 messages of that * request. */ #[AuthorizedAdminSetting(settings: Admin::class)] public function poll(string $lastReqId): JSONResponse { $logType = $this->settingsService->getLoggingType(); // we only support web access when `log_type` is set to `file` (the default) if ($logType !== 'file') { $this->logger->debug('File-based logging must be enabled to access logs from the Web UI.'); return new JSONResponse([], Http::STATUS_FAILED_DEPENDENCY); } $lastItem = $this->getLastItem(); if ($lastItem === null || $lastItem['reqId'] === $lastReqId) { return new JSONResponse([]); } $iterator = $this->logIteratorFactory->getLogIterator($this->settingsService->getShownLevels()); $iterator->next(); $data = []; while ($iterator->valid()) { $line = $iterator->current(); if ($line['reqId'] === $lastReqId) { break; } if (!is_null($line)) { $line['id'] = uniqid(); $data[] = $line; } $iterator->next(); } return new JSONResponse($data); } protected function responseFromIterator(\Iterator $iterator, $count, $offset): JSONResponse { $iterator->rewind(); for ($i = 0; $i < $offset; $i++) { $iterator->next(); } $data = []; for ($i = 0; $i < $count && $iterator->valid(); $i++) { $line = $iterator->current(); if (!is_null($line)) { $line["id"] = uniqid(); $data[] = $line; } $iterator->next(); } return new JSONResponse([ 'data' => $data, 'remain' => $iterator->valid() ]); } }