flex_logger 1.0.1 copy "flex_logger: ^1.0.1" to clipboard
flex_logger: ^1.0.1 copied to clipboard

A flexible logging package for Flutter applications with support for multiple logging strategies, observers, and integrations.

example/lib/main.dart

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

// ---------------------------------------------------------------------------
// Custom log type – demonstrates extending FlexLog.
// ---------------------------------------------------------------------------

/// A custom log type carrying HTTP request metadata.
final class NetworkLog extends FlexLog {
  NetworkLog({
    required String url,
    required int statusCode,
    String? description,
  }) : super(
         '${description ?? 'HTTP'} $url [$statusCode]',
         level: statusCode >= 400 ? FlexLogLevel.error : FlexLogLevel.info,
         tag: 'HTTP',
       );
}

// ---------------------------------------------------------------------------
// Custom observer – captures logs into an in-memory list so the UI can
// display them. Demonstrates implementing FlexObserver without any
// external dependency.
// ---------------------------------------------------------------------------

/// An observer that stores formatted log entries for display in the UI.
final class InMemoryObserver extends FlexObserver {
  InMemoryObserver({super.filter});

  final List<LogEntry> entries = [];

  /// Callback invoked whenever a new entry is added.
  void Function()? onUpdate;

  @override
  Future<void> onLog(FlexLog log) async {
    entries.add(LogEntry(log.formattedTitle, log.message ?? '', log.level));
    onUpdate?.call();
  }

  @override
  Future<void> onException(FlexLog log) async {
    entries.add(
      LogEntry(
        log.formattedTitle,
        '${log.message}\n${log.error}',
        log.level,
      ),
    );
    onUpdate?.call();
  }

  @override
  Future<void> onError(FlexLog log) async {
    entries.add(
      LogEntry(
        log.formattedTitle,
        '${log.message}\n${log.error}',
        log.level,
      ),
    );
    onUpdate?.call();
  }

  void clear() {
    entries.clear();
    onUpdate?.call();
  }
}

/// Holds a single log line for display purposes.
final class LogEntry {
  const LogEntry(this.title, this.message, this.level);

  final String title;
  final String message;
  final FlexLogLevel level;

  Color get color => switch (level) {
    FlexLogLevel.debug    => const Color(0xFF00BCD4),
    FlexLogLevel.info     => const Color(0xFF2196F3),
    FlexLogLevel.success  => const Color(0xFF4CAF50),
    FlexLogLevel.warning  => const Color(0xFFFF9800),
    FlexLogLevel.error    => const Color(0xFFF44336),
    FlexLogLevel.critical => const Color(0xFFD32F2F),
  };
}

// ---------------------------------------------------------------------------
// Custom provider – wires the observer into FlexLogger.
// ---------------------------------------------------------------------------

/// Provider that exposes [InMemoryObserver] to FlexLogger.
final class InMemoryLoggerProvider implements LoggerProvider {
  InMemoryLoggerProvider({LogFilter filter = const AcceptAllFilter()})
      : _observer = InMemoryObserver(filter: filter);

  final InMemoryObserver _observer;

  InMemoryObserver get observer => _observer;

  @override
  String get providerId => 'InMemoryLoggerProvider';

  @override
  Future<void> initialize() async {}

  @override
  FlexObserver? createObserver() => _observer;

  @override
  Future<void> dispose() async => _observer.clear();
}

// ---------------------------------------------------------------------------
// App entry point
// ---------------------------------------------------------------------------

final InMemoryLoggerProvider _provider = InMemoryLoggerProvider();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  FlexLogger.instance.configure(providers: [_provider]);
  await FlexLogger.instance.initialize();

  FlexLogger.instance.info('FlexLogger core example started');
  FlexLogger.instance.debug('All log levels and custom log types are supported');

  runApp(const MyApp());
}

// ---------------------------------------------------------------------------
// UI
// ---------------------------------------------------------------------------

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FlexLogger Core Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: const LoggerDemoPage(),
    );
  }
}

class LoggerDemoPage extends StatefulWidget {
  const LoggerDemoPage({super.key});

  @override
  State<LoggerDemoPage> createState() => _LoggerDemoPageState();
}

class _LoggerDemoPageState extends State<LoggerDemoPage> {
  late final InMemoryObserver _observer;

  @override
  void initState() {
    super.initState();
    _observer = _provider.observer;
    _observer.onUpdate = () {
      if (mounted) setState(() {});
    };
  }

  @override
  void dispose() {
    _observer.onUpdate = null;
    FlexLogger.instance.dispose();
    super.dispose();
  }

  void _logAll() {
    FlexLogger.instance.debug('Debug – detailed diagnostic information');
    FlexLogger.instance.info('Info – general application event');
    FlexLogger.instance.success('Success – operation completed');
    FlexLogger.instance.warning('Warning – something might be wrong');
    FlexLogger.instance.error('Error – something went wrong');
    FlexLogger.instance.critical('Critical – immediate action required');
  }

  void _logCustom() {
    FlexLogger.instance.logCustom(
      NetworkLog(
        url: 'https://api.example.com/data',
        statusCode: 200,
        description: 'GET',
      ),
    );
    FlexLogger.instance.logCustom(
      NetworkLog(
        url: 'https://api.example.com/missing',
        statusCode: 404,
        description: 'GET',
      ),
    );
  }

  void _logException() {
    try {
      throw Exception('Something went wrong in the app');
    } catch (e, st) {
      FlexLogger.instance.error('Caught exception', e, st);
    }
  }

  @override
  Widget build(BuildContext context) {
    final entries = List<LogEntry>.from(_observer.entries.reversed);

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('FlexLogger Core Example'),
        actions: [
          IconButton(
            icon: const Icon(Icons.delete_outline),
            tooltip: 'Clear logs',
            onPressed: () => setState(_observer.clear),
          ),
        ],
      ),
      body: Column(
        children: [
          // Button panel
          Padding(
            padding: const EdgeInsets.all(12),
            child: Wrap(
              spacing: 8,
              runSpacing: 8,
              alignment: WrapAlignment.center,
              children: [
                _LogButton(
                  label: 'All levels',
                  color: Colors.indigo,
                  onPressed: _logAll,
                ),
                _LogButton(
                  label: 'Debug',
                  color: const Color(0xFF00BCD4),
                  onPressed: () => FlexLogger.instance.debug('Debug message'),
                ),
                _LogButton(
                  label: 'Info',
                  color: const Color(0xFF2196F3),
                  onPressed: () => FlexLogger.instance.info('Info message'),
                ),
                _LogButton(
                  label: 'Success',
                  color: const Color(0xFF4CAF50),
                  onPressed: () =>
                      FlexLogger.instance.success('Success message'),
                ),
                _LogButton(
                  label: 'Warning',
                  color: const Color(0xFFFF9800),
                  onPressed: () =>
                      FlexLogger.instance.warning('Warning message'),
                ),
                _LogButton(
                  label: 'Error',
                  color: const Color(0xFFF44336),
                  foreground: Colors.white,
                  onPressed: () => FlexLogger.instance.error('Error message'),
                ),
                _LogButton(
                  label: 'Critical',
                  color: const Color(0xFFD32F2F),
                  foreground: Colors.white,
                  onPressed: () =>
                      FlexLogger.instance.critical('Critical message'),
                ),
                _LogButton(
                  label: 'Custom (NetworkLog)',
                  color: Colors.teal,
                  foreground: Colors.white,
                  onPressed: _logCustom,
                ),
                _LogButton(
                  label: 'Exception',
                  color: const Color(0xFFF44336),
                  foreground: Colors.white,
                  onPressed: _logException,
                ),
              ],
            ),
          ),

          const Divider(height: 1),

          // Log list
          Expanded(
            child: entries.isEmpty
                ? const Center(
                    child: Text(
                      'Press a button to generate logs',
                      style: TextStyle(color: Colors.grey),
                    ),
                  )
                : ListView.separated(
                    padding: const EdgeInsets.all(8),
                    itemCount: entries.length,
                    separatorBuilder: (_, __) => const SizedBox(height: 4),
                    itemBuilder: (context, index) {
                      final entry = entries[index];
                      return _LogTile(entry: entry);
                    },
                  ),
          ),
        ],
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Reusable widgets
// ---------------------------------------------------------------------------

class _LogButton extends StatelessWidget {
  const _LogButton({
    required this.label,
    required this.color,
    required this.onPressed,
    this.foreground,
  });

  final String label;
  final Color color;
  final Color? foreground;
  final VoidCallback onPressed;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      style: ElevatedButton.styleFrom(
        backgroundColor: color,
        foregroundColor: foreground ?? Colors.black87,
      ),
      child: Text(label),
    );
  }
}

class _LogTile extends StatelessWidget {
  const _LogTile({required this.entry});

  final LogEntry entry;

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: entry.color.withAlpha(25),
        border: Border(left: BorderSide(color: entry.color, width: 3)),
        borderRadius: const BorderRadius.only(
          topRight: Radius.circular(4),
          bottomRight: Radius.circular(4),
        ),
      ),
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            entry.title,
            style: TextStyle(
              fontSize: 11,
              fontWeight: FontWeight.bold,
              color: entry.color,
            ),
          ),
          const SizedBox(height: 2),
          Text(entry.message, style: const TextStyle(fontSize: 13)),
        ],
      ),
    );
  }
}
0
likes
0
points
313
downloads

Publisher

verified publisherkrajna.dev

Weekly Downloads

A flexible logging package for Flutter applications with support for multiple logging strategies, observers, and integrations.

Repository (GitLab)
View/report issues

Topics

#logging #flutter #observability

License

unknown (license)

Dependencies

flutter

More

Packages that depend on flex_logger