Files
homepage/src/posts/logger.md
2025-05-14 14:35:15 +02:00

5.3 KiB

title, excerpt, author, date, category, tags, coverImage, hidden
title excerpt author date category tags coverImage hidden
Implementare un logger categorizzabile Scopri come implementare un logger categorizzabile in Flutter per migliorare la gestione dei log. francesco 25 aprile 2025 Sviluppo frontend
Flutter
Frontend
Log
/assets/posts/logger/head.png?height=600&width=1200 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:

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:

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:

// 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.