wake-up-neo.com

benutzerdefinierte Protokolldatei für verschiedene Aufgaben

Können wir eine benutzerdefinierte Protokolldatei für verschiedene Zwecke in laravel 5.2 erstellen. Wie für auftragsbezogene Protokolleinträge, die in "order.log" enthalten sein sollten, und für Zahlungen, die mit Zahlungsbezügen zu tun haben, sollte der Eintrag in payments.log protokolliert werden

Ich möchte den bestmöglichen Laravel-Weg finden.

Derzeit können wir nur die Häufigkeit der Protokolldateien ändern (wie täglich, einzeln) oder den Namen der Protokolldatei, die nicht die Standardeinstellung ist, d. H. Laravel.log

26
Gaurav Bakshi

Es gibt einen einfachen Weg:

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);

Ausgabe in logs/order.log:

[2017-04-30 00:00:00] order.INFO: OrderLog {"orderId":10, "description":"Some description"} []
34
massreuy

Los geht's ... Ich habe so viel Zeit damit verbracht, Monolog um benutzerdefinierte Funktionen zu erweitern, die DAS auf die richtige Art und Weise tun. Ich habe sooooo viele verschiedene Arten ausprobiert, aber alles war ein bisschen abgedreht. Endlich habe ich einen guten Weg gefunden, um diese Funktionalität zum Laufen zu bringen ...

Da die Anwendung groß ist, benötigte ich separate Protokolldateien und pflegte die vorhandene Laravel-Protokollschnittstelle so weit wie möglich. Ich brauchte so etwas wie:

Log::write('audit', 'User logged in to the app.');
Log::info('event', 'User sent out 2 emails.');

Die Lösung:

App\Providers\AppServiceProvider.php (zur Registrierungsfunktion hinzufügen)

//Facade to Object binding
$this->app->bind('chanellog', 'App\Helpers\ChannelWriter');

config\app.php (zu Aliases hinzufügen)

//Custom Alias Class
'ChannelLog' => App\Contracts\Facades\ChannelLog::class,

App\Contracts\Facades\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
            );
        }
    }

}

Danach können Sie in einer beliebigen Datei Folgendes tun:

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])
}
33
ShQ

Sie können die Protokollfunktionen erneut verwenden, um verschiedene Protokolltypen in verschiedene Dateien zu schreiben. Dies kann durch Bearbeiten der bootstrap/app.php-Datei erfolgen:

$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);
});

Dann können Sie in Ihrem Code Folgendes tun:

Log::info('Order was created', ['ORDER-123']);

Log::warning('User login', ['USER-1']);

Sie können diese Methode verwenden, um alle verfügbaren Protokollfunktionen zu bearbeiten:

  • DEBUGGEN
  • INFO
  • BEACHTEN
  • WARNUNG
  • ERROR
  • KRITISCH
  • WARNEN
  • NOTFALL
11
Niraj Shah

Um die Antwort von ShQ zu erweitern:

Ein Problem, das mir aufgefallen ist, ist, dass das Protokoll mit [] [] angehängt wird. Dies sind die leeren Array-Werte für $context und $extra in LineFormatter.format();

dh vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php

Es gibt zwei Möglichkeiten, um dies zu erreichen: Entweder stellen Sie ein Format bereit, das dem Konstruktor von LineFormatter kein Extra oder Kontext enthält, oder stellen Sie das vierte Argument $ignoreEmptyContextAndExtra = true bereit.

Alle Dateien in ShQs Antwort bleiben gleich, ChannelStreamHandler muss sich jedoch ändern.

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);
        }
    }

}

Die wichtigste Änderung besteht darin, den vierten Parameter von wahr anzugeben, der $ignoreEmptyContextAndExtra ist. Dieser Parameter weist LineFormatter an, entweder context von extra Arrays zu ignorieren, wenn sie leer sind:

$formatter = new LineFormatter(null, null, false, true);
$this->setFormatter($formatter);

Sie müssen auch sicherstellen, dass Ihr Monolog 1.22 ausgeführt wird, da es einen Bugfix für ignoreEmptyContextAndExtra enthält.

Ich habe auch eine Überschreibung für info () zur ChannelWritter-Klasse hinzugefügt:

public function info($channel, $message, array $context = [])
{
    $level = array_flip($this->levels)[$this->channels[$channel]['level']];
    $this->writeLog($channel, $level, $message, $context);
}

Außerdem war ich mit dem "Lazy Load Logger" in der ShQ-Lösung, die so modifiziert wurde, dass sie den Service Provider/IoC verwendet, nicht zufrieden

Ersetzen Sie 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);
}

und in deiner AppServiceProvider:

    $this->app->bind('eventlog', function () {
        return new Logger('event');
    });

    $this->app->bind('auditlog', function () {
        return new Logger('audit');
    });

Ich werde versuchen, dies in einem Paket zusammenzufassen.

6
wired00

Dies wird jetzt viel einfacher unterstützt

  1. Erstellen Sie einen Kanal

    goto: app/config/logging.php, fügen Sie unter channels array Ihren benutzerdefinierten Kanal hinzu, d

    'Zahlungen' => [
     'driver' => 'single', 
     'path' => Speicherpfad ('logs/payments.log'), 
     'level' => 'info', 
    ],
  2. Schreiben Sie in Ihre Route oder Ihren Controller in dieses Protokoll

        Log::channel('payments')->info('A transaction has been made!');
    
  3. Die Zahlungsprotokolle finden Sie unter /storage/logs/payments.log

HINWEIS: erweiterbar, um Ihre Anforderungen zu verbessern

Laravel Version 5.6 Docs

4
Faiz Khan

Ich habe meine eigene Log-Funktion verwaltet, die in der Datei helper.php im App-Verzeichnis abgelegt werden kann.

if ( ! function_exists( 'write_log' ) ) {
    /**
     * Write log to log file
     *
     * @param string|array|object $log
     */
    function write_log( $log ) {
        if ( env('APP_LOG_LEVEL', 'debug') == 'debug' ) {
            if ( is_array( $log ) || is_object( $log ) ) {
                file_put_contents(laravelInstallDir().'../debug.log', print_r( $log, true ), FILE_APPEND);
            } else {
                file_put_contents(laravelInstallDir().'../debug.log', $log, FILE_APPEND);
            }
        }
    }
}

Bitte passen Sie den Pfad laravelInstallDir (). '../debug.log' nach Bedarf an

0
Manchumahara

Schnellste Möglichkeit, das Protokoll in verschiedene Dateien auszugeben

Log::useFiles('path/to/file.log');
Log::info('Info');
0
Deepak Pandey
Solution:

step1: create a channel inside config/logging.php file

example :

'channels' => [
    'single' => [
    'driver' => 'single', 
    'path' => storage_path('logs/laravel.log'),
    'level' => 'debug',
],

'web' => [
      'driver' => 'single',
      'path' => storage_path('logs/web/web.log'),
   ],

]

Step2: Now set dynamic path from the controller  like this

config(['logging.channels.web.path' => storage_path('logs/web/'.time().'.log')]);

Step3 : now generate your log

  Log::channel('web')->info("your message goes here");

Enjoy :)
0
Kundan roy

Basierend auf der ShQ-Antwort, einem kürzeren und einfacheren Logger-Helfer, mit dem Sie sich spontan bei einer benutzerdefinierten Datei anmelden können. Sie können auch Ihren benutzerdefinierten Handler hinzufügen und den Dateipfad festlegen.

App\Helfer

<?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 (zur Registrierungsfunktion hinzufügen)

//Facade to Object binding
$this->app->bind('LogToChannels', 'App\Helpers\LogToChannels');

config\app.php (zu Aliasnamen hinzufügen)

// Custom Alias Class
'Log' => App\Contracts\Facades\LogToChannels::class

Dann können Sie überall in Ihrer App anrufen

Log::info('logger_name', 'Log message');
Log::error('other_logger_name', 'Log message', $someContext);

Sie können sogar Ihre Loggerausgabe durch Aufrufen anpassen

Log::addChannel('channel_name', $customHandler);

Sie können darauf zugreifen, wenn Sie den Namen an einer beliebigen Stelle in Ihrer App aufrufen.

0

Für mich in Laravel 5.3 bin ich nicht sicher, ob es meine Installation war, aber ich fand, dass die Bootstrap/app.php für mich nicht funktionierte.

Ich musste dies in app/Providers/AppServiceProvider.php einfügen.

n.b. Hier hatte ich vorher die Einstellung des Log-Levels von config, also habe ich 3 Log-Handler.

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);

}
0
tristanbailey