Logging: Renamed EngelsystemLogger to Logger and added UserAwareLogger

This commit is contained in:
Igor Scheller 2020-02-29 20:53:25 +01:00 committed by msquare
parent 36da807ca2
commit c519be276a
9 changed files with 157 additions and 55 deletions

View File

@ -606,9 +606,6 @@ class ImportSchedule extends BaseController
*/ */
protected function log(string $message, array $context = []): void protected function log(string $message, array $context = []): void
{ {
$user = auth()->user();
$message = sprintf('%s (%u): %s', $user->name, $user->id, $message);
$this->log->info($message, $context); $this->log->info($message, $context);
} }
} }

View File

@ -12,14 +12,7 @@ use Psr\Log\LogLevel;
*/ */
function engelsystem_log($message, $level = LogLevel::INFO) function engelsystem_log($message, $level = LogLevel::INFO)
{ {
$nick = "Guest";
/** @var LoggerInterface $logger */ /** @var LoggerInterface $logger */
$logger = app('logger'); $logger = app('logger');
$user = auth()->user(); $logger->log($level, $message);
if ($user) {
$nick = User_Nick_render($user, true);
}
$logger->log($level, '{nick}: {message}', ['nick' => $nick, 'message' => $message]);
} }

View File

@ -7,7 +7,7 @@ use Psr\Log\AbstractLogger;
use Psr\Log\InvalidArgumentException; use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
class EngelsystemLogger extends AbstractLogger class Logger extends AbstractLogger
{ {
protected $allowedLevels = [ protected $allowedLevels = [
LogLevel::ALERT, LogLevel::ALERT,
@ -24,8 +24,6 @@ class EngelsystemLogger extends AbstractLogger
protected $log; protected $log;
/** /**
* EngelsystemLogger constructor.
*
* @param LogEntry $log * @param LogEntry $log
*/ */
public function __construct(LogEntry $log) public function __construct(LogEntry $log)

View File

@ -3,16 +3,28 @@
namespace Engelsystem\Logger; namespace Engelsystem\Logger;
use Engelsystem\Container\ServiceProvider; use Engelsystem\Container\ServiceProvider;
use Engelsystem\Helpers\Authenticator;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
class LoggerServiceProvider extends ServiceProvider class LoggerServiceProvider extends ServiceProvider
{ {
public function register() public function register()
{ {
$logger = $this->app->make(EngelsystemLogger::class); $logger = $this->app->make(UserAwareLogger::class);
$this->app->instance('logger', $logger); $this->app->instance('logger', $logger);
$this->app->bind(LoggerInterface::class, 'logger'); $this->app->bind(LoggerInterface::class, 'logger');
$this->app->bind(EngelsystemLogger::class, 'logger'); $this->app->bind(Logger::class, 'logger');
$this->app->bind(UserAwareLogger::class, 'logger');
}
public function boot()
{
/** @var UserAwareLogger $logger */
$logger = $this->app->get(UserAwareLogger::class);
/** @var Authenticator $auth */
$auth = $this->app->get(Authenticator::class);
$logger->setAuth($auth);
} }
} }

View File

@ -0,0 +1,38 @@
<?php
namespace Engelsystem\Logger;
use Engelsystem\Helpers\Authenticator;
use Psr\Log\InvalidArgumentException;
class UserAwareLogger extends Logger
{
/** @var Authenticator */
protected $auth;
/**
* Logs with an arbitrary level and prepends the user
*
* @param mixed $level
* @param string $message
* @param array $context
*
* @throws InvalidArgumentException
*/
public function log($level, $message, array $context = [])
{
if ($this->auth && ($user = $this->auth->user())) {
$message = sprintf('%s (%u): %s', $user->name, $user->id, $message);
}
parent::log($level, $message, $context);
}
/**
* @param Authenticator $auth
*/
public function setAuth(Authenticator $auth)
{
$this->auth = $auth;
}
}

View File

@ -2,7 +2,7 @@
namespace Engelsystem\Test\Feature\Logger; namespace Engelsystem\Test\Feature\Logger;
use Engelsystem\Logger\EngelsystemLogger; use Engelsystem\Logger\Logger;
use Engelsystem\Models\LogEntry; use Engelsystem\Models\LogEntry;
use Engelsystem\Test\Feature\ApplicationFeatureTest; use Engelsystem\Test\Feature\ApplicationFeatureTest;
use Psr\Log\InvalidArgumentException; use Psr\Log\InvalidArgumentException;
@ -10,20 +10,20 @@ use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use stdClass; use stdClass;
class EngelsystemLoggerTest extends ApplicationFeatureTest class LoggerTest extends ApplicationFeatureTest
{ {
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::__construct * @covers \Engelsystem\Logger\Logger::__construct
* @return LoggerInterface * @return LoggerInterface
*/ */
public function getLogger() public function getLogger()
{ {
$logEntry = new LogEntry(); $logEntry = new LogEntry();
return new EngelsystemLogger($logEntry); return new Logger($logEntry);
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::__construct * @covers \Engelsystem\Logger\Logger::__construct
*/ */
public function testImplements() public function testImplements()
{ {
@ -48,7 +48,7 @@ class EngelsystemLoggerTest extends ApplicationFeatureTest
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::log * @covers \Engelsystem\Logger\Logger::log
* @dataProvider provideLogLevels * @dataProvider provideLogLevels
* @param string $level * @param string $level
*/ */
@ -65,7 +65,7 @@ class EngelsystemLoggerTest extends ApplicationFeatureTest
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::log * @covers \Engelsystem\Logger\Logger::log
*/ */
public function testContextReplacement() public function testContextReplacement()
{ {
@ -93,8 +93,8 @@ class EngelsystemLoggerTest extends ApplicationFeatureTest
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::interpolate * @covers \Engelsystem\Logger\Logger::interpolate
* @covers \Engelsystem\Logger\EngelsystemLogger::log * @covers \Engelsystem\Logger\Logger::log
* @dataProvider provideContextReplaceValues * @dataProvider provideContextReplaceValues
* *
* @param string $message * @param string $message
@ -111,7 +111,7 @@ class EngelsystemLoggerTest extends ApplicationFeatureTest
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::log * @covers \Engelsystem\Logger\Logger::log
*/ */
public function testContextToString() public function testContextToString()
{ {
@ -133,8 +133,8 @@ class EngelsystemLoggerTest extends ApplicationFeatureTest
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::checkLevel * @covers \Engelsystem\Logger\Logger::checkLevel
* @covers \Engelsystem\Logger\EngelsystemLogger::log * @covers \Engelsystem\Logger\Logger::log
*/ */
public function testThrowExceptionOnInvalidLevel() public function testThrowExceptionOnInvalidLevel()
{ {

View File

@ -2,7 +2,9 @@
namespace Engelsystem\Test\Unit\Logger; namespace Engelsystem\Test\Unit\Logger;
use Engelsystem\Logger\EngelsystemLogger; use Engelsystem\Helpers\Authenticator;
use Engelsystem\Logger\Logger;
use Engelsystem\Logger\UserAwareLogger;
use Engelsystem\Logger\LoggerServiceProvider; use Engelsystem\Logger\LoggerServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest; use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
@ -11,28 +13,41 @@ use Psr\Log\LoggerInterface;
class LoggerServiceProviderTest extends ServiceProviderTest class LoggerServiceProviderTest extends ServiceProviderTest
{ {
/** /**
* @covers \Engelsystem\Logger\LoggerServiceProvider::register() * @covers \Engelsystem\Logger\LoggerServiceProvider::register
*/ */
public function testRegister() public function testRegister()
{ {
/** @var EngelsystemLogger|MockObject $logger */ $serviceProvider = new LoggerServiceProvider($this->app);
$logger = $this->getMockBuilder(EngelsystemLogger::class) $serviceProvider->register();
$this->assertInstanceOf(UserAwareLogger::class, $this->app->get('logger'));
$this->assertInstanceOf(UserAwareLogger::class, $this->app->get(LoggerInterface::class));
$this->assertInstanceOf(UserAwareLogger::class, $this->app->get(Logger::class));
$this->assertInstanceOf(UserAwareLogger::class, $this->app->get(UserAwareLogger::class));
}
/**
* @covers \Engelsystem\Logger\LoggerServiceProvider::boot
*/
public function testBoot()
{
/** @var Authenticator|MockObject $auth */
$auth = $this->getMockBuilder(Authenticator::class)
->disableOriginalConstructor()
->getMock();
/** @var UserAwareLogger|MockObject $log */
$log = $this->getMockBuilder(UserAwareLogger::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$app = $this->getApp(['make', 'instance', 'bind']); $this->app->instance(Authenticator::class, $auth);
$this->app->instance(UserAwareLogger::class, $log);
$this->setExpects($app, 'make', [EngelsystemLogger::class], $logger); $log->expects($this->once())
$this->setExpects($app, 'instance', ['logger', $logger]); ->method('setAuth')
->with($auth);
$app->expects($this->atLeastOnce()) $serviceProvider = new LoggerServiceProvider($this->app);
->method('bind') $serviceProvider->boot();
->withConsecutive(
[LoggerInterface::class, 'logger'],
[EngelsystemLogger::class, 'logger']
);
$serviceProvider = new LoggerServiceProvider($app);
$serviceProvider->register();
} }
} }

View File

@ -2,18 +2,18 @@
namespace Engelsystem\Test\Unit\Logger; namespace Engelsystem\Test\Unit\Logger;
use Engelsystem\Logger\EngelsystemLogger; use Engelsystem\Logger\Logger;
use Engelsystem\Models\LogEntry; use Engelsystem\Models\LogEntry;
use Engelsystem\Test\Unit\ServiceProviderTest; use Engelsystem\Test\Unit\ServiceProviderTest;
use InvalidArgumentException; use InvalidArgumentException;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
class EngelsystemLoggerTest extends ServiceProviderTest class LoggerTest extends ServiceProviderTest
{ {
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::__construct * @covers \Engelsystem\Logger\Logger::__construct
* @covers \Engelsystem\Logger\EngelsystemLogger::log * @covers \Engelsystem\Logger\Logger::log
*/ */
public function testLog() public function testLog()
{ {
@ -25,27 +25,27 @@ class EngelsystemLoggerTest extends ServiceProviderTest
->method('create') ->method('create')
->with(['level' => LogLevel::INFO, 'message' => 'I\'m an information!']); ->with(['level' => LogLevel::INFO, 'message' => 'I\'m an information!']);
$logger = new EngelsystemLogger($logEntry); $logger = new Logger($logEntry);
$logger->log(LogLevel::INFO, 'I\'m an information!'); $logger->log(LogLevel::INFO, 'I\'m an information!');
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::log * @covers \Engelsystem\Logger\Logger::log
* @covers \Engelsystem\Logger\EngelsystemLogger::checkLevel * @covers \Engelsystem\Logger\Logger::checkLevel
*/ */
public function testCheckLevel() public function testCheckLevel()
{ {
/** @var LogEntry|MockObject $logEntry */ /** @var LogEntry|MockObject $logEntry */
$logEntry = $this->createMock(LogEntry::class); $logEntry = $this->createMock(LogEntry::class);
$logger = new EngelsystemLogger($logEntry); $logger = new Logger($logEntry);
$this->expectException(InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
$logger->log('FooBar', 'Random Stuff'); $logger->log('FooBar', 'Random Stuff');
} }
/** /**
* @covers \Engelsystem\Logger\EngelsystemLogger::interpolate * @covers \Engelsystem\Logger\Logger::interpolate
*/ */
public function testInterpolate() public function testInterpolate()
{ {
@ -61,7 +61,7 @@ class EngelsystemLoggerTest extends ServiceProviderTest
[['level' => LogLevel::NOTICE, 'message' => 'User: Bar']] [['level' => LogLevel::NOTICE, 'message' => 'User: Bar']]
); );
$logger = new EngelsystemLogger($logEntry); $logger = new Logger($logEntry);
$logger->log(LogLevel::DEBUG, 'User: {user}', ['user' => 'Foo']); $logger->log(LogLevel::DEBUG, 'User: {user}', ['user' => 'Foo']);
$logger->log(LogLevel::NOTICE, 'User: {user}', ['user' => ['name' => 'Lorem']]); $logger->log(LogLevel::NOTICE, 'User: {user}', ['user' => ['name' => 'Lorem']]);

View File

@ -0,0 +1,49 @@
<?php
namespace Engelsystem\Test\Unit\Logger;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Logger\UserAwareLogger;
use Engelsystem\Models\LogEntry;
use Engelsystem\Models\User\User;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LogLevel;
class UserAwareLoggerTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Logger\UserAwareLogger::log
* @covers \Engelsystem\Logger\UserAwareLogger::setAuth
*/
public function testLog()
{
$user = (new User())->forceFill(['id' => 1, 'name' => 'admin']);
/** @var LogEntry|MockObject $logEntry */
$logEntry = $this->getMockBuilder(LogEntry::class)
->addMethods(['create'])
->getMock();
$logEntry->expects($this->exactly(2))
->method('create')
->withConsecutive(
[['level' => LogLevel::INFO, 'message' => 'Some more informational foo']],
[['level' => LogLevel::INFO, 'message' => 'admin (1): Some even more informational bar']]
);
/** @var Authenticator|MockObject $auth */
$auth = $this->createMock(Authenticator::class);
$auth->expects($this->exactly(2))
->method('user')
->willReturnOnConsecutiveCalls(
null,
$user
);
$logger = new UserAwareLogger($logEntry);
$logger->setAuth($auth);
$logger->log(LogLevel::INFO, 'Some more informational foo');
$logger->log(LogLevel::INFO, 'Some even more informational bar');
}
}