Prologo
Primi Passi
Architettura
Le Basi
- Routing
- Middleware
- Protezione da CSRF
- Controller
- Richieste
- Risposte
- Views
- Blade
- Vite
- URL
- Sessioni
- Validazione
- Errori
- Logging
Approfondimenti
- Artisan
- Broadcasting
- Cache
- Collezioni
- Concorrenza
- Contesto
- Contratti
- Eventi
- File System
- Helpers
- Client HTTP
- Localizzazione
- Notifiche
- Sviluppo di Package
- Processi
- Code
- Rate-limiting
- Stringhe
- Scheduling di Task
Sicurezza
Database
Eloquent ORM
Testing
Package
Logging
- Introduzione
- Configurazione
- Creare Stack di Log
- Scrivere Messaggi di Log
- Personalizzazione del Canale Monolog
- Monitorare i Messaggi di Log con Pail
Introduzione
Per aiutarti a capire meglio cosa succede all’interno della tua applicazione, Laravel fornisce servizi di logging robusti che ti permettono di registrare messaggi in file, nel registro degli errori di sistema e persino su Slack per notificare l’intero team.
Il logging di Laravel si basa sui "canali". Ogni canale rappresenta un modo specifico di scrivere le informazioni di log. Ad esempio, il canale single
scrive i file di log in un unico file, mentre il canale slack
invia i messaggi di log a Slack. I messaggi di log possono essere scritti su più canali in base alla loro gravità.
Dietro le quinte, Laravel utilizza la libreria Monolog, che offre supporto per una varietà di gestori di log potenti. Laravel rende semplice configurare questi gestori, permettendoti di combinarli per personalizzare la gestione dei log della tua applicazione.
Configurazione
Tutte le opzioni di configurazione che controllano il comportamento del logging della tua applicazione si trovano nel file di configurazione config/logging.php
. Questo file ti permette di configurare i canali di log della tua applicazione, quindi assicurati di esaminare ciascuno dei canali disponibili e le loro opzioni. Di seguito esamineremo alcune opzioni comuni.
Per impostazione predefinita, Laravel utilizza il canale stack
per registrare i messaggi. Il canale stack
serve ad aggregare più canali di log in un unico canale. Per maggiori informazioni sulla creazione di stack, consulta la documentazione di seguito.
Driver di canale disponibili
Ogni canale di log è gestito da un "driver". Il driver determina come e dove il messaggio di log viene effettivamente registrato. I seguenti driver di canale di log sono disponibili in ogni applicazione Laravel. Una voce per la maggior parte di questi driver è già presente nel file di configurazione config/logging.php
della tua applicazione, quindi assicurati di rivedere questo file per familiarizzare con il suo contenuto:
Nome | Descrizione |
---|---|
custom |
Un driver che richiama una factory specificata per creare un canale. |
daily |
Un driver Monolog basato su RotatingFileHandler che ruota giornalmente. |
errorlog |
Un driver Monolog basato su ErrorLogHandler . |
monolog |
Un driver factory Monolog che può usare qualsiasi handler Monolog supportato. |
papertrail |
Un driver Monolog basato su SyslogUdpHandler . |
single |
Un canale di log basato su un file singolo o percorso (StreamHandler ). |
slack |
Un driver Monolog basato su SlackWebhookHandler . |
stack |
Un wrapper per facilitare la creazione di canali "multi-canale". |
syslog |
Un driver Monolog basato su SyslogHandler . |
Consulta la documentazione su personalizzazione avanzata dei canali per saperne di più sui driver
monolog
ecustom
.
Configurare il Nome del Canale
Per impostazione predefinita, Monolog viene istanziato con un "nome canale" che corrisponde all’ambiente attuale, come production
o local
. Per modificare questo valore, puoi aggiungere un’opzione name
alla configurazione del tuo canale:
'stack' => [
'driver' => 'stack',
'name' => 'channel-name',
'channels' => ['single', 'slack'],
],
Prerequisiti del Channel
Configurazione dei canali Single e Daily
I canali single
e daily
hanno tre opzioni di configurazione opzionali: bubble
, permission
e locking
.
Nome | Descrizione | Predefinito |
---|---|---|
bubble |
Indica se i messaggi devono propagarsi ad altri canali dopo essere stati gestiti. | true |
locking |
Tenta di bloccare il file di log prima di scriverci. | false |
permission |
Le autorizzazioni del file di log. | 0644 |
Inoltre, la politica di conservazione per il canale daily
può essere configurata tramite la variabile d’ambiente LOG_DAILY_DAYS
o impostando l’opzione di configurazione days
.
Nome | Descrizione | Predefinito |
---|---|---|
days |
Il numero di giorni in cui i file di log giornalieri devono essere mantenuti. | 14 |
Configurare il Canale Papertrail
Il canale papertrail
richiede le opzioni di configurazione host
e port
. Queste possono essere definite tramite le variabili d’ambiente PAPERTRAIL_URL
e PAPERTRAIL_PORT
. Puoi ottenere questi valori da Papertrail.
Configurazione del canale Slack
Il canale slack
richiede un’opzione di configurazione url
. Questo valore può essere definito tramite la variabile d’ambiente LOG_SLACK_WEBHOOK_URL
. Questo URL deve corrispondere a un incoming webhook che hai configurato per il tuo team Slack.
Per impostazione predefinita, Slack riceverà solo i log a livello critical
e superiori; tuttavia, puoi modificare questo comportamento utilizzando la variabile d’ambiente LOG_LEVEL
o modificando l’opzione di configurazione level
all’interno dell’array di configurazione del tuo canale log Slack.
Registrare Avvisi di Deprecazione
PHP, Laravel e altre librerie spesso informano gli utenti che alcune funzionalità sono state deprecate e saranno rimosse in future versioni. Se vuoi registrare questi avvisi di deprecazione, puoi specificare il canale di log preferito deprecations
utilizzando la variabile d’ambiente LOG_DEPRECATIONS_CHANNEL
, oppure nel file di configurazione config/logging.php
della tua applicazione:
'deprecations' => [
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],
'channels' => [
// ...
]
Oppure, puoi definire un canale di log chiamato deprecations
. Se esiste un canale di log con questo nome, verrà sempre utilizzato per registrare le deprecazioni:
'channels' => [
'deprecations' => [
'driver' => 'single',
'path' => storage_path('logs/php-deprecation-warnings.log'),
],
],
Creare Stack di Log
Come menzionato precedentemente, il driver stack
permette di combinare più canali in un unico canale di log per comodità. Per illustrare come utilizzare gli stack di log, diamo un’occhiata a un esempio di configurazione che potresti vedere in un’applicazione in produzione:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['syslog', 'slack'], // [tl! add]
'ignore_exceptions' => false,
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
'replace_placeholders' => true,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
],
Esaminiamo questa configurazione. Innanzitutto, notiamo che il nostro canale stack
aggrega altri due canali tramite l’opzione channels
: syslog
e slack
. Quindi, quando si registrano i messaggi, entrambi questi canali avranno la possibilità di registrare il messaggio. Tuttavia, come vedremo più avanti, se questi canali registrano effettivamente il messaggio può dipendere dalla severità / "level" del messaggio.
Livelli di Log
Fai attenzione all’opzione di configurazione level
presente nelle configurazioni dei canali syslog
e slack
nell’esempio sopra. Questa opzione determina il "livello" minimo che un messaggio deve avere per essere registrato dal canale. Monolog, che alimenta i servizi di logging di Laravel, offre tutti i livelli di log definiti nella specifica RFC 5424. In ordine decrescente di gravità, questi livelli di log sono: emergency, alert, critical, error, warning, notice, info e debug.
Quindi, immagina di registrare un messaggio usando il metodo debug
:
Log::debug('Un messaggio informativo.');
Dato la nostra configurazione, il canale syslog
scriverà il messaggio nel log di sistema; tuttavia, poiché il messaggio di errore non è critical
o superiore, non sarà inviato a Slack. Tuttavia, se registriamo un messaggio di emergency
, sarà inviato sia al log di sistema che a Slack poiché il livello emergency
è al di sopra della soglia minima per entrambi i canali:
Log::emergency('Il sistema è giù!');
Scrivere Messaggi di Log
Puoi scrivere informazioni nei log usando la facade Log
facade. Come menzionato precedentemente, il logger fornisce otto livelli di log definiti nella specifica RFC 5424: emergency, alert, critical, error, warning, notice, info e debug:
use Illuminate\Support\Facades\Log;
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
Puoi chiamare uno qualsiasi di questi metodi per registrare un messaggio per il livello corrispondente. Per impostazione predefinita, il messaggio verrà scritto nel canale di log predefinito come configurato nel tuo file di configurazione logging
:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* Mostra il profilo per l'utente dato.
*/
public function show(string $id): View
{
Log::info('Showing the user profile for user: {id}', ['id' => $id]);
return view('user.profile', [
'user' => User::findOrFail($id)
]);
}
}
Informazioni Contestuali
Un array di dati contestuali può essere passato ai metodi di log. Questi dati verranno formattati e mostrati insieme al messaggio di log:
use Illuminate\Support\Facades\Log;
Log::info('User {id} failed to login.', ['id' => $user->id]);
A volte, potresti voler specificare alcune informazioni contestuali che devono essere incluse in tutte le voci di log successive in un canale particolare. Ad esempio, potresti voler registrare un ID richiesta associato a ogni richiesta in entrata nella tua applicazione. Per fare questo, puoi chiamare il metodo withContext
della facade Log
:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
class AssignRequestId
{
/**
* Gestisce una richiesta in arrivo.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$requestId = (string) Str::uuid();
Log::withContext([
'request-id' => $requestId
]);
$response = $next($request);
$response->headers->set('Request-Id', $requestId);
return $response;
}
}
Se desideri condividere informazioni contestuali su tutti i canali di log, puoi invocare il metodo Log::shareContext()
. Questo metodo fornirà le informazioni contestuali a tutti i canali creati e a quelli che saranno creati successivamente:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
class AssignRequestId
{
/**
* Gestisce una richiesta in arrivo.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$requestId = (string) Str::uuid();
Log::shareContext([
'request-id' => $requestId
]);
// ...
}
}
Se hai bisogno di condividere il contesto del log durante l’elaborazione di job in coda, puoi utilizzare middleware per i job.
Scrivere su Canali Specifici
A volte potresti voler registrare un messaggio su un canale diverso dal canale predefinito della tua applicazione. Puoi usare il metodo channel
sulla facade Log
per recuperare e registrare su qualsiasi canale definito nel tuo file di configurazione:
use Illuminate\Support\Facades\Log;
Log::channel('slack')->info('Something happened!');
Se desideri creare uno stack di registrazione su richiesta composto da più canali, puoi usare il metodo stack
:
Log::stack(['single', 'slack'])->info('Something happened!');
Canali On-Demand
È anche possibile creare un canale on-demand fornendo la configurazione a runtime senza che essa sia presente nel file di configurazione logging
della tua applicazione. Per fare ciò, puoi passare un array di configurazione al metodo build
del facade Log
:
use Illuminate\Support\Facades\Log;
Log::build([
'driver' => 'single',
'path' => storage_path('logs/custom.log'),
])->info('Qualcosa è successo!');
Potresti anche voler includere un canale on-demand in uno stack di logging on-demand. Questo può essere fatto includendo l’istanza del tuo canale on-demand nell’array passato al metodo stack
:
use Illuminate\Support\Facades\Log;
$channel = Log::build([
'driver' => 'single',
'path' => storage_path('logs/custom.log'),
]);
Log::stack(['slack', $channel])->info('Qualcosa è successo!');
Personalizzazione del Canale Monolog
Personalizzare Monolog per i Canali
A volte potresti aver bisogno di avere il completo controllo su come Monolog è configurato per un canale esistente. Ad esempio, potresti voler configurare un’implementazione personalizzata di Monolog FormatterInterface
per il canale predefinito single
di Laravel.
Per iniziare, definisci un array tap
nella configurazione del canale. L’array tap
dovrebbe contenere una lista di classi che possono personalizzare (o "tappare") l’istanza di Monolog dopo che è stata creata. Non c’è una posizione convenzionale in cui inserire queste classi, quindi sei libero di creare una directory nella tua applicazione per contenerle:
'single' => [
'driver' => 'single',
'tap' => [App\Logging\CustomizeFormatter::class],
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
Una volta configurata l’opzione tap
nel tuo canale, sei pronto per definire la classe che personalizzerà l’istanza di Monolog. Questa classe necessita solo di un metodo: __invoke
, che riceve un’istanza di Illuminate\Log\Logger
. L’istanza di Illuminate\Log\Logger
proxy tutte le chiamate ai metodi all’istanza sottostante di Monolog:
<?php
namespace App\Logging;
use Illuminate\Log\Logger;
use Monolog\Formatter\LineFormatter;
class CustomizeFormatter
{
/**
* Personalizza l'istanza del logger fornita.
*/
public function __invoke(Logger $logger): void
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new LineFormatter(
'[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
));
}
}
}
Tutte le tue classi "tap" vengono risolte dal service container, quindi tutte le dipendenze del costruttore necessarie verranno automaticamente iniettate.
Creazione di Canali Handler Monolog
Monolog offre una varietà di handler disponibili e Laravel non include un canale predefinito per ognuno di essi. In alcuni casi, potresti voler creare un canale personalizzato che sia semplicemente un’istanza di uno specifico handler Monolog che non ha un driver di log Laravel corrispondente. Questi canali possono essere facilmente creati usando il driver monolog
.
Quando si utilizza il driver monolog
, l’opzione di configurazione handler
serve a specificare quale handler sarà istanziato. Facoltativamente, eventuali parametri del costruttore di cui l’handler ha bisogno possono essere specificati usando l’opzione di configurazione with
:
'logentries' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\SyslogUdpHandler::class,
'with' => [
'host' => 'my.logentries.internal.datahubhost.company.com',
'port' => '10000',
],
],
Formattatori Monolog
Quando usi il driver monolog
, il LineFormatter
di Monolog viene utilizzato come formattatore predefinito. Tuttavia, puoi personalizzare il tipo di formattatore passato all’handler usando le opzioni di configurazione formatter
e formatter_with
:
'browser' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\BrowserConsoleHandler::class,
'formatter' => Monolog\Formatter\HtmlFormatter::class,
'formatter_with' => [
'dateFormat' => 'Y-m-d',
],
],
Se usi un handler di Monolog che può fornire il proprio formattatore, puoi impostare il valore dell’opzione di configurazione formatter
su default
:
'newrelic' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\NewRelicHandler::class,
'formatter' => 'default',
],
Processori di Monolog
Monolog può anche elaborare i messaggi prima di registrarli. Puoi creare i tuoi processori oppure utilizzare i processori esistenti offerti da Monolog.
Se desideri personalizzare i processori per un driver monolog
, aggiungi un valore di configurazione processors
alla configurazione del tuo canale:
'memory' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\StreamHandler::class,
'with' => [
'stream' => 'php://stderr',
],
'processors' => [
// Sintassi semplice...
Monolog\Processor\MemoryUsageProcessor::class,
// Con opzioni...
[
'processor' => Monolog\Processor\PsrLogMessageProcessor::class,
'with' => ['removeUsedContextFields' => true],
],
],
],
Creare Canali Personalizzati tramite Factory
Se desideri definire un canale completamente personalizzato in cui hai il pieno controllo sull’istanza e la configurazione di Monolog, puoi specificare un driver di tipo custom
nel tuo file di configurazione config/logging.php
. La tua configurazione dovrebbe includere un’opzione via
che contiene il nome della classe factory che verrà utilizzata per creare l’istanza di Monolog:
'channels' => [
'example-custom-channel' => [
'driver' => 'custom',
'via' => App\Logging\CreateCustomLogger::class,
],
],
Una volta configurato il driver custom
, sei pronto a definire la classe che creerà l’istanza di Monolog. Questa classe ha bisogno solo di un metodo __invoke
che deve restituire l’istanza del logger Monolog. Il metodo riceverà l’array di configurazione dei canali come unico argomento:
<?php
namespace App\Logging;
use Monolog\Logger;
class CreateCustomLogger
{
/**
* Crea un'istanza personalizzata di Monolog.
*/
public function __invoke(array $config): Logger
{
return new Logger(/* ... */);
}
}
Monitorare i Messaggi di Log con Pail
Spesso potresti aver bisogno di monitorare in tempo reale i log della tua applicazione. Ad esempio, durante il debug di un problema o per controllare i log in cerca di specifici tipi di errori.
Laravel Pail è un pacchetto che ti permette di esplorare facilmente i file di log della tua applicazione Laravel direttamente dalla riga di comando. A differenza del comando standard tail
, Pail è progettato per funzionare con qualsiasi log driver, inclusi Sentry o Flare. Inoltre, Pail offre una serie di filtri utili per aiutarti a trovare rapidamente ciò che cerchi.
Installazione
Per iniziare, installa Pail nel tuo progetto usando il gestore di pacchetti Composer:
composer require laravel/pail
Uso
Per iniziare a visualizzare i log in tempo reale, esegui il comando pail
:
php artisan pail
Per aumentare la verbosità dell’output e evitare troncamenti (…), usa l’opzione -v
:
php artisan pail -v
Per la massima verbosità e per mostrare le tracce degli stack delle eccezioni, usa l’opzione -vv
:
php artisan pail -vv
Per fermare la visualizzazione dei log, premi Ctrl+C
in qualsiasi momento.
Filtrare i Log
--filter
Puoi usare l’opzione --filter
per filtrare i log per tipo, file, messaggio e contenuto dello stack trace:
php artisan pail --filter="QueryException"
--message
Per filtrare i log in base al loro messaggio, puoi usare l’opzione --message
:
php artisan pail --message="User created"
--level
L’opzione --level
può essere usata per filtrare i log in base al loro livello di log:
php artisan pail --level=error
--user
Per visualizzare solo i log scritti mentre un determinato utente era autenticato, puoi fornire l’ID dell’utente all’opzione --user
:
php artisan pail --user=1