Generic Logger for Flutter

A generic, customizable logging library that works seamlessly across Flutter, Dart VM, and web builds—without initializing or depending on any third-party logging packages internally. Instead of enforcing a specific logging backend, users inject their own preferred logging implementation, making this a truly framework-agnostic and highly flexible solution for Flutter applications.

Features

  • 🚀 Plug-and-play adapters (Console, File) with clear blueprints for HTTP/cloud adapters.
  • 🛡️ Built-in sanitization with tag-specific overrides to keep sensitive data safe.
  • 🧰 Fluent context builder and scoped loggers for ergonomic instrumentation.
  • ⚙️ Configurable error handling, severity thresholds, and repository lifecycle management.
  • 🧪 Unit-tested core plus CI workflow and documentation tooling.

Installation

Add the package to your pubspec.yaml:

dependencies:
  generic_logger:
    path: ../generic_logger/flutter_generic_logger

(Replace the path above with the appropriate location once published to pub.dev.)

Quick Start

import 'package:generic_logger/generic_logger.dart';

Future<void> bootstrapLogging() async {
  final logger = Logger(
    config: LoggerRepositoryConfig(
      severity: LogLevel.debug,
    ),
  );

  await logger.registerAdapter(
    'console',
    ConsoleLoggerAdapter(),
    config: const ConsoleAdapterConfig(
      enabled: true,
      colorize: true,
    ),
  );

  logger.info('Generic Logger ready 🚀');
}

Scoped logging

final authLogger = ScopedLogger.tag('Auth');

authLogger.debug(
  'Attempting login',
  options: LogContextBuilder()
      .metadata({'strategy': 'password'})
      .build(),
);

authLogger.error(
  'Login failed',
  error: Exception('Invalid credentials'),
  options: const EnhancedLogOptions(
    data: {'email': 'hidden@example.com'},
  ),
);

File logging

final fileAdapter = FileLoggerAdapter();

await fileAdapter.initialize(
  FileAdapterConfig(
    enabled: true,
    directory: '/tmp',
    formats: {FileLogFormat.text, FileLogFormat.json},
  ),
);

await logger.registerAdapter('file', fileAdapter);

Sanitization

Sanitization runs automatically when sanitizationEnabled is true (default).
You can supply custom sanitizers per tag or per log call.

class PaymentSanitizer extends Sanitizer {
  @override
  Object? sanitize(Object? data) {
    if (data is Map<String, Object?>) {
      return {
        ...data,
        'cardNumber': '[REDACTED]',
      };
    }
    return data;
  }
}

final repository = LoggerRepository.getInstance();
repository.registerSanitizer('Payment', PaymentSanitizer());

Skip sanitization for a specific call:

logger.debug(
  'Diagnostics payload',
  options: const EnhancedLogOptions(
    data: {'raw': 'large-object'},
    skipSanitization: true,
  ),
);

Error handling

Provide a custom error handler to capture adapter failures:

final repository = LoggerRepository.getInstance(
  config: LoggerRepositoryConfig(
    onAdapterError: (error, stack) {
      // Forward to Crashlytics, Sentry, etc.
    },
  ),
);

Project scripts

  • flutter test — run unit tests
  • flutter analyze — lint with recommended rules
  • tool/generate_docs.sh — regenerate API documentation
  • npm run flutter:version:patch|minor|major — bump versions from the repository root (--release adds branch/tag automation)
  • npm run flutter:release:create flutter-vX.Y.Z — re-create GitHub release notes if needed

Roadmap

  • Streaming adapters (HTTP, Firebase, Firehose)
  • Structured tracing integration
  • Devtools log viewer widget

License

MIT © Thomas Samoul

Libraries

generic_logger