v13.39.0. Pour les opérations de base, consultez Journalisation, et pour préparer le provider, consultez Développement de packages.
Choisir le point d’extension nécessaire
Si un driver existant suffit, il n’est pas nécessaire d’en ajouter un nouveau.
Les classes
via et tap sont résolues par le conteneur, l’injection par constructeur est donc disponible. tap est un ajustement effectué lors de la création du canal, et non un hook exécuté à chaque écriture d’une entrée de log.
Dans
logging.channels.audit, audit est le nom du canal. Le driver qu’il contient est le nom de la méthode de création. Log::channel('audit') sélectionne un nom de canal : vous pouvez donc changer de driver plus tard tout en conservant le nom utilisé par l’appelant.Exposer d’abord une factory avec custom et via
Dans un package fictifAcme\Audit, nous fournissons une factory pour la sortie vers un fichier. Placez-la dans src/Logging/CreateAuditLogger.php, chargeable via PSR-4.
channels existant de config/logging.php. Conservez les réglages existants de default et de stack.
LogManager::createCustomDriver() récupère la classe via depuis le conteneur et l’appelle avec le tableau de configuration du canal comme unique argument. Avec cette seule approche, aucun provider d’enregistrement de driver n’est nécessaire.
level au StreamHandler. LogManager n’applique pas uniformément le level de la configuration au logger renvoyé par une factory custom. Si vous ajoutez vos propres options de configuration, appliquez-les également dans la factory.
Utiliser extend pour fournir un nom de driver propre
Si vous souhaitez exposer une configurationdriver: acme-audit à l’application consommatrice, enregistrez un driver utilisant la même factory. Étendez le service log de Laravel dans la méthode boot() de src/AuditServiceProvider.php.
channels.audit précédente par la suivante. via n’est plus nécessaire.
- Le
LogServiceProviderde Laravel enregistrelogen singleton.callAfterResolving()attend si le service n’est pas encore résolu, et applique aussi l’enregistrement à l’instance s’il l’est déjà. Pour plus de détails, consultez Hooks après résolution de service. extend()ne fait qu’enregistrer la closure de création. Ni la création du canal ni l’écriture de logs n’ont lieu au moment de l’enregistrement de ce callback.callCustomCreator()transmet$appet le tableau de configuration du canal à la closure. Ces arguments diffèrent de ceux transmis à une factoryvia.- Enregistrer à nouveau le même nom de driver écrase la closure de création. N’utilisez pas de noms intégrés comme
single, ni de noms susceptibles d’entrer en conflit avec d’autres packages.
logging.default ni l’ensemble des logging.channels existants.
Les canaux sont conservés par nom
LogManager::get() stocke les canaux résolus dans $channels. Lorsqu’un canal du même nom est demandé, l’objet conservé est renvoyé sans relire le tableau de configuration.
Il s’agit d’une conservation d’objets au sein du LogManager courant, distincte du cache de configuration stocké dans un fichier. Modifier config() ou ré-enregistrer extend() ne suffit pas à remplacer les Handlers déjà créés.
$same est le même objet que $before. Une fois que forgetChannel('audit') a libéré la conservation dans le Manager, la récupération suivante génère $after à partir de la nouvelle configuration.
forgetChannel ne met pas à jour les références existantes
forgetChannel() se contente de supprimer l’entrée dans le Manager.
- Un service qui conserve
$beforepeut continuer à utiliser l’ancien logger. Ce n’est pas une opération qui remplace les références existantes par le nouvel objet. - Une stack déjà générée, par exemple via
Log::channel('stack'), possède son propre Monolog indépendant qui regroupe les Handlers et Processors des canaux enfants. AppelerforgetChannel()uniquement sur un enfant ne modifie pas la composition de la stack existante. Si nécessaire, libérez également la conservation du nom de canal de cette stack, puis récupérez-la à nouveau. forgetChannel()n’appelle pas lui-mêmeclose()sur les Handlers. Cette API ne garantit pas la fermeture des connexions ni le vidage des buffers.
L’intégration dans une stack nécessite aussi des opérations compatibles Monolog
Un driver personnalisé peut renvoyer une implémentation dePsr\Log\LoggerInterface, mais createStackDriver() de Laravel appelle getHandlers() et getProcessors() sur les canaux enfants. Ces méthodes ne font pas partie de l’interface PSR.
Renvoyer n’importe quel logger PSR ne garantit pas le fonctionnement dans une stack. Un package qui prend aussi en charge l’intégration dans une stack doit donc, comme dans l’exemple, renvoyer un Monolog, ou bien documenter explicitement le périmètre d’utilisation et le tester.
Vérifier la résolution réelle des canaux, pas seulement des mocks
Log::shouldReceive('channel') seul ne permet pas de vérifier l’enregistrement du provider, la sélection de la factory ni l’application de la configuration. L’exemple suivant fait passer les appels par le véritable Manager et la véritable factory dans l’environnement de test du package.
Utilisez php://memory comme destination de test. Ici, on vérifie la construction du canal et la configuration du Handler, sans écrire de log.
Vérifications à ajouter pour la maintenance à long terme
Sources primaires consultées
- Documentation officielle de Laravel : Logging
- Framework v13.39.0 : création, extension et libération dans LogManager
- Framework v13.39.0 : enveloppement et transfert des méthodes dans Logger
- Framework v13.39.0 : enregistrement singleton dans LogServiceProvider
- Framework v13.39.0 : ServiceProvider::callAfterResolving
- Framework v13.39.0 : RebindsCallbacksToSelf
- Tests officiels de Laravel : LogManagerTest