printx_logger - Advanced & Extensible Logging for Flutter

printx_logger is a clean, full-featured, production-ready logging package for Flutter/Dart inspired by the best in the ecosystem. It combines ergonomic, print()-like usage with power features loved by professionals:

  • Multiple output "sinks" (console, file, HTTP, DevTools)
  • Extensible, colorized, JSON or custom formatters
  • Fine-grained filtering (level, tag, predicate)
  • Detailed caller info (file name, line number, method)
  • Seamless integration with Flutter error handling
  • Modular, testable, and high performance

Features

  • Standard log levels: trace, debug, info, warn, error, fatal (customizable)
  • Multiple outputs: console, file with rotation, HTTP, DevTools
  • Formatters: colorized output, JSON, or plain text
  • Caller info (file name, line number, method) included automatically
  • Filtering by level, tag, or predicate, global or per sink
  • Lazy message evaluation for expensive logs
  • Flutter integration capturing uncaught errors
  • Specialized loggers for common domains: API, UI, Network, Auth, Database
  • Export logs as zipped archive for support/debugging
  • Cross-platform support: Android, iOS, Windows, macOS, Linux, Web (with graceful fallback)

Getting Started

Installation

Add to your pubspec.yaml:

dependencies:
  printx_logger: ^1.0.0

Example Usage

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize PrintX (optional - it auto-initializes with sane defaults)
  await PrintX.initialize(
    minimumLevel: LogLevel.info,
    enableConsoleLogging: true,
    enableFileLogging: false,
    enableDeveloperLogging: true,
    captureFlutterErrors: true,
    enableColorOutput: true,
  );

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PrintX Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'PrintX Logger Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });

    // Basic logging (like print)
    PrintX('Counter incremented to $_counter');

    // Different log levels
    PrintX.info('Info: Button pressed, counter = $_counter');
    PrintX.warn('Warning: Counter getting high!', tag: 'UI');
    PrintX.debug('Debug: Counter is now $_counter');

    if (_counter > 5) {
      PrintX.error(
        'Error: Counter exceeded 5!',
        error: Exception('Counter too high'),
        context: {'counter': _counter, 'threshold': 5},
      );
    }

    // Lazy evaluation (expensive operations only run when needed)
    PrintX.debugLazy(() {
      final expensiveCalculation = List.generate(
        1000,
        (i) => i * i,
      ).fold(0, (a, b) => a + b);
      return 'Expensive calculation result: $expensiveCalculation';
    });

    // Specialized loggers
    PrintX.api.info('API call completed successfully');
    PrintX.ui.debug('Button animation started');
    PrintX.network.warn('Slow network detected');
    PrintX.auth.error(
      'Authentication failed',
      error: Exception('Invalid token'),
    );

    // Custom logger
    final customLogger = PrintX.getLogger('CustomFeature');
    customLogger.info(
      'Custom feature executed',
      tag: 'feature-x',
      context: {'user_id': '123', 'session_id': 'abc'},
    );
  }

  void _demonstrateErrorHandling() {
    try {
      throw Exception('This is a test exception');
    } catch (error, stackTrace) {
      PrintX.error(
        'Caught an exception!',
        error: error,
        stackTrace: stackTrace,
        tag: 'error-demo',
      );
    }
  }

  void _demonstrateContextLogging() {
    PrintX.info(
      'User action performed',
      context: {
        'user_id': '12345',
        'action': 'button_press',
        'timestamp': DateTime.now().toIso8601String(),
        'session_duration': const Duration(minutes: 15).inSeconds,
        'metadata': {'app_version': '1.0.0', 'platform': 'mobile'},
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _demonstrateErrorHandling,
              child: const Text('Demonstrate Error Logging'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: _demonstrateContextLogging,
              child: const Text('Demonstrate Context Logging'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: () async {
                final logs = await PrintX.exportLogs();
                if (logs != null) {
                  PrintX.info('Logs exported to: $logs');
                } else {
                  PrintX.warn('Could not export logs (web platform?)');
                }
              },
              child: const Text('Export Logs'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: () async {
                await PrintX.clearLogs();
                PrintX.info('All logs cleared');
              },
              child: const Text('Clear Logs'),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

More Information

For more usage examples, filtering, custom sinks, and advanced features, see the documentation at the package's repository.


License

MIT © Flutter Community


printx_logger – The only logger you'll need for serious Flutter apps!
Made with ❤️ for developers who love clean, powerful tools.


Libraries

printx_logger