Skip to content

infofactory/flutter_meta_logger

Repository files navigation

flutter_infofactory_logger

A small Flutter logging library focused on:

  • Always including caller information (file, line, column, member)
  • Supporting severity levels (LogLevel)
  • Supporting standardized types (LogType) like HTTP.REQUEST, DB.QUERY, ...
  • Emitting structured JSON fields

The default formatter produces lines like:

2025-12-18T16:52:10.123Z INFO [network] package:my_app/data/api_client.dart:123:17 ApiClient.fetchUser - Request completed {"status":200,"ms":84} [TYPE:HTTP.RESPONSE]

If a stack trace is provided, it is appended on a new line.

Features

  • Logger interface + AbstractLogger implementation
  • DebugPrintLogger backend (Flutter debugPrint)
  • DeveloperLogLogger backend (dart:developer)
  • DebugAndProdLogger (different logger in debug vs --release)
  • DefaultLogFormatter (caller + JSON fields + [TYPE:...] suffix)
  • CompositeLogger (fan-out to multiple backends)
  • FilteringLogger (minimum level filtering)

Getting started

Add the dependency to your pubspec.yaml:

dependencies:
  flutter_infofactory_logger:
    path: ../flutter_infofactory_logger

Then run:

flutter pub get

Usage

1) DebugPrintLogger

import 'package:flutter_infofactory_logger/flutter_infofactory_logger.dart';

final logger = DebugPrintLogger(
  minLevel: LogLevel.debug,
  formatter: const DefaultLogFormatter(),
);

logger.info(
  'Request completed',
  tag: 'network',
  type: LogType.httpResponse,
  fields: {'status': 200, 'ms': 84},
);

Environment configuration (--dart-define):

  • DebugPrintLogger.minLevel
    • Allowed values:
      • none (disables logging)
      • trace, debug, info, warn, error, fatal
      • aliases: off, disabled => none

Example:

flutter run --dart-define=DebugPrintLogger.minLevel=debug

And in code:

final logger = DebugPrintLogger.fromEnvironment();

Example output:

2025-12-18T16:52:10.123Z INFO [network] package:my_app/data/api_client.dart:123:17 ApiClient.fetchUser - Request completed {"status":200,"ms":84} [TYPE:HTTP.RESPONSE]

2) DeveloperLogLogger

import 'package:flutter_infofactory_logger/flutter_infofactory_logger.dart';

final logger = DeveloperLogLogger(
  minLevel: LogLevel.trace,
  formatter: const DefaultLogFormatter(),
  name: 'my_app',
);

try {
  throw StateError('boom');
} catch (e, st) {
  logger.error(
    'Unexpected error',
    tag: 'app',
    type: LogType.error,
    error: e,
    stackTrace: st,
    fields: {'feature': 'startup'},
  );
}

Environment configuration (--dart-define):

  • DeveloperLogLogger.minLevel
    • Allowed values:
      • none (disables logging)
      • trace, debug, info, warn, error, fatal
      • aliases: off, disabled => none
  • DeveloperLogLogger.name
    • String, used as the developer.log name when tag is not set.

Example:

flutter run \
  --dart-define=DeveloperLogLogger.minLevel=info \
  --dart-define=DeveloperLogLogger.name=my_app

And in code:

final logger = DeveloperLogLogger.fromEnvironment();

Example output:

2025-12-18T16:52:12.456Z ERROR [app] package:my_app/main.dart:42:9 main - Unexpected error {"feature":"startup"} error=Bad state: boom [TYPE:ERROR]
<stack trace...>

3) DebugAndProdLogger (debug vs --release)

Use one logger while running in debug/profile and a different one when running in release.

The selection is based on kReleaseMode (so flutter run --release).

import 'package:flutter_infofactory_logger/flutter_infofactory_logger.dart';

final logger = DebugAndProdLogger(
  debugLogger: DebugPrintLogger.fromEnvironment(),
  releaseLogger: DeveloperLogLogger.fromEnvironment(),
);

Environment configuration (--dart-define):

  • None directly. Configure the underlying loggers instead.

4) CompositeLogger (multiple backends)

import 'package:flutter_infofactory_logger/flutter_infofactory_logger.dart';

final formatter = const DefaultLogFormatter();

final logger = CompositeLogger(
  children: [
    DebugPrintLogger(minLevel: LogLevel.debug, formatter: formatter),
    DeveloperLogLogger(minLevel: LogLevel.info, formatter: formatter, name: 'my_app'),
  ],
);

logger.debug('Only debugPrint receives this', tag: 'dev');
logger.info('Both backends receive this', tag: 'app');

Environment configuration (--dart-define):

  • None.

5) FilteringLogger

import 'package:flutter_infofactory_logger/flutter_infofactory_logger.dart';

final formatter = const DefaultLogFormatter();

final inner = DebugPrintLogger(minLevel: LogLevel.trace, formatter: formatter);
final logger = FilteringLogger(
  inner: inner,
  minLevel: LogLevel.warn,
);

logger.info('Filtered out');
logger.warn('Visible');

Environment configuration (--dart-define):

  • None.

Notes

  • Caller information is extracted using package:stack_trace.
  • Capturing stack traces has a cost; use an appropriate minLevel in production.
  • Set minLevel to LogLevel.none to disable logging.

About

Meta logger per flutter.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages