J'utilise Monolog en tant que bibliothèque autonome dans mon application et récemment, j'ai rencontré un problème. Disons que, à un moment donné de mon application, une exception est capturée et je souhaite la journaliser:
$mylogger->error('Exception caught', array('exception' => $exception));
Cela fonctionne parfaitement, sauf une petite chose - il ne se connecte pas trace complète de la pile. Est-il possible de consigner la trace de pile complète de l'exception à l'aide des outils de formatage intégrés à monolog?
En fait, depuis la version 1.12.0
, il est possible d'inclure stacktrace dans votre fichier journal: il existe une nouvelle méthode de LineFormatter
appelée includeStacktraces
.
Pour utiliser cela, vous devez écraser le comportement par défaut du formateur Monolog:
config.yml
monolog:
handlers:
main:
formatter: your.monolog.service.id
(rest of config is as usual)
services.yml
services:
your.monolog.service.id:
class: Monolog\Formatter\LineFormatter
calls:
- [includeStacktraces]
Vérifiez github pour plus d’informations: Demande de tirage
J'ai une solution très simple !!!
$mylogger->error((string) $exception);
Non, vous ne pouvez pas enregistrer la trace de la pile à l'aide des outils de formatage intégrés. Voir ma question ici .
Si vous examinez LineFormatter.php
, vous constatez que la méthode normalizeException
est chargée de récupérer les données sur les exceptions. Donc, je devais créer un nouveau formateur qui étendait LineFormatter
. Voici le code:
<?php
namespace Monolog\Formatter;
use Exception;
class ExceptionLineFormatter extends LineFormatter
{
protected function normalizeException(Exception $e)
{
return 'Message: ' . $e->getMessage() .
'Stack Trace: '. $e->getTraceAsString();
}
}
Et j'ai initialisé mon logger comme ceci:
$logFile = 'MyLogFile.txt';
$handler = new StreamHandler($logFile);
$handler->setFormatter(new ExceptionLineFormatter);
$log = new Logger('MyLogger');
$handler = self::getStreamHander();
$log->pushHandler($handler);
Cela imprimera votre trace de pile.
Ajout à La réponse de Tomasz Madeyski , voici comment vous pouvez l'utiliser via un code uniquement:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\ErrorHandler;
use Monolog\Formatter\LineFormatter;
$formatter = new LineFormatter(LineFormatter::SIMPLE_FORMAT, LineFormatter::SIMPLE_DATE);
$formatter->includeStacktraces(true); // <--
$stream = new StreamHandler('error.log');
$stream->setFormatter($formatter);
$logger = new Logger('logger');
$logger->pushHandler($stream);
getTraceAsString vous donnera le tableau Stack Trace en tant que chaîne délimitée par "Fin de ligne". Exploser sur PHP_EOL puis foreach à travers le tableau en enregistrant chaque élément. J'espère que cela t'aides.
<?php
function test() {
throw new Exception;
}
try {
test();
} catch(Exception $e) {
$array = explode(PHP_EOL, $e->getTraceAsString());
foreach($array as $line){
$mylogger->error($line);
}
Devrait produire quelque chose comme ceci:
#0 index.php(14): test()
#1 {main}
Si vous souhaitez consigner stacktrace only lorsque Exception est levée, vous pouvez le faire dans la AppServiceProvider
:
public function register()
{
$logger = Log::getMonolog();
$logger->pushProcessor(function ($record) {
if (isset($record['context']['exception']))
{
$record['extra']['stacktrace'] = $record['context']['exception']->getTraceAsString();
}
return $record;
});
}
Cela ajoutera le stacktrace à la colonne extra
, qui pourra ensuite être utilisée par LineFormatter.
Vous pouvez simplement utiliser le fichier de configuration (Symfony Bundle)} _ avec le paramètre "include_stacktraces":
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: info
channels: ["!event"]
max_files: 10
include_stacktraces: true <--- SET TO TRUE
@seethis commit
La réponse Upvoted fonctionne , mais vous n'êtes pas obligé de créer un service personnalisé pour cela.
Le monolog.formatter.line
existe déjà sur la pile complète Symfony 3.4. Vous pouvez simplement y ajouter un appel de méthode grâce à la variable CompilerPassInterface
:
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use use Symfony\Component\HttpKernel\Kernel;
class AppKernel extends Kernel implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$container->getDefinition('monolog.formatter.line')->addMethodCall('includeStacktraces');
}
}
Le gestionnaire monolog ne semble pas recevoir le service par défaut, vous devez donc le spécifier. Exemple:
monolog:
handlers:
main:
type: rotating_file
max_files: 12
date_format: 'Y-m'
path: '%kernel.logs_dir%/%kernel.environment%.log'
level: debug
formatter: monolog.formatter.line