mirror of
https://github.com/Techtonic-Fault/homepage.git
synced 2026-01-23 13:29:52 +00:00
146 lines
5.3 KiB
Markdown
146 lines
5.3 KiB
Markdown
|
|
---
|
||
|
|
title: "Implementare un logger categorizzabile"
|
||
|
|
excerpt: "Scopri come implementare un logger categorizzabile in Flutter per migliorare la gestione dei log."
|
||
|
|
author: francesco
|
||
|
|
date: "25 aprile 2025"
|
||
|
|
category: "Sviluppo frontend"
|
||
|
|
tags:
|
||
|
|
- Flutter
|
||
|
|
- Frontend
|
||
|
|
- Log
|
||
|
|
coverImage: "/assets/posts/logger/head.png?height=600&width=1200"
|
||
|
|
hidden: true
|
||
|
|
---
|
||
|
|
|
||
|
|
Quando si pubblica un'applicazione, spesso si ha bisogno di un modo per monitorare
|
||
|
|
le performance e il comportamento dell'app. Un modo comune per farlo è utilizzare
|
||
|
|
un logger, che può registrare eventi, errori e altre informazioni utili. In questo
|
||
|
|
articolo, esploreremo come implementare un logger categorizzabile in Flutter,
|
||
|
|
che ci permetterà di organizzare i log in categorie specifiche e facilitare la
|
||
|
|
loro gestione.
|
||
|
|
|
||
|
|
## Perché un logger categorizzabile?
|
||
|
|
|
||
|
|
Molti progetti utilizzano Firebase Crashlytics o Sentry per monitorare gli errori e le performance.
|
||
|
|
Tuttavia, questi strumenti richiedono che l'applicazione sia costantemente in
|
||
|
|
contatto con il servizio per inviare i log. In alcuni casi, potrebbe non essere
|
||
|
|
necessario avere un flusso continuo di log, ma può bastare registrare gli eventi
|
||
|
|
localmente e inviarli in un secondo momento, ad esempio quando l'app è online o
|
||
|
|
quando l'utente lo richiede.
|
||
|
|
È proprio qui che entra in gioco il logger categorizzabile.
|
||
|
|
|
||
|
|
Un logger categorizzabile consente di organizzare i log in categorie specifiche,
|
||
|
|
rendendo più facile la loro gestione e analisi. Possiamo ad esempio avere categorie
|
||
|
|
per gli errori, le performance, le azioni degli utenti e così via. In questo modo,
|
||
|
|
possiamo filtrare i log in base alla categoria e concentrarci solo su quelli che
|
||
|
|
ci interessano in un determinato momento.
|
||
|
|
|
||
|
|
## Creazione del logger
|
||
|
|
|
||
|
|
Iniziamo definendo i tipi di eventi di cui vogliamo tenere traccia:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
enum LogLevel {
|
||
|
|
debug(0),
|
||
|
|
info(1),
|
||
|
|
warning(2),
|
||
|
|
error(3),
|
||
|
|
fatal(99);
|
||
|
|
|
||
|
|
const LogLevel(this.value);
|
||
|
|
|
||
|
|
final int value;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
In questo esempio, abbiamo definito cinque livelli di log: `debug`, `info`, `warning`,
|
||
|
|
`error` e `fatal`. Ogni livello ha un valore associato che ci permette di
|
||
|
|
classificarli in ordine di gravità. È qui che possiamo decidere di aggiungere
|
||
|
|
categorie come `performance`, `userAction`, `network` e così via.
|
||
|
|
|
||
|
|
Passiamo ora alla classe Logger. Questa classe sarà responsabile della
|
||
|
|
registrazione dei log e della loro gestione. Ecco un esempio di implementazione:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
typedef LogTransformer = void Function(LogEntry entry);
|
||
|
|
|
||
|
|
class LogEntry {
|
||
|
|
final LogLevel level;
|
||
|
|
final String message;
|
||
|
|
final String? category;
|
||
|
|
final DateTime timestamp;
|
||
|
|
|
||
|
|
// ...
|
||
|
|
}
|
||
|
|
|
||
|
|
class Logger {
|
||
|
|
static final Logger _instance = Logger._internal();
|
||
|
|
factory Logger() => _instance;
|
||
|
|
Logger._internal();
|
||
|
|
|
||
|
|
final List<LogTransformer> _transformers = [];
|
||
|
|
|
||
|
|
void addTransformer(LogTransformer transformer) {
|
||
|
|
_transformers.add(transformer);
|
||
|
|
}
|
||
|
|
|
||
|
|
void log(LogLevel level, String message, {String? category}) {
|
||
|
|
final entry = LogEntry(
|
||
|
|
level: level,
|
||
|
|
message: message,
|
||
|
|
category: category,
|
||
|
|
timestamp: DateTime.now(),
|
||
|
|
);
|
||
|
|
|
||
|
|
for (final transformer in _transformers) {
|
||
|
|
// Invia il messaggio trasformato a un servizio di logging
|
||
|
|
// oppure a un repository locale.
|
||
|
|
transformer(entry);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
In questo esempio, abbiamo creato una classe `Logger` che utilizza il
|
||
|
|
singleton pattern per garantire che ci sia solo un'istanza del logger in tutta
|
||
|
|
l'applicazione. La classe ha un metodo `log` che accetta un livello di log,
|
||
|
|
un messaggio e una categoria opzionale. Quando viene chiamato il metodo `log`,
|
||
|
|
viene creato un oggetto `LogEntry` che contiene tutte le informazioni sul log.
|
||
|
|
|
||
|
|
Il logger accetta anche una lista di trasformatori (`LogTransformer`) che sono
|
||
|
|
responsabili della gestione dei log. Questi trasformatori possono essere
|
||
|
|
utilizzati per inviare i log a un servizio esterno, salvarli in un file locale
|
||
|
|
o eseguire qualsiasi altra operazione necessaria, come salvare i log in una
|
||
|
|
`List` per una successiva visione degli stessi.
|
||
|
|
|
||
|
|
Il modo in cui abbiamo definito l'enum `LogLevel` e la classe `LogEntry` ci
|
||
|
|
permette di filtrare molto facilmente i log in base alla loro categoria:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
// Assumiamo di avere una lista di log del tipo
|
||
|
|
List<LogEntry> _logs = [];
|
||
|
|
|
||
|
|
// Filtriamo i log in base alla categoria
|
||
|
|
LogLevel category = LogLevel.warning;
|
||
|
|
List<LogEntry> filteredLogs = _logs
|
||
|
|
.where((log) => log.category.value >= category.value)
|
||
|
|
.toList();
|
||
|
|
```
|
||
|
|
|
||
|
|
Così facendo, ignoriamo tutti i log di tipo `debug` e `info`. Ovviamente, possiamo
|
||
|
|
anche prendere solo i log di una categoria specifica, ad esempio `performance` o `userAction`,
|
||
|
|
a seconda delle nostre esigenze.
|
||
|
|
|
||
|
|
## Conclusione
|
||
|
|
|
||
|
|
In questo articolo, abbiamo visto come implementare un logger categorizzabile
|
||
|
|
in Flutter. Questo approccio ci consente di organizzare i log in categorie
|
||
|
|
specifiche, facilitando la loro gestione e analisi. Abbiamo anche visto come
|
||
|
|
creare una classe `Logger` che utilizza il singleton pattern e accetta
|
||
|
|
trasformatori per gestire i log in modo flessibile.
|
||
|
|
|
||
|
|
Abbiamo implementato un logger molto semplice ma estremamente potente. A
|
||
|
|
TECHTONIC FAULT, crediamo che la semplicità sia la chiave per un buon
|
||
|
|
sviluppo software, senza compromettere la potenza e la flessibilità. Con questo
|
||
|
|
logger, possiamo monitorare le performance e il comportamento delle nostre
|
||
|
|
applicazioni in modo efficace e senza complicazioni inutili.
|