Skip to content

Commit 7fdc80b

Browse files
committed
Add stdout and stderr log target support to Logger
- Introduced support for `log.output` configuration to specify logging target as `file`, `stdout`, or `stderr`. - Updated `Logger` to handle new log output targets. - Added unit test for `stdout` output target.
1 parent 0ab283c commit 7fdc80b

4 files changed

Lines changed: 59 additions & 6 deletions

File tree

src/base/Logger.php

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020

2121
if (!defined('LOG_DIR')) {
22-
GeneratorHelper::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
2322
define('LOG_DIR', BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
2423
}
2524

@@ -29,6 +28,10 @@
2928
class Logger
3029
{
3130
const DEFAULT_NAMESPACE = 'PSFS';
31+
private const OUTPUT_FILE = 'file';
32+
private const OUTPUT_STDOUT = 'stdout';
33+
private const OUTPUT_STDERR = 'stderr';
34+
3235
use SingletonTrait;
3336

3437
/**
@@ -47,6 +50,7 @@ class Logger
4750
* @var string
4851
*/
4952
protected string $logLevel;
53+
private bool $closeStreamOnDestruct = true;
5054

5155
/**
5256
* @throws GeneratorException
@@ -56,8 +60,9 @@ class Logger
5660
public function __construct()
5761
{
5862
$args = func_get_args();
59-
list($logger, $debug, $path) = $this->setup($args);
60-
$this->stream = fopen($path . DIRECTORY_SEPARATOR . date('Ymd') . '.log', 'ab+');
63+
list($logger, $debug, $target, $closeStreamOnDestruct) = $this->setup($args);
64+
$this->closeStreamOnDestruct = $closeStreamOnDestruct;
65+
$this->stream = fopen($target, 'ab+');
6166
if (false !== $this->stream && is_resource($this->stream)) {
6267
$this->addPushLogger($logger, $debug);
6368
} else {
@@ -68,7 +73,9 @@ public function __construct()
6873

6974
public function __destruct()
7075
{
71-
fclose($this->stream);
76+
if ($this->closeStreamOnDestruct && is_resource($this->stream)) {
77+
fclose($this->stream);
78+
}
7279
}
7380

7481
/**
@@ -108,8 +115,26 @@ private function setup(array $args = [])
108115
$namespace = $args[0][0] ?? 'PSFS';
109116
$debug = $args[0][1] ?? true;
110117
}
118+
[$target, $closeStreamOnDestruct] = $this->resolveLogOutputTarget();
119+
return [LogHelper::cleanLoggerName($namespace), $debug, $target, $closeStreamOnDestruct];
120+
}
121+
122+
/**
123+
* @return array{0:string,1:bool}
124+
* @throws GeneratorException
125+
*/
126+
private function resolveLogOutputTarget(): array
127+
{
128+
$output = strtolower(trim((string)Config::getParam('log.output', self::OUTPUT_FILE)));
129+
if ($output === self::OUTPUT_STDOUT) {
130+
return ['php://stdout', false];
131+
}
132+
if ($output === self::OUTPUT_STDERR) {
133+
return ['php://stderr', false];
134+
}
135+
111136
$path = $this->createLoggerPath();
112-
return [LogHelper::cleanLoggerName($namespace), $debug, $path];
137+
return [$path . DIRECTORY_SEPARATOR . date('Ymd') . '.log', true];
113138
}
114139

115140
/**

src/base/config/Config.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class Config
7070
'api.secret', // Secret passphrase to securize the api
7171
'api.admin', // Enable the autogenerated api admin(wok)
7272
'log.level', // Max log level(default INFO)
73+
'log.output', // Logger sink target (file|stdout|stderr)
7374
'admin_action', // Default admin url when access to /admin
7475
'cache.var', // Static cache var
7576
'twig.autoreload', // Enable or disable auto reload templates for twig

src/base/extension/traits/CssTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ protected function loopCssLines($file)
110110
}
111111

112112
/**
113-
* @param string|array $source
113+
* @param array $source
114114
* @param string $file
115115
*/
116116
protected function extractCssResources($source, $file)

tests/base/LoggerTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,31 @@ public function testLogSetup()
9090
Config::save($defaultConfig, []);
9191
}
9292

93+
public function testLoggerSupportsStdoutOutputTarget(): void
94+
{
95+
$config = Config::getInstance();
96+
$configProperty = new \ReflectionProperty(Config::class, 'config');
97+
$configProperty->setAccessible(true);
98+
$defaultConfig = $configProperty->getValue($config);
99+
$overrideConfig = $defaultConfig;
100+
$overrideConfig['log.output'] = 'stdout';
101+
$configProperty->setValue($config, $overrideConfig);
102+
103+
try {
104+
$reflection = new \ReflectionClass(Logger::class);
105+
/** @var Logger $logger */
106+
$logger = $reflection->newInstanceWithoutConstructor();
107+
108+
$method = new \ReflectionMethod(Logger::class, 'resolveLogOutputTarget');
109+
$method->setAccessible(true);
110+
[$target, $closeStreamOnDestruct] = $method->invoke($logger);
111+
112+
$this->assertSame('php://stdout', $target);
113+
$this->assertFalse($closeStreamOnDestruct);
114+
} finally {
115+
Logger::dropInstance();
116+
$configProperty->setValue($config, $defaultConfig);
117+
}
118+
}
119+
93120
}

0 commit comments

Comments
 (0)