Question #101MediumFlutter Basics

Have you used any logger plugin (flutter log handler , flog)

#flutter

Answer

Overview

Yes, Flutter has several logging plugins for better debugging, error tracking, and production monitoring. Popular options include logger, fimber, f_logs, and pretty_dio_logger for network logs.


1. logger Package (Most Popular)

Beautiful, colorful console logs with multiple levels.

Installation

yaml
dependencies:
  logger: ^2.0.0

Basic Usage

dart
import 'package:logger/logger.dart';

final logger = Logger();

void main() {
  logger.d('Debug message');     // Debug
  logger.i('Info message');      // Info
  logger.w('Warning message');   // Warning
  logger.e('Error message');     // Error
  logger.wtf('What a terrible failure!'); // Fatal
}

Custom Configuration

dart
final logger = Logger(
  printer: PrettyPrinter(
    methodCount: 2,        // Stack trace depth
    errorMethodCount: 8,   // Error stack trace
    lineLength: 120,       // Console width
    colors: true,          // Colorful output
    printEmojis: true,     // Add emoji icons
    printTime: true,       // Include timestamp
  ),
);

// Simple output (no colors/stack trace)
final simpleLogger = Logger(
  printer: SimplePrinter(),
);

Log Levels

dart
// Development — verbose
Logger.level = Level.verbose; // All logs

// Production — errors only
Logger.level = Level.error;

// No logs
Logger.level = Level.nothing;

Log to File

dart
import 'dart:io';

class FileOutput extends LogOutput {
  final File file;

  FileOutput(this.file);

  
  void output(OutputEvent event) {
    for (var line in event.lines) {
      file.writeAsStringSync('$line
', mode: FileMode.append);
    }
  }
}

final logger = Logger(
  output: FileOutput(File('logs.txt')),
);

2. fimber (Lightweight)

Lightweight logging inspired by Timber (Android).

Installation

yaml
dependencies:
  fimber: ^0.7.0

Usage

dart
import 'package:fimber/fimber.dart';

void main() {
  Fimber.plantTree(DebugTree()); // Setup logger

  Fimber.d('Debug message');
  Fimber.i('Info message');
  Fimber.w('Warning message');
  Fimber.e('Error message');
}

Custom Tree

dart
class CrashReportingTree extends LogTree {
  
  void log(String level, String message, {String? tag, dynamic ex}) {
    if (level == 'E') {
      // Send error to Crashlytics, Sentry, etc.
      crashlytics.recordError(message, ex);
    }
  }
}

Fimber.plantTree(CrashReportingTree());

3. f_logs (File Logging)

Logs to files with filtering and export.

Installation

yaml
dependencies:
  f_logs: ^2.0.0

Usage

dart
import 'package:f_logs/f_logs.dart';

void main() async {
  await FLog.applyConfigurations(
    isDevelopmentDebuggingEnabled: true,
    timestampFormat: LogsConfig.DEFAULT_TIMESTAMP,
  );

  FLog.info(text: 'App started');
  FLog.warning(text: 'Low battery');
  FLog.error(text: 'Network error', exception: Exception('Timeout'));
}

Export Logs

dart
// Export logs to file
final file = await FLog.exportLogs();
print('Logs saved to: ${file.path}');

// Share logs via email, WhatsApp, etc.
Share.shareFiles([file.path], text: 'App logs');

Clear Logs

dart
await FLog.clearLogs();

4. pretty_dio_logger (Network Logging)

Logs HTTP requests/responses for Dio.

Installation

yaml
dependencies:
  dio: ^5.3.0
  pretty_dio_logger: ^1.3.0

Usage

dart
import 'package:dio/dio.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

final dio = Dio();

dio.interceptors.add(
  PrettyDioLogger(
    requestHeader: true,
    requestBody: true,
    responseBody: true,
    responseHeader: false,
    error: true,
    compact: true,
    maxWidth: 90,
  ),
);

// All network calls now logged
final response = await dio.get('https://api.example.com/users');

Output:

text
┌──────────────────────────────────────────────────────────────
│ GET https://api.example.com/users
├──────────────────────────────────────────────────────────────
│ Headers:
│  • content-type: application/json
├──────────────────────────────────────────────────────────────
│ Response [200 OK] (250ms)
│ Body:
│  {"users": [...]}
└──────────────────────────────────────────────────────────────

5. talker (All-in-One)

Logs, errors, exceptions, and HTTP logs in one package.

Installation

yaml
dependencies:
  talker: ^3.0.0
  talker_dio_logger: ^3.0.0
  talker_flutter: ^3.0.0

Usage

dart
import 'package:talker_flutter/talker_flutter.dart';

final talker = Talker();

void main() {
  talker.info('App started');
  talker.error('Something went wrong');

  runApp(MyApp(talker: talker));
}

// View logs in UI
TalkerScreen(talker: talker);

Features:

  • Console logging
  • UI viewer (built-in logs screen)
  • HTTP logging (Dio interceptor)
  • Error tracking
  • Custom filters

Comparison Table

PackageSizeFeaturesBest For
loggerSmallColorful console, stack tracesDevelopment
fimberTinyLightweight, custom treesProduction
f_logsMediumFile export, email logsProduction
pretty_dio_loggerSmallNetwork logs onlyDio HTTP
talkerLargeAll-in-one (logs + UI)Full apps

Production Logging Setup

dart
import 'package:logger/logger.dart';
import 'package:flutter/foundation.dart';

class AppLogger {
  static final Logger _logger = Logger(
    printer: PrettyPrinter(
      methodCount: kDebugMode ? 2 : 0, // Stack trace in debug only
      colors: kDebugMode,
      printEmojis: kDebugMode,
    ),
    level: kDebugMode ? Level.debug : Level.error, // Errors only in release
  );

  static void debug(String message) => _logger.d(message);
  static void info(String message) => _logger.i(message);
  static void warning(String message) => _logger.w(message);
  static void error(String message, [dynamic error, StackTrace? stackTrace]) {
    _logger.e(message, error: error, stackTrace: stackTrace);

    // Send to crash reporting in production
    if (!kDebugMode) {
      FirebaseCrashlytics.instance.recordError(error, stackTrace);
    }
  }
}

// Usage
AppLogger.info('User logged in');
AppLogger.error('API call failed', error, stackTrace);

Best Practices

dart
// ✅ Use different log levels
logger.d('Detailed debug info');
logger.i('User action');
logger.w('Potential issue');
logger.e('Error occurred');

// ✅ Disable logs in release
Logger.level = kDebugMode ? Level.verbose : Level.error;

// ✅ Add context to logs
logger.e('API Error', error: error, stackTrace: stackTrace);

// ✅ Use custom logger wrapper
class MyLogger {
  static void logNetworkError(String url, int statusCode) {
    logger.e('Network Error: $url returned $statusCode');
  }
}

// ❌ Don't log sensitive data
logger.d('Password: $password'); // ❌ Security risk

// ❌ Don't log in hot paths (performance)
for (var i = 0; i < 10000; i++) {
  logger.d('Loop $i'); // ❌ Slows down app
}

Integration with Crash Reporting

dart
import 'package:firebase_crashlytics/firebase_crashlytics.dart';

class CrashlyticsLogger {
  static void log(String message) {
    logger.i(message);
    FirebaseCrashlytics.instance.log(message);
  }

  static void recordError(dynamic error, StackTrace stackTrace) {
    logger.e('Error', error: error, stackTrace: stackTrace);
    FirebaseCrashlytics.instance.recordError(error, stackTrace);
  }
}

Complete Example

dart
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';

final logger = Logger(
  printer: PrettyPrinter(
    methodCount: 2,
    colors: true,
    printEmojis: true,
  ),
);

void main() {
  logger.i('App started');

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  Future<void> fetchData() async {
    try {
      logger.d('Fetching data...');
      // API call
      final response = await http.get(Uri.parse('https://api.example.com'));
      logger.i('Data fetched successfully');
    } catch (e, stackTrace) {
      logger.e('Failed to fetch data', error: e, stackTrace: stackTrace);
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Logger Example')),
      body: Center(
        child: ElevatedButton(
          onPressed: fetchData,
          child: Text('Fetch Data'),
        ),
      ),
    );
  }
}

Learn more: