Skip to content

Commit

Permalink
Fix logger injection in DIC and handling and logging
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierstoval committed Jan 13, 2025
1 parent b8ac00e commit d9b0e80
Show file tree
Hide file tree
Showing 14 changed files with 207 additions and 267 deletions.
3 changes: 1 addition & 2 deletions dependency_injection/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@

use Glpi\DependencyInjection\PublicService;
use Glpi\Error\ErrorHandler;
use Glpi\Log\LegacyGlobalLogger;

return static function (ContainerConfigurator $container): void {
$projectDir = dirname(__DIR__);
Expand Down Expand Up @@ -66,5 +65,5 @@
* Override Symfony's logger.
* @see \Symfony\Component\HttpKernel\DependencyInjection\LoggerPass
*/
$services->set('logger', LegacyGlobalLogger::class);
$services->set('logger')->synthetic();
};
2 changes: 1 addition & 1 deletion phpunit/functional/Glpi/Exception/LogLineFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

namespace tests\units\Glpi\Exception;

use Glpi\Error\LogLineFormatter;
use Glpi\Log\LogLineFormatter;
use PHPUnit\Framework\TestCase;

class LogLineFormatterTest extends TestCase
Expand Down
1 change: 0 additions & 1 deletion src/CommonGLPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,6 @@ public function getHeaderName(): string
*/
public function display($options = [])
{
trigger_error('Error triggerred', E_USER_WARNING);
// Item might already be loaded, skip load and rights checks
$item_loaded = $options['loaded'] ?? false;
unset($options['loaded']);
Expand Down
48 changes: 1 addition & 47 deletions src/GLPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* ---------------------------------------------------------------------
*/

use Glpi\Error\LogLineFormatter;
use Glpi\Log\LogLineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Log\LogLevel;
Expand Down Expand Up @@ -66,50 +66,4 @@ class GLPI
*/
public const ENV_DEVELOPMENT = 'development';

/**
* Init logger
*
* @return void
*/
public function initLogger()
{
$errorHandler = new \Glpi\Error\ErrorHandler();
$errorHandler::register($errorHandler);

/**
* @var \Psr\Log\LoggerInterface $PHPLOGGER
*/
global $PHPLOGGER;

if (defined('GLPI_LOG_LVL')) {
$log_level = GLPI_LOG_LVL;
} else {
switch (GLPI_ENVIRONMENT_TYPE) {
case self::ENV_DEVELOPMENT:
// All error/messages are logs, including deprecations.
$log_level = LogLevel::DEBUG;
break;
case self::ENV_TESTING:
// Silent deprecation and info, as they should have no functional impact.
// Keep notices as they have may indicate that code is not correctly handling a specific case.
$log_level = LogLevel::NOTICE;
break;
case self::ENV_STAGING:
case self::ENV_PRODUCTION:
default:
// Keep only warning/error messages.
$log_level = LogLevel::WARNING;
break;
}
}

$PHPLOGGER = new Logger('glpiphplog');
$handler = new StreamHandler(
GLPI_LOG_DIR . "/php-errors.log",
$log_level
);
$handler->setFormatter(new LogLineFormatter());

$PHPLOGGER->pushHandler($handler);
}
}
32 changes: 29 additions & 3 deletions src/Glpi/Application/SystemConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,25 @@

namespace Glpi\Application;

use Glpi\Error\ErrorHandler;
use Glpi\Log\GlpiLogHandler;
use Monolog\Logger;
use Psr\Log\LoggerInterface;

final class SystemConfigurator
{
private LoggerInterface $logger;

public function __construct(private string $root_dir, private ?string $env)
{
$this->computeConstants();
$this->setSessionConfiguration();
$this->initLogger();
}

public function __invoke(): void
public function getLogger(): LoggerInterface
{
$this->computeConstants();
$this->setSessionConfiguration();
return $this->logger;
}

private function computeConstants(): void
Expand Down Expand Up @@ -245,4 +254,21 @@ private function setSessionConfiguration(): void
// for every GLPI instance, enven if they are served by the same server (mostly for dev envs).
session_name('glpi_' . \hash('sha512', $this->root_dir . ($_SERVER['HTTP_HOST'] ?? '') . ($_SERVER['SERVER_PORT'] ?? '')));
}

private function initLogger(): void
{
/**
* @var LoggerInterface $PHPLOGGER
*/
global $PHPLOGGER;

$PHPLOGGER = new Logger('glpi');
$PHPLOGGER->pushHandler(new GlpiLogHandler());

$this->logger = $PHPLOGGER;

$errorHandler = new ErrorHandler($PHPLOGGER);
$errorHandler::register($errorHandler);

}
}
2 changes: 2 additions & 0 deletions src/Glpi/Controller/CentralController.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public function __invoke(Request $request): Response
return new RedirectResponse($url);
}

throw new \RuntimeException('Noop');

return $this->render('pages/central/index.html.twig', [
'central' => new Central(),
]);
Expand Down
54 changes: 24 additions & 30 deletions src/Glpi/Controller/ErrorController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@

use Config;
use DBConnection;
use Glpi\Application\ErrorUtils;
use Html;
use Session;
use Symfony\Component\ErrorHandler\Error\OutOfMemoryError;
Expand All @@ -57,12 +56,17 @@ public function __invoke(Request $request, ?\Throwable $exception = null): Respo
return new Response('', 500);
}

$this->logException($exception, $request);
$this->logHttpException($exception, $request);

return $this->getErrorResponse($exception, $request);
}

private function logException(\Throwable $exception, Request $request): void
/**
* @TODO: create a specific handler in our logger so that HTTP errors are logged differently according to this method ⬇
*
* @see \Glpi\Log\GlpiLogHandler::canHandle
*/
private function logHttpException(\Throwable $exception, Request $request): void
{
if (
$exception instanceof HttpExceptionInterface
Expand All @@ -78,29 +82,23 @@ private function logException(\Throwable $exception, Request $request): void

$user_id = Session::getLoginUserID() ?: 'Anonymous';

switch ($exception::class) {
case AccessDeniedHttpException::class:
$message = sprintf(
'User ID: `%s` tried to access or perform an action on `%s` with insufficient rights.',
$user_id,
$requested_uri
);
break;
case NotFoundHttpException::class:
$message = sprintf(
'User ID: `%s` tried to access a non-existent item on `%s`.',
$user_id,
$requested_uri
);
break;
default:
$message = sprintf(
'User ID: `%s` tried to execute an invalid request on `%s`.',
$user_id,
$requested_uri
);
break;
}
$message = match ($exception::class) {
AccessDeniedHttpException::class => sprintf(
'User ID: `%s` tried to access or perform an action on `%s` with insufficient rights.',
$user_id,
$requested_uri
),
NotFoundHttpException::class => sprintf(
'User ID: `%s` tried to access a non-existent item on `%s`.',
$user_id,
$requested_uri
),
default => sprintf(
'User ID: `%s` tried to execute an invalid request on `%s`.',
$user_id,
$requested_uri
),
};

if (($exception_message = $exception->getMessage()) !== '') {
$message .= sprintf('Additional information: %s', $exception_message);
Expand All @@ -119,10 +117,6 @@ private function logException(\Throwable $exception, Request $request): void
}

Toolbox::logInFile('access-errors', $message);
} else {
// Other errors are logged in the `php-errors` log
ErrorUtils::logException($exception);
ErrorUtils::outputExceptionMessage($exception);
}
}

Expand Down
32 changes: 21 additions & 11 deletions src/Glpi/Error/ErrorDisplayHandler/HtmlErrorDisplayHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,30 @@ public static function setCurrentRequest(Request $request): void

public function canOutput(string $log_level, string $env): bool
{
return self::$currentRequest !== null;
if (!self::$currentRequest) {
return false;
}
$is_dev_env = $env === \GLPI::ENV_DEVELOPMENT;
$is_debug_mode = isset($_SESSION['glpi_use_mode']) && $_SESSION['glpi_use_mode'] == \Session::DEBUG_MODE;

if (
!$is_dev_env // error messages are always displayed in development environment
&& !$is_debug_mode // error messages are always displayed in debug mode
) {
return false;
}

/**
* @see Request::initializeFormats
*/
$type = self::$currentRequest->getPreferredFormat();

return $type === 'html';
}

public function displayErrorMessage(string $error_type, string $message, string $log_level, mixed $env): void
{
$req = self::$currentRequest;

$types = $req->getAcceptableContentTypes();

if (in_array('text/html', $types)) {
echo '<div class="alert alert-important alert-danger glpi-debug-alert" style="z-index:10000">'
. '<span class="b">' . \htmlescape($error_type) . ': </span>' . \htmlescape($message) . '</div>';
} else {
\trigger_error('Cannot display error in HTTP context for requests that do not accept HTML as a response.', \E_USER_WARNING);
}
echo '<div class="alert alert-important alert-danger glpi-debug-alert" style="z-index:10000">'
. '<span class="b">' . \htmlescape($error_type) . ': </span>' . \htmlescape($message) . '</div>';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@

namespace Glpi\Error\ErrorDisplayHandler;

final class EchoDisplayHandler implements ErrorDisplayHandler
final class LegacyCliDisplayHandler implements ErrorDisplayHandler
{
public function canOutput(string $log_level, string $env): bool
{
return true;
return \isCommandLine();
}

public function displayErrorMessage(string $error_type, string $message, string $log_level, mixed $env): void
Expand Down
Loading

0 comments on commit d9b0e80

Please sign in to comment.