app_factory_logging 0.0.1 copy "app_factory_logging: ^0.0.1" to clipboard
app_factory_logging: ^0.0.1 copied to clipboard

App Factory debug logging baseline (AppLogger abstraction + Riverpod bindings).

app_factory_logging #

Riverpod-native debug logging baseline for Flutter apps.

This package gives you a small AppLogger abstraction, a console implementation backed by Dart's official package:logging, generated Riverpod providers, and a test fake. Logging stays separate from telemetry (Analytics / Crashlytics): this package never depends on Firebase.

Features #

  • Four public levels only: debug / info / warn / error
  • Default ConsoleAppLogger (internal package:logging + dart:developer log)
  • Per-instance minLevel gating (debug is silent in release by default)
  • Message truncation (default 2000 chars) and debugChunked for large payloads
  • Generated keepAlive providers: appLoggerProvider / appLogSinkProvider
  • FakeAppLogger for unit tests
  • Optional debug-only AppLoggerProviderObserver
  • AppLogSink interface for breadcrumb bridges (e.g. Crashlytics in another package)

What This Package Does Not Do #

  • Production analytics or crash reporting
  • Log UI, local persistence, or remote log shipping
  • Third-party logging ecosystems (Talker, etc.)

Missing console output in release builds is expected. dart:developer log depends on the VM service, so release builds usually show nothing. That matches the "debug diagnostics" role of this package. In release, the useful path for warn / error is an optional AppLogSink (breadcrumbs). This package will not fall back to print.

Installation #

dependencies:
  app_factory_logging: ^0.0.1
flutter pub get

Quick Start #

Create one logger instance, override the provider with it, and optionally attach the provider observer in debug. Sharing the same instance avoids the chicken-and-egg problem of reading the logger from a container that is still being constructed:

import 'package:app_factory_logging/app_factory_logging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  final appLogger = ConsoleAppLogger(
    // sink: MyCrashlyticsBreadcrumbSink(...),
  );

  final container = ProviderContainer(
    overrides: [
      appLoggerProvider.overrideWithValue(appLogger),
    ],
    observers: [
      if (kDebugMode)
        AppLoggerProviderObserver(
          appLogger,
          include: {
            // Codegen names look like authControllerProvider
            'authControllerProvider',
            'bootstrapControllerProvider',
          },
        ),
    ],
  );

  runApp(
    UncontrolledProviderScope(
      container: container,
      child: const MyApp(),
    ),
  );
}

Custom minimum level:

appLoggerProvider.overrideWithValue(
  ConsoleAppLogger(minLevel: AppLogLevel.info),
);

Using the logger in features #

Depend on the abstraction only. Prefer a shared tag constants file in your app (for example core/logging/log_tags.dart) instead of string literals:

final log = ref.read(appLoggerProvider);

log.info('asr', 'transcription started');
log.error(
  'rtc',
  'join channel failed',
  error: e,
  stackTrace: st,
);

// Large payloads (network bodies, etc.): default chunk size is 800
log.debugChunked('net', responseBody);

Do not put tokens, passwords, emails, or full URLs in log messages.

Provider Observer #

AppLoggerProviderObserver is off by default. Mount it only in debug:

Callback Level Filtered by include?
didAddProvider debug No
didDisposeProvider debug No
didUpdateProvider debug Yes (null = all updates; noisy)
providerDidFail error No

include matches context.provider.name. Codegen providers already have names such as authControllerProvider. Hand-written providers without name: never match a whitelist.

Failures observed here are breadcrumbs only (see sink contract below). Your app still owns explicit error reporting.

AppLogSink contract #

AppLogSink is a breadcrumb channel. Implementations may do lightweight logging (for example FirebaseCrashlytics.instance.log) and must never call error-reporting APIs such as recordError. Error reporting stays at the business boundary so each failure is recorded once.

Override the sink from bootstrap:

final container = ProviderContainer(
  overrides: [
    appLogSinkProvider.overrideWithValue(MyCrashlyticsBreadcrumbSink()),
    // Or pass sink into ConsoleAppLogger(...) and override appLoggerProvider.
  ],
);

This package ships no Firebase (or other) sink implementation.

Testing #

final fake = FakeAppLogger();
final container = ProviderContainer(
  overrides: [
    appLoggerProvider.overrideWithValue(fake),
  ],
);

container.read(appLoggerProvider).info('rtc', 'hello');
expect(fake.entries, hasLength(1));

When testing ConsoleAppLogger itself, call ConsoleAppLogger.debugResetForTest() between tests to reset the process-wide format handler.

Suggested lint gates #

Keep feature code on AppLogger instead of ad-hoc prints:

# Ban print/debugPrint in lib (allow your bootstrap path if needed)
rg -n "\bdebugPrint\(|\bprint\(" lib --glob "*.dart"

# Ban direct package:logging / dart:developer imports in app code
rg -n "package:logging|import 'dart:developer'" lib --glob "*.dart"

Enable avoid_print in analysis_options.yaml (flutter_lints includes it).

License #

See LICENSE.

0
likes
0
points
338
downloads

Publisher

verified publisheradoptrack.com

Weekly Downloads

App Factory debug logging baseline (AppLogger abstraction + Riverpod bindings).

Repository (GitHub)
View/report issues

Topics

#logging #riverpod #flutter #debug

License

unknown (license)

Dependencies

flutter, flutter_riverpod, logging, riverpod_annotation

More

Packages that depend on app_factory_logging