Pour envoyer vos logs PHP à Datadog, activez la journalisation au sein d’un fichier et suivez ce fichier avec l’Agent Datadog. Les exemples de configuration ci-dessous utilisent les bibliothèques de journalisation Monolog, Zend-Log et Symfony.
Utilisez la configuration ci-dessous pour activer le format JSON et enregistrer les logs et les événements dans le fichier application-json.log. Après avoir lancé l’instance Monolog, ajoutez dans votre code un nouveau gestionnaire :
<?phprequire__DIR__.'/vendor/autoload.php';// Charger la bibliothèque Monolog
useMonolog\Logger;useMonolog\Handler\StreamHandler;useMonolog\Formatter\JsonFormatter;// Créer un canal pour l'enregistrement des logs
$log=newLogger('channel_name');// Créer un formateur JSON
$formatter=newJsonFormatter();// Créer un gestionnaire
$stream=newStreamHandler(__DIR__.'/application-json.log',Logger::DEBUG);$stream->setFormatter($formatter);// Connexion
$log->pushHandler($stream);// Un exemple
$log->info('Ajout d'unnouvelutilisateur', array('username' => 'Seldaek'));
Utilisez la configuration ci-dessous pour activer le format JSON et enregistrer les logs et les événements dans le fichier application-json.log. Après avoir lancé l’instance Zend-Log, ajoutez dans votre code un nouveau gestionnaire :
<?phpuseZend\Log\Logger;useZend\Log\Writer\Stream;useZend\Log\Formatter\JsonFormatter;// Créer un logger
$logger=newLogger();// Créer un service d'écriture
$writer=newStream('file://'.__DIR__.'/application-json.log');// Créer un formateur JSON
$formatter=newJsonFormatter();$writer->setFormatter($formatter);// Connexion
$logger->addWriter($writer);Zend\Log\Logger::registerErrorHandler($logger);
Pour configurer le formateur dans votre configuration Monolog, déclarez le champ formatter comme suit :
Si la solution APM est activée pour cette application, vous pouvez améliorer la corrélation entre vos logs et vos traces d’application en suivant les instructions de journalisation PHP pour APM. Cela vous permet d’ajouter automatiquement des identifiants de trace et de span à vos logs.
Il peut être utile d’enrichir le contexte de vos logs et événements. Monolog propose différents moyens de définir des données de contexte propres à chaque thread, qui sont ensuite automatiquement envoyées avec tous les événements. Par exemple, pour loguer un événement accompagné de données de contexte, utilisez ce qui suit :
Le préprocesseur de Monolog comporte une fonctionnalité de rappel simple qui enrichit vos événements en ajoutant les métadonnées de votre choix (par exemple, l’ID de session ou l’ID de requête) :
<?php$log->pushProcessor(function($record){// Enregistrer l'utilisateur actuel
$user=Acme::getCurrentUser();$record['context']['user']=array('name'=>$user->getName(),'username'=>$user->getUsername(),'email'=>$user->getEmail(),);// Ajouter différents tags
$record['ddtags']=array('key'=>'value');// Ajouter des données de contexte générales
$record['extra']['key']='value';return$record;});
Il peut être utile d’enrichir le contexte de vos logs et événements. Zend-Log propose différents moyens de définir des données de contexte propres à chaque thread, qui sont ensuite automatiquement envoyées avec tous les événements. Par exemple, pour loguer un événement accompagné de données de contexte, utilisez ce qui suit :
Suivez les étapes ci-dessous pour ajouter un contexte variable à vos logs à l’aide d’un processeur de session.
Implémentez votre processeur de session :
Dans l’exemple ci-dessous, le processeur a accès aux informations de la session actuelle et enrichit l’entrée de log en y ajoutant des données telles que les attributs requestId, sessionId, etc.
<?phpnamespaceAcme\Bundle\MonologBundle\Log;useSymfony\Component\HttpFoundation\Session\Session;classSessionRequestProcessor{private$session;private$sessionId;private$requestId;private$_server;private$_get;private$_post;publicfunction__construct(Session$session){$this->session=$session;}publicfunctionprocessRecord(array$record){if(null===$this->requestId){if('cli'===php_sapi_name()){$this->sessionId=getmypid();}else{try{$this->session->start();$this->sessionId=$this->session->getId();}catch(\RuntimeException$e){$this->sessionId='????????';}}$this->requestId=substr(uniqid(),-8);$this->_server=array('http.url'=>(@$_SERVER['HTTP_HOST']).'/'.(@$_SERVER['REQUEST_URI']),'http.method'=>@$_SERVER['REQUEST_METHOD'],'http.useragent'=>@$_SERVER['HTTP_USER_AGENT'],'http.referer'=>@$_SERVER['HTTP_REFERER'],'http.x_forwarded_for'=>@$_SERVER['HTTP_X_FORWARDED_FOR']);$this->_post=$this->clean($_POST);$this->_get=$this->clean($_GET);}$record['http.request_id']=$this->requestId;$record['http.session_id']=$this->sessionId;$record['http.url']=$this->_server['http.url'];$record['http.method']=$this->_server['http.method'];$record['http.useragent']=$this->_server['http.useragent'];$record['http.referer']=$this->_server['http.referer'];$record['http.x_forwarded_for']=$this->_server['http.x_forwarded_for'];return$record;}protectedfunctionclean($array){$toReturn=array();foreach(array_keys($array)as$key){if(false!==strpos($key,'password')){// Do not add
}elseif(false!==strpos($key,'csrf_token')){// Do not add
}else{$toReturn[$key]=$array[$key];}}return$toReturn;}}
Ajoutez ce qui suit pour intégrer le processeur avec Symfony :
Ajoutez ce qui suit pour intégrer Monolog à votre framework :
<?php// Vérifier que la bibliothèque Monolog est bien chargée
//use Monolog\Logger;
//use Monolog\Handler\StreamHandler;
//use Monolog\Formatter\JsonFormatter;
// Avec l'instance Monolog suivante
$monolog=...///// Configuration du log shipper
$formatter=newJsonFormatter();$stream=newStreamHandler(__DIR__.'/application-json.log',Logger::DEBUG);$stream->setFormatter($formatter);$monolog->pushHandler($stream);return$r;
Dans votre répertoire de configuration /chemin/vers/répertoire/configuration/, ajoutez ce qui suit aux fichiers config_dev.yml et config_prod.yml. Modifiez l’exemple afin d’adapter la configuration à vos environnements de développement et de production.
# app/config/config.ymlmonolog:# Supprimer la mise en commentaire de cette section si vous avez besoin d'un processeur.# Processor :# session_processor:# class: Acme\Bundle\MonologBundle\Log\SessionRequestProcessor# arguments: [ @session ]# tags:# - { name: monolog.processor, method: processRecord }json_formatter:class:Monolog\Formatter\JsonFormatterhandlers:# Configuration du log shipperto_json_files:# Enregistrer les logs dans var/logs/(environment).logtype:streampath:"%kernel.logs_dir%/%kernel.environment%.log"# Inclut tous les canaux (doctrine, erreurs, etc.)channels:~# Utiliser le formatteur JSONformatter:monolog.json_formatter# Définir le niveau de journalisation (par exemple, debug, error ou alert)level:debug
Dans votre répertoire de configuration /chemin/vers/répertoire/configuration/, ajoutez ce qui suit aux fichiers config_dev.yml et config_prod.yml. Modifiez l’exemple afin d’adapter la configuration à vos environnements de développement et de production.
monolog:handlers:# Configuration du log shipperto_json_files:# Enregistrer les logs dans var/logs/(environment).logtype:streampath:"%kernel.logs_dir%/%kernel.environment%.log"# Utiliser le formateur JSONformatter:monolog.json_formatter# Définir le niveau de journalisation (par exemple, debug, error ou alert)level:debug
La fonction \DDTrace\current_context() a été ajoutée avec la version 0.61.0.
Ajoutez ce qui suit :
<?phpnamespaceApp\Providers;useIlluminate\Support\ServiceProvider;classAppServiceProviderextendsServiceProvider{/**
* Enregistrer des services d'application.
*
* @return void
*/publicfunctionregister(){// Récupérer l'instance Monolog
$monolog=logger()->getLogger();if(!$monologinstanceof\Monolog\Logger){return;}// Facultatif : utiliser le format JSON
$useJson=false;foreach($monolog->getHandlers()as$handler){if(method_exists($handler,'setFormatter')){$handler->setFormatter(new\Monolog\Formatter\JsonFormatter());$useJson=true;}}// Injecter l'ID de trace et de span pour associer l'entrée de log à la trace APM
$monolog->pushProcessor(function($record)use($useJson){$context=\DDTrace\current_context();if($useJson===true){$record['extra']['dd']=['trace_id'=>$context['trace_id'],'span_id'=>$context['span_id'],];}else{$record['message'].=sprintf(' [dd.trace_id=%d dd.span_id=%d]',$context['trace_id'],$context['span_id']);}return$record;});}/**
* Bootstrap des services d'application.
*
* @return void
*/publicfunctionboot(){//
}}