php - modificar - Archivo de registro personalizado de laravel 5.2 para diferentes tareas
login personalizado laravel (8)
¿Podemos crear un archivo de registro personalizado para diferentes propósitos en laravel 5.2 como para las entradas de registro relacionadas con el pedido que deberían estar en order.log y para las cosas relacionadas con el pago, la entrada debe registrarse en changes.log?
Quiero encontrar la mejor manera posible de Laravel.
Actualmente solo podemos cambiar la frecuencia del archivo de registro (como diario, individual) o podemos cambiar el nombre del archivo de registro que no sea el predeterminado, por ejemplo, laravel.log
Aquí tienes ... He dedicado mucho tiempo para agregar una funcionalidad personalizada a Monolog que puede hacer ESO de manera adecuada. Lo intenté de muchas maneras diferentes, pero todo fue un poco raro. Finalmente encontré una buena manera de hacer funcionar esta funcionalidad ...
Como la aplicación es grande, necesitaba archivos de registro separados y mantener la interfaz de registro existente de Laravel tanto como fuera posible. Necesitaba algo como:
Log::write(''audit'', ''User logged in to the app.'');
Log::info(''event'', ''User sent out 2 emails.'');
La solución:
App / Providers / AppServiceProvider.php (agregar a la función de registro)
//Facade to Object binding
$this->app->bind(''chanellog'', ''App/Helpers/ChannelWriter'');
config / app.php (agregar a los alias)
//Custom Alias Class
''ChannelLog'' => App/Contracts/Facades/ChannelLog::class,
Aplicación / Contratos / Fachadas / ChannelLog.php
<?php
namespace App/Contracts/Facades;
use Illuminate/Support/Facades/Facade;
/**
* @see /Illuminate/Log/Writer
*/
class ChannelLog extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return ''chanellog'';
}
}
App / Helpers / ChannelWriter.php
<?php
namespace App/Helpers;
use Monolog/Logger;
use App/Helpers/ChannelStreamHandler;
class ChannelWriter
{
/**
* The Log channels.
*
* @var array
*/
protected $channels = [
''event'' => [
''path'' => ''logs/audit.log'',
''level'' => Logger::INFO
],
''audit'' => [
''path'' => ''logs/audit.log'',
''level'' => Logger::INFO
]
];
/**
* The Log levels.
*
* @var array
*/
protected $levels = [
''debug'' => Logger::DEBUG,
''info'' => Logger::INFO,
''notice'' => Logger::NOTICE,
''warning'' => Logger::WARNING,
''error'' => Logger::ERROR,
''critical'' => Logger::CRITICAL,
''alert'' => Logger::ALERT,
''emergency'' => Logger::EMERGENCY,
];
public function __construct() {}
/**
* Write to log based on the given channel and log level set
*
* @param type $channel
* @param type $message
* @param array $context
* @throws InvalidArgumentException
*/
public function writeLog($channel, $level, $message, array $context = [])
{
//check channel exist
if( !in_array($channel, array_keys($this->channels)) ){
throw new InvalidArgumentException(''Invalid channel used.'');
}
//lazy load logger
if( !isset($this->channels[$channel][''_instance'']) ){
//create instance
$this->channels[$channel][''_instance''] = new Logger($channel);
//add custom handler
$this->channels[$channel][''_instance'']->pushHandler(
new ChannelStreamHandler(
$channel,
storage_path() .''/''. $this->channels[$channel][''path''],
$this->channels[$channel][''level'']
)
);
}
//write out record
$this->channels[$channel][''_instance'']->{$level}($message, $context);
}
public function write($channel, $message, array $context = []){
//get method name for the associated level
$level = array_flip( $this->levels )[$this->channels[$channel][''level'']];
//write to log
$this->writeLog($channel, $level, $message, $context);
}
//alert(''event'',''Message'');
function __call($func, $params){
if(in_array($func, array_keys($this->levels))){
return $this->writeLog($params[0], $func, $params[1]);
}
}
}
App / Helpers / ChannelStreamHandler.php
<?php
namespace App/Helpers;
use Monolog/Handler/StreamHandler;
/**
* Use channels to log into separate files
*
* @author Peter Feher
*/
class ChannelStreamHandler extends StreamHandler
{
/**
* Channel name
*
* @var String
*/
protected $channel;
/**
* @param String $channel Channel name to write
* @see parent __construct for params
*/
public function __construct($channel, $stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
{
$this->channel = $channel;
parent::__construct($stream, $level, $bubble);
}
/**
* When to handle the log record.
*
* @param array $record
* @return type
*/
public function isHandling(array $record)
{
//Handle if Level high enough to be handled (default mechanism)
//AND CHANNELS MATCHING!
if( isset($record[''channel'']) ){
return (
$record[''level''] >= $this->level &&
$record[''channel''] == $this->channel
);
} else {
return (
$record[''level''] >= $this->level
);
}
}
}
Después de esto, puedes hacerlo en cualquier archivo:
use ChannelLog as Log;
...
function myFunction(){
//Recommended (writes INFO to logs/event.log)
Log::write(''event'', ''User sent out 3 voucher.'')
//Possible to use (writes ALERT to logs/audit.log)
Log::alert(''audit'', ''User modified xyz entry.'')
//Or even:
Log::write(''audit'', ''User modified xyz entry.'', [''user''=>1])
}
Basado en la respuesta de ShQ, un ayudante de registro más corto y simple que le permite iniciar sesión en un archivo personalizado sobre la marcha. También puede agregar su controlador personalizado y establecer la ruta del archivo.
App / Helper
<?php
/**
* Logger helper to log into different files
*
* @package App/Helpers
* @author Romain Laneuville <[email protected]>
*/
namespace App/Helpers;
use Monolog/Logger;
use Monolog/Handler/HandlerInterface;
use Monolog/Handler/StreamHandler;
/**
* Class LogToChannels
*
* @package App/Helpers
*/
class LogToChannels
{
/**
* The LogToChannels channels.
*
* @var Logger[]
*/
protected $channels = [];
/**
* LogToChannels constructor.
*/
public function __construct()
{
}
/**
* @param string $channel The channel to log the record in
* @param int $level The error level
* @param string $message The error message
* @param array $context Optional context arguments
*
* @return bool Whether the record has been processed
*/
public function log(string $channel, int $level, string $message, array $context = []): bool
{
// Add the logger if it doesn''t exist
if (!isset($this->channels[$channel])) {
$handler = new StreamHandler(
storage_path() . DIRECTORY_SEPARATOR . ''logs'' . DIRECTORY_SEPARATOR . $channel . ''.log''
);
$this->addChannel($channel, $handler);
}
// LogToChannels the record
return $this->channels[$channel]->{Logger::getLevelName($level)}($message, $context);
}
/**
* Add a channel to log in
*
* @param string $channelName The channel name
* @param HandlerInterface $handler The channel handler
* @param string|null $path The path of the channel file, DEFAULT storage_path()/logs
*
* @throws /Exception When the channel already exists
*/
public function addChannel(string $channelName, HandlerInterface $handler, string $path = null)
{
if (isset($this->channels[$channelName])) {
throw new /Exception(''This channel already exists'');
}
$this->channels[$channelName] = new Logger($channelName);
$this->channels[$channelName]->pushHandler(
new $handler(
$path === null ?
storage_path() . DIRECTORY_SEPARATOR . ''logs'' . DIRECTORY_SEPARATOR . $channelName . ''.log'' :
$path . DIRECTORY_SEPARATOR . $channelName . ''.log''
)
);
}
/**
* Adds a log record at the DEBUG level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function debug(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::DEBUG, $message, $context);
}
/**
* Adds a log record at the INFO level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function info(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::INFO, $message, $context);
}
/**
* Adds a log record at the NOTICE level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function notice(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::NOTICE, $message, $context);
}
/**
* Adds a log record at the WARNING level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function warn(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::WARNING, $message, $context);
}
/**
* Adds a log record at the WARNING level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function warning(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::WARNING, $message, $context);
}
/**
* Adds a log record at the ERROR level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function err(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::ERROR, $message, $context);
}
/**
* Adds a log record at the ERROR level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function error(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::ERROR, $message, $context);
}
/**
* Adds a log record at the CRITICAL level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function crit(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::CRITICAL, $message, $context);
}
/**
* Adds a log record at the CRITICAL level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return Boolean Whether the record has been processed
*/
public function critical(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::CRITICAL, $message, $context);
}
/**
* Adds a log record at the ALERT level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function alert(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::ALERT, $message, $context);
}
/**
* Adds a log record at the EMERGENCY level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function emerg(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::EMERGENCY, $message, $context);
}
/**
* Adds a log record at the EMERGENCY level.
*
* @param string $channel The channel name
* @param string $message The log message
* @param array $context The log context
*
* @return bool Whether the record has been processed
*/
public function emergency(string $channel, string $message, array $context = []): bool
{
return $this->log($channel, Logger::EMERGENCY, $message, $context);
}
}
App / Providers / AppServiceProvider.php (agregar a la función de registro)
//Facade to Object binding
$this->app->bind(''LogToChannels'', ''App/Helpers/LogToChannels'');
config / app.php (agregar a los alias)
// Custom Alias Class
''Log'' => App/Contracts/Facades/LogToChannels::class
Entonces, en cualquier parte de tu aplicación puedes llamar
Log::info(''logger_name'', ''Log message'');
Log::error(''other_logger_name'', ''Log message'', $someContext);
Incluso puede personalizar la salida de su registrador llamando
Log::addChannel(''channel_name'', $customHandler);
Y será accesible cuando llames su nombre en cualquier lugar de tu aplicación.
Hay una forma sencilla:
use Monolog/Logger;
use Monolog/Handler/StreamHandler;
$log = [''orderId'' => 10,
''description'' => ''Some description''];
$orderLog = new Logger(order);
$orderLog->pushHandler(new StreamHandler(storage_path(''logs/order.log'')), Logger::INFO);
$orderLog->info(''OrderLog'', $log);
Salida en logs / order.log:
[2017-04-30 00:00:00] order.INFO: OrderLog {"orderId":10, "description":"Some description"} []
La manera más rápida de generar registros en diferentes archivos
Log::useFiles(''path/to/file.log'');
Log::info(''Info'');
Para ampliar la respuesta de ShQ:
Un problema que noté es que el registro se agregará con [] []
, que son los valores de la matriz vacía para $context
y $extra
en LineFormatter.format();
es decir, vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php
Hay dos maneras de LineFormatter
esto, ya sea proporcionar un formato que no incluya extra o contexto para el constructor de LineFormatter
, o proporcionar el cuarto argumento $ignoreEmptyContextAndExtra
= true
.
Todos los archivos dentro de la respuesta de ShQ siguen siendo los mismos, pero ChannelStreamHandler
debe cambiar.
ChannelStreamHandler:
<?php
namespace App/Helpers;
use Monolog/Formatter/LineFormatter;
use Monolog/Handler/StreamHandler;
use Monolog/Logger;
/**
* Use channels to log into separate files
*
*/
class ChannelStreamHandler extends StreamHandler
{
/**
* Channel name
*
* @var String
*/
protected $channel;
/**
* @param String $channel Channel name to write
* @param bool|int $stream
* @param bool|int $level
* @param bool $bubble
* @param null $filePermission
* @param bool $useLocking
* @see parent __construct for params
*/
public function __construct(
$channel,
$stream,
$level = Logger::DEBUG,
$bubble = true,
$filePermission = null,
$useLocking = false
) {
$this->channel = $channel;
$formatter = new LineFormatter(null, null, false, true);
$this->setFormatter($formatter);
parent::__construct($stream, $level, $bubble);
}
/**
* When to handle the log record.
*
* @param array $record
* @return bool
*/
public function isHandling(array $record)
{
//Handle if Level high enough to be handled (default mechanism)
//AND CHANNELS MATCHING!
if (isset($record[''channel''])) {
return ($record[''level''] >= $this->level && $record[''channel''] == $this->channel);
} else {
return ($record[''level''] >= $this->level);
}
}
}
El cambio importante es proporcionar el cuarto parámetro de true, que es $ignoreEmptyContextAndExtra
. Este LineFormatter
le dice a LineFormatter
que ignore cualquiera de los context
de arreglos extra
si está vacío:
$formatter = new LineFormatter(null, null, false, true);
$this->setFormatter($formatter);
Debe asegurarse de asegurar también su monolog 1.22 en ejecución porque incluye una corrección de errores relacionada con ignoreEmptyContextAndExtra
.
También agregué un reemplazo para info () a la clase ChannelWritter
:
public function info($channel, $message, array $context = [])
{
$level = array_flip($this->levels)[$this->channels[$channel][''level'']];
$this->writeLog($channel, $level, $message, $context);
}
Además, no estaba contento con el "registrador de carga lenta" en la solución de ShQ modificada para usar el proveedor de servicios / IoC
Reemplace ChannelWriter.writeLog()
:
public function writeLog(string $channel, string $level, string $message, array $context = [])
{
if (!in_array($channel, array_keys($this->channels))) {
throw new InvalidArgumentException(''Invalid channel used.'');
}
$logger = /App::make("{$channel}log");
$channelHandler = new ChannelStreamHandler(
$channel,
storage_path() . ''/'' . $this->channels[$channel][''path''],
$this->channels[$channel][''level'']
);
$logger->pushHandler($channelHandler);
$logger->{$level}($message);
}
y en su AppServiceProvider
:
$this->app->bind(''eventlog'', function () {
return new Logger(''event'');
});
$this->app->bind(''auditlog'', function () {
return new Logger(''audit'');
});
Intentaré agrupar esto en un paquete.
Para el registro más simple
Crear un canal
goto:
app/config/logging.php
en la matriz de
channels
añadir su canal personalizado, es decir''payments'' => [ ''driver'' => ''single'', ''path'' => storage_path(''logs/payments.log''), ''level'' => ''info'', ],
En su ruta o controlador escriba en este registro.
Log::channel(''payments'')->info(''A transaction has been made!'');
Los registros de pago se pueden encontrar en
/storage/logs/payments.log
NOTA: extensible para realzar furthur sus requerimientos.
Laravel version 5.6 Docs
lo siento por el formato sin sentido
Para mí, en Laravel 5.3, no estoy seguro de si fue mi instalación anteriormente, pero encontré que bootstrap / app.php no me funcionó.
Necesitaba poner esto en app / Providers / AppServiceProvider.php.
nb Aquí es donde tenía la configuración del nivel de registro de la configuración anterior, por lo que acabo con 3 controladores de registro.
public function register()
{
$monolog = Log::getMonolog();
foreach ($monolog->getHandlers() as $handler) {
$handler->setLevel(Config::get(''app.log_level''));
}
$bubble = false;
$infoStreamHandler = new /Monolog/Handler/StreamHandler( storage_path("logs/info.log"), /Monolog/Logger::INFO, $bubble);
$monolog->pushHandler($infoStreamHandler);
$warningStreamHandler = new /Monolog/Handler/StreamHandler( storage_path("logs/warning.log"), /Monolog/Logger::WARNING, $bubble);
$monolog->pushHandler($warningStreamHandler);
}
Puede intentar reutilizar las funciones de registro para escribir diferentes tipos de registros en diferentes archivos. Esto se puede hacer editando el archivo bootstrap/app.php
:
$app->configureMonologUsing(function($monolog) {
$bubble = false;
$infoStreamHandler = new Monolog/Handler/StreamHandler( storage_path("/logs/orders.log"), Monolog/Logger::INFO, $bubble);
$monolog->pushHandler($infoStreamHandler);
$warningStreamHandler = new Monolog/Handler/StreamHandler( storage_path("/logs/logins.log"), Monolog/Logger::WARNING, $bubble);
$monolog->pushHandler($warningStreamHandler);
});
Luego en tu código, puedes hacer:
Log::info(''Order was created'', [''ORDER-123'']);
Log::warning(''User login'', [''USER-1'']);
Puede utilizar este método para editar todas las funciones de registro disponibles:
- DEPURAR
- INFO
- DARSE CUENTA
- ADVERTENCIA
- ERROR
- CRÍTICO
- ALERTA
- EMERGENCIA