v13.39.0. Per le operazioni di base consulta Logging, per la preparazione del provider consulta Sviluppo di pacchetti.
Scegliere il punto di estensione necessario
Se puoi ottenere il risultato con un driver esistente, non serve aggiungere un driver personalizzato.
Le classi di
via e di tap vengono risolte dal container, quindi puoi usare anche l’iniezione nel costruttore. tap è una regolazione eseguita alla creazione del channel, non un hook eseguito a ogni singola scrittura di log.
audit in logging.channels.audit è il nome del channel. Il driver al suo interno è il nome del metodo di creazione. Con Log::channel('audit') si sceglie il nome del channel, quindi anche se in seguito cambi il driver puoi mantenere invariato il nome usato dal codice chiamante.Esporre prima una factory con custom e via
Nel pacchetto fittizioAcme\Audit forniamo una factory per l’output su file. La collochiamo in src/Logging/CreateAuditLogger.php, caricabile tramite PSR-4.
channels esistente in config/logging.php. Mantieni le configurazioni esistenti di default e stack.
LogManager::createCustomDriver() recupera la classe di via dal container e la invoca passando l’array di configurazione del channel come unico argomento. Con questo solo approccio non serve un provider per registrare il driver.
level allo StreamHandler. LogManager non applica in modo uniforme il level della configurazione al logger restituito da una factory custom. Anche quando aggiungi opzioni di configurazione personalizzate, applicale nella factory.
Usare extend per fornire un nome di driver personalizzato
Se vuoi esporre all’utente una configurazione comedriver: acme-audit, registra un driver che usa la stessa factory. Nel metodo boot() di src/AuditServiceProvider.php estendi il servizio log di Laravel.
channels.audit con la seguente. via non è più necessario.
- Il
LogServiceProviderdi Laravel registralogcome singleton.callAfterResolving()attende se il servizio non è ancora stato risolto e, se è già risolto, applica la registrazione anche a quell’istanza. Per i dettagli consulta Hook di risoluzione dei servizi. extend()registra soltanto la closure di creazione. Al momento della registrazione di questa callback non vengono creati channel né scritti log.callCustomCreator()passa alla closure$appe l’array di configurazione del channel. Gli argomenti sono diversi da quelli passati alla factory divia.- Registrare di nuovo lo stesso nome di driver sovrascrive la closure di creazione. Non usare nomi integrati come
singlené nomi che possano entrare in conflitto con altri pacchetti.
logging.default né l’intero logging.channels esistente.
I channel vengono conservati per nome
LogManager::get() salva i channel risolti in $channels. Quando richiedi un channel con lo stesso nome, restituisce l’oggetto conservato senza rileggere l’array di configurazione.
Si tratta della conservazione degli oggetti all’interno del LogManager corrente, distinta dalla cache della configurazione salvata su file. Modificare config() o registrare di nuovo extend() non basta a sostituire un Handler già creato.
$same è lo stesso oggetto di $before. Quando forgetChannel('audit') rimuove la conservazione nel Manager, alla richiesta successiva $after viene generato dalla nuova configurazione.
forgetChannel non aggiorna i riferimenti esistenti
forgetChannel() si limita a eliminare la voce all’interno del Manager.
- Un servizio che conserva
$beforepuò continuare a usare il vecchio logger. Non è un’operazione che sostituisce i riferimenti esistenti con il nuovo oggetto. - Uno stack già generato, ad esempio con
Log::channel('stack'), possiede un Monolog indipendente che raccoglie gli Handler e i Processor dei channel figli. ApplicareforgetChannel()solo a un figlio non modifica la composizione dello stack esistente. Se necessario, rimuovi la conservazione anche per il nome di channel dello stack e richiedilo di nuovo. forgetChannel()di per sé non chiamaclose()sugli Handler. Non è un’API che garantisce la chiusura di connessioni o buffer.
L’integrazione in uno stack richiede anche operazioni compatibili con Monolog
Un driver personalizzato può restituire un’implementazione diPsr\Log\LoggerInterface, ma createStackDriver() di Laravel chiama getHandlers() e getProcessors() sui channel figli. Questi metodi non fanno parte dell’interfaccia PSR.
Restituire un qualsiasi logger PSR non garantisce che funzioni anche in uno stack, quindi i pacchetti che supportano anche l’integrazione negli stack dovrebbero restituire un Monolog come nell’esempio, oppure documentare chiaramente l’ambito d’uso e testarlo.
Verificare la risoluzione reale dei channel, non solo i mock
Con il soloLog::shouldReceive('channel') non puoi verificare la registrazione del provider, la scelta della factory né l’applicazione della configurazione. Di seguito un esempio che, nell’ambiente di test dei pacchetti, passa per il Manager e la factory reali.
Come destinazione dell’output nei test specifichiamo php://memory. Qui verifichiamo la costruzione del channel e la configurazione dell’Handler, senza scrivere effettivamente log.
Verifiche da aggiungere per la manutenzione a lungo termine
Fonti primarie consultate
- Documentazione ufficiale di Laravel: Logging
- Framework v13.39.0: creazione, estensione e rimozione della conservazione in LogManager
- Framework v13.39.0: wrapping e inoltro dei metodi in Logger
- Framework v13.39.0: registrazione singleton in LogServiceProvider
- Framework v13.39.0: ServiceProvider::callAfterResolving
- Framework v13.39.0: RebindsCallbacksToSelf
- Test ufficiali di Laravel: LogManagerTest