Skip to content

Commit

Permalink
Merge pull request #180 from City-of-Helsinki/UHF-10751-log-levels
Browse files Browse the repository at this point in the history
UHF-10751: Add log level to monolog
  • Loading branch information
hyrsky authored Oct 10, 2024
2 parents 834be00 + c8c5cfe commit 189161e
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 1 deletion.
19 changes: 18 additions & 1 deletion src/HelfiApiBaseServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\Site\Settings;
use Drupal\helfi_api_base\Logger\CurrentUserProcessor;
use Drupal\monolog\Logger\Formatter\ConditionalFormatter;
use Drupal\monolog\Logger\Handler\ConditionalHandler;
use Drupal\monolog\Logger\Handler\DrupalHandler;
use Drush\Log\DrushLog;
use Monolog\Handler\StreamHandler;
use Monolog\Level;
use Symfony\Component\DependencyInjection\Reference;

/**
Expand Down Expand Up @@ -38,6 +41,8 @@ public function register(ContainerBuilder $container) : void {
],
]);

$logLevel = Settings::get('helfi_api_base.log_level', Level::Info->value);

if (!$container->has('logger.drupaltodrush')) {
$container->register('logger.drupaltodrush', DrushLog::class)
->addArgument(new Reference('logger.log_message_parser'))
Expand All @@ -51,7 +56,8 @@ public function register(ContainerBuilder $container) : void {
$container->register('monolog.handler.default_conditional_handler', ConditionalHandler::class)
->addArgument(new Reference('monolog.handler.drupal.drupaltodrush'))
->addArgument(new Reference('monolog.handler.website'))
->addArgument(new Reference('monolog.condition_resolver.cli'));
->addArgument(new Reference('monolog.condition_resolver.cli'))
->addArgument($logLevel);
$container->register('monolog.handler.website', StreamHandler::class)
->addArgument('php://stdout');
$container->register('monolog.formatter.drush_or_json', ConditionalFormatter::class)
Expand All @@ -62,4 +68,15 @@ public function register(ContainerBuilder $container) : void {
}
}

/**
* {@inheritDoc}
*/
public function alter(ContainerBuilder $container) {
if ($container->hasDefinition('monolog.processor.current_user')) {
$definition = $container->getDefinition('monolog.processor.current_user');
$definition->setClass(CurrentUserProcessor::class)
->addArgument(new Reference('current_user'));
}
}

}
51 changes: 51 additions & 0 deletions src/Logger/CurrentUserProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Drupal\helfi_api_base\Logger;

use Drupal\Core\Session\AccountProxyInterface;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;

/**
* Processor that adds user information to the log records.
*
* Compared to monolog implementation, this does not log usernames.
*
* @see \Drupal\monolog\Logger\Processor\CurrentUserProcessor
*/
class CurrentUserProcessor implements ProcessorInterface {

/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected AccountProxyInterface $accountProxy;

/**
* Constructs a Default object.
*
* @param \Drupal\Core\Session\AccountProxyInterface $account_proxy
* The current user.
*/
public function __construct(AccountProxyInterface $account_proxy) {
$this->accountProxy = $account_proxy;
}

/**
* {@inheritdoc}
*/
public function __invoke(LogRecord $record): LogRecord {
$record->extra = \array_merge(
$record->extra,
[
'uid' => $this->accountProxy->id(),
],
);

return $record;
}

}
98 changes: 98 additions & 0 deletions tests/src/Kernel/MonologTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

declare(strict_types=1);

namespace Drupal\Tests\helfi_api_base\Kernel;

use Drupal\KernelTests\KernelTestBase;
use Drupal\monolog\Logger\ConditionResolver\ConditionResolverInterface;
use Prophecy\PhpUnit\ProphecyTrait;

/**
* Tests monolog configuration.
*/
final class MonologTest extends KernelTestBase {

use ProphecyTrait;

/**
* Log level that is configured for the duration of this test.
*/
private const TEST_LOG_LEVEL = 'warning';

/**
* {@inheritdoc}
*/
protected static $modules = [
'monolog',
'helfi_api_base',
];

/**
* Temporary file where logs are stored.
*
* @var string
*/
private string $logFile;

/**
* {@inheritdoc}
*/
protected function bootKernel() : void {
// Set test log level before kernel is booted.
$this->setSetting('helfi_api_base.log_level', self::TEST_LOG_LEVEL);

parent::bootKernel();
}

/**
* {@inheritdoc}
*/
protected function setUp() : void {
parent::setUp();

$this->logFile = 'temporary://' . $this->randomMachineName();

$this->container
->getDefinition('monolog.handler.website')
->replaceArgument(0, $this->logFile);

// Pretend that we are running in web process so Drush log is not used.
$this->container->set('monolog.condition_resolver.cli', new class implements ConditionResolverInterface {

/**
* {@inheritdoc}
*/
public function resolve(): bool {
return FALSE;
}

});
}

/**
* Tests logger message.
*/
public function testLogging() : void {
/** @var \Psr\Log\LoggerInterface $logger */
$logger = $this->container->get('logger.channel.default');
$logger->warning('Test warning message');
$logger->debug('Test debug message');

$log = file_get_contents($this->logFile);
$this->assertNotFalse($log);

// Debug messages were not logged due to the log level.
$this->assertStringContainsString('Test warning message', $log);
$this->assertStringNotContainsString('Test debug message', $log);

foreach (explode('\n', $log) as $logLine) {
// Message is valid JSON.
$message = json_decode($logLine, flags: JSON_THROW_ON_ERROR);

// Tests \Drupal\helfi_api_base\Logger\CurrentUserProcessor.
$this->assertObjectNotHasProperty('user', $message->extra);
}
}

}

0 comments on commit 189161e

Please sign in to comment.