v13.39.0. Para el uso básico, consulta Logging, y para preparar el provider, Desarrollo de paquetes.
Elige el punto de extensión que necesitas
Si puedes conseguirlo con un driver existente, no hace falta añadir un driver propio.
Las clases de
via y de tap se resuelven desde el contenedor, así que también puedes usar inyección por constructor. tap es un ajuste que se realiza al generar el canal, no un hook que se ejecute cada vez que se escribe una entrada de log.
En
logging.channels.audit, audit es el nombre del canal. El driver que contiene es el nombre del método de creación. Lo que se elige con Log::channel('audit') es el nombre del canal, por lo que aunque cambies el driver más adelante, el código que lo llama puede mantener el mismo nombre.Publica primero una factory con custom y via
En el paquete ficticioAcme\Audit, ofreceremos una factory para la salida a archivo. Colócala en src/Logging/CreateAuditLogger.php, que se carga mediante PSR-4.
channels existente de config/logging.php. Conserva la configuración existente de default y stack.
LogManager::createCustomDriver() obtiene la clase de via desde el contenedor y la llama con el array de configuración del canal como único argumento. Si solo usas este método, no necesitas un provider para registrar el driver.
level explícitamente al StreamHandler. LogManager no aplica de forma general el level de la configuración al logger que devuelve una factory custom. Si añades opciones de configuración propias, también debes aplicarlas en la factory.
Usa extend cuando ofrezcas un nombre de driver propio
Si quieres publicar para la aplicación una configuración comodriver: acme-audit, registra un driver que use la misma factory. Extiende el servicio log de Laravel en el boot() de src/AuditServiceProvider.php.
channels.audit por la siguiente. via ya no es necesario.
- El
LogServiceProviderde Laravel registralogcomo singleton.callAfterResolving()espera si todavía no se ha resuelto y, si ya está resuelto, aplica el registro también a esa instancia. Para más detalles, consulta Hooks posteriores a la resolución de servicios. extend()solo registra el closure de creación. Al registrar este callback no se genera ningún canal ni se escribe ningún log.callCustomCreator()pasa al closure$appy el array de configuración del canal. Son argumentos distintos de los que recibe la factory devia.- Registrar de nuevo el mismo nombre de driver sobrescribe el closure de creación. No uses nombres integrados como
singleni nombres que puedan entrar en conflicto con otros paquetes.
logging.default ni todo el logging.channels existente.
Los canales se retienen por nombre
LogManager::get() guarda los canales resueltos en $channels. Al obtener un canal con el mismo nombre, devuelve el objeto retenido sin volver a leer el array de configuración.
Esto es la retención de objetos dentro del LogManager actual, distinta de la caché de configuración que se guarda en un archivo. Cambiar config() o volver a registrar extend() no sustituye por sí solo los Handlers ya creados.
$same es el mismo objeto que $before. Cuando forgetChannel('audit') libera la retención en el Manager, la siguiente obtención genera $after a partir de la nueva configuración.
forgetChannel no actualiza las referencias existentes
Lo que haceforgetChannel() es eliminar la entrada dentro del Manager.
- Los servicios que conservan
$beforepueden seguir usando el logger antiguo. No es una operación que sustituya las referencias existentes por el nuevo objeto. - Un stack ya generado, por ejemplo con
Log::channel('stack'), tiene su propio Monolog independiente que reúne los Handlers y Processors de los canales hijos. AplicarforgetChannel()solo al hijo no cambia la composición del stack existente. Si es necesario, libera también la retención del nombre de canal de ese stack y vuelve a obtenerlo. forgetChannel()por sí mismo no llama aclose()de los Handlers. No es una API que garantice el cierre de conexiones ni el vaciado de buffers.
Para incorporarlo a un stack también se necesitan operaciones compatibles con Monolog
Un driver propio puede devolver una implementación dePsr\Log\LoggerInterface, pero createStackDriver() de Laravel llama a getHandlers() y getProcessors() en los canales hijos. Estos métodos no forman parte de la interfaz PSR.
Devolver cualquier logger PSR no garantiza que funcione dentro de un stack, así que en los paquetes que también admitan su incorporación a un stack, devuelve un Monolog como en el ejemplo, o indica claramente el alcance de uso y pruébalo.
Verifica la resolución real de canales, no solo con mocks
ConLog::shouldReceive('channel') por sí solo no puedes comprobar el registro del provider, la selección de la factory ni la aplicación de la configuración. A continuación se muestra un ejemplo que pasa por el Manager y la factory reales en el entorno de pruebas de paquetes.
Como destino de salida para las pruebas se indica php://memory. Aquí se verifican la construcción del canal y la configuración del Handler, sin escribir realmente ningún log.
Verificaciones adicionales para el mantenimiento a largo plazo
Fuentes primarias consultadas
- Documentación oficial de Laravel: Logging
- Framework v13.39.0: generación, extensión y liberación de la retención en LogManager
- Framework v13.39.0: envoltura y reenvío de métodos en Logger
- Framework v13.39.0: registro singleton en LogServiceProvider
- Framework v13.39.0: ServiceProvider::callAfterResolving
- Framework v13.39.0: RebindsCallbacksToSelf
- Tests oficiales de Laravel: LogManagerTest