Skip to content

Commit 3dbc7fc

Browse files
committed
feat: Allow to show all log types by adding an internal log file for non-file based loggers
Signed-off-by: Ferdinand Thiessen <[email protected]>
1 parent 29d0240 commit 3dbc7fc

File tree

3 files changed

+136
-19
lines changed

3 files changed

+136
-19
lines changed

lib/Listener/LogListener.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use OC\SystemConfig;
2727
use OCA\LogReader\Log\Console;
2828
use OCA\LogReader\Log\Formatter;
29+
use OCA\LogReader\Log\LogProxy;
2930
use OCP\EventDispatcher\Event;
3031
use OCP\EventDispatcher\IEventListener;
3132
use OCP\Log\BeforeMessageLoggedEvent;
@@ -35,9 +36,14 @@
3536
* @template-implements IEventListener<BeforeMessageLoggedEvent>
3637
*/
3738
class LogListener implements IEventListener {
38-
private ?Console $console;
39+
private ?Console $console = null;
40+
private ?LogProxy $proxy = null;
3941

40-
public function __construct(Formatter $formatter, SystemConfig $config) {
42+
public function __construct(
43+
Formatter $formatter,
44+
SystemConfig $config,
45+
LogProxy $proxy,
46+
) {
4147
if (defined('OC_CONSOLE') && \OC_CONSOLE) {
4248
$level = getenv('OCC_LOG');
4349
if ($level) {
@@ -46,8 +52,11 @@ public function __construct(Formatter $formatter, SystemConfig $config) {
4652
} else {
4753
$this->console = null;
4854
}
49-
} else {
50-
$this->console = null;
55+
}
56+
57+
// Only create a proxy file if log type is not file
58+
if ($config->getValue('log_type', 'file') !== 'file') {
59+
$this->proxy = $proxy;
5160
}
5261
}
5362

@@ -60,5 +69,8 @@ public function handle(Event $event): void {
6069
if ($this->console) {
6170
$this->console->log($event->getLevel(), $event->getApp(), $event->getMessage());
6271
}
72+
if ($this->proxy) {
73+
$this->proxy->log($event->getLevel(), $event->getApp(), $event->getMessage());
74+
}
6375
}
6476
}

lib/Log/LogIteratorFactory.php

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@
2323

2424
namespace OCA\LogReader\Log;
2525

26+
use OCP\Files\IAppData;
27+
use OCP\Files\NotFoundException;
2628
use OCP\IConfig;
2729
use OCP\Log\IFileBased;
2830
use OCP\Log\ILogFactory;
2931

3032
class LogIteratorFactory {
31-
private $config;
32-
private $logFactory;
3333

34-
public function __construct(IConfig $config, ILogFactory $logFactory) {
35-
$this->config = $config;
36-
$this->logFactory = $logFactory;
34+
public function __construct(
35+
private IConfig $config,
36+
private ILogFactory $logFactory,
37+
private IAppData $appData,
38+
) {
3739
}
3840

3941
/**
@@ -44,18 +46,39 @@ public function __construct(IConfig $config, ILogFactory $logFactory) {
4446
public function getLogIterator(array $levels) {
4547
$dateFormat = $this->config->getSystemValue('logdateformat', \DateTime::ATOM);
4648
$timezone = $this->config->getSystemValue('logtimezone', 'UTC');
47-
$log = $this->logFactory->get('file');
48-
if ($log instanceof IFileBased) {
49-
$handle = fopen($log->getLogFilePath(), 'rb');
50-
if ($handle) {
51-
$iterator = new LogIterator($handle, $dateFormat, $timezone);
52-
return new \CallbackFilterIterator($iterator, function ($logItem) use ($levels) {
53-
return $logItem && in_array($logItem['level'], $levels);
54-
});
49+
50+
if ($this->config->getSystemValue('log_type', 'file') !== 'file') {
51+
try {
52+
$folder = $this->appData->getFolder('logreader');
53+
} catch (NotFoundException $e) {
54+
$folder = $this->appData->newFolder('logreader');
55+
}
56+
57+
try {
58+
$logfile = $folder->getFile('nextcloud.log');
59+
} catch (NotFoundException $e) {
60+
$logfile = $folder->newFile('nextcloud.log');
61+
}
62+
63+
$handle = $logfile->read();
64+
if (!$handle) {
65+
throw new \Exception('Error while opening internal logfile');
66+
}
67+
} else {
68+
$logfile = $this->logFactory->get('file');
69+
if ($logfile instanceof IFileBased) {
70+
$handle = fopen($logfile->getLogFilePath(), 'rb');
71+
if (!$handle) {
72+
throw new \Exception("Error while opening " . $logfile->getLogFilePath());
73+
}
5574
} else {
56-
throw new \Exception("Error while opening " . $log->getLogFilePath());
75+
throw new \Exception('Can\'t find log class');
5776
}
5877
}
59-
throw new \Exception('Can\'t find log class');
78+
79+
$iterator = new LogIterator($handle, $dateFormat, $timezone);
80+
return new \CallbackFilterIterator($iterator, function ($logItem) use ($levels) {
81+
return $logItem && in_array($logItem['level'], $levels);
82+
});
6083
}
6184
}

lib/Log/LogProxy.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* @copyright Copyright (c) 2023 Ferdinand Thiessen <[email protected]>
6+
*
7+
* @license GNU AGPL version 3 or any later version
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License as
11+
* published by the Free Software Foundation, either version 3 of the
12+
* License, or (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Affero General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Affero General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
namespace OCA\LogReader\Log;
25+
26+
use OC\Log\LogDetails;
27+
use OC\SystemConfig;
28+
use OCP\Files\IAppData;
29+
use OCP\Files\NotFoundException;
30+
use OCP\Files\SimpleFS\ISimpleFile;
31+
32+
/**
33+
* Create a logfile even for syslog etc loggers
34+
*/
35+
class LogProxy extends LogDetails {
36+
private ISimpleFile $logfile;
37+
38+
public function __construct(IAppData $appData, private SystemConfig $config) {
39+
parent::__construct($config);
40+
41+
try {
42+
$folder = $appData->getFolder('logreader');
43+
} catch (NotFoundException $e) {
44+
$folder = $appData->newFolder('logreader');
45+
}
46+
47+
try {
48+
$this->logfile = $folder->getFile('nextcloud.log');
49+
} catch (NotFoundException $e) {
50+
$this->logfile = $folder->newFile('nextcloud.log');
51+
}
52+
}
53+
54+
public function log(int $level, string $app, array $entry) {
55+
if ($level >= $this->config->getValue('loglevel', 1)) {
56+
$hasBacktrace = isset($entry['exception']);
57+
$logBacktrace = $this->config->getValue('log.backtrace', false);
58+
if (!$hasBacktrace && $logBacktrace) {
59+
$entry['backtrace'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
60+
}
61+
62+
$entry = $this->logDetailsAsJSON($app, $entry, $level);
63+
64+
$handle = $this->logfile->read();
65+
if ($handle) {
66+
$content = stream_get_contents($handle);
67+
fclose($handle);
68+
}
69+
70+
$handle = $this->logfile->write();
71+
if ($handle) {
72+
if (isset($content) && $content !== false) {
73+
fwrite($handle, $content);
74+
}
75+
fwrite($handle, $entry."\n");
76+
fclose($handle);
77+
} else {
78+
throw new \Error('Could not open internal log file.');
79+
}
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)