app_factory_logging 0.0.2
app_factory_logging: ^0.0.2 copied to clipboard
App Factory debug-print baseline — AppLogger abstraction, debugPrint console, Riverpod bindings, FakeAppLogger, and AppLogSink breadcrumbs.
app_factory_logging #
Riverpod-native debug print baseline for Flutter apps.
This package gives you a small AppLogger abstraction, a console implementation
backed by Flutter's debugPrint, 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
ConsoleAppLoggerprints[LEVEL][tag] messageviadebugPrint - Debug builds print by default; release builds stay silent by default
- Optional ANSI colors by level (gray / cyan / yellow / red), off by default
- Per-instance
minLevelandenableConsoleOutput - Message truncation (default 2000 chars) and
debugChunkedfor large payloads - Generated keepAlive providers:
appLoggerProvider/appLogSinkProvider FakeAppLoggerfor unit tests- Optional debug-only
AppLoggerProviderObserver AppLogSinkinterface 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.)
- Structured DevTools
developer.log(may be added later if needed)
Release builds do not print by default (enableConsoleOutput defaults to
kDebugMode). In release, prefer an optional AppLogSink for breadcrumbs.
Disable console output:
ConsoleAppLogger(enableConsoleOutput: false);
Enable ANSI colors (some IDEs / CI show escape codes as plain text):
ConsoleAppLogger(useAnsiColors: true);
Installation #
dependencies:
app_factory_logging: ^0.0.2
flutter pub get
Quick Start #
Create one logger instance, override the provider with it, and optionally attach the provider observer in debug:
import 'package:app_factory_logging/app_factory_logging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
final appLogger = ConsoleAppLogger(
// useAnsiColors: true,
// sink: MyCrashlyticsBreadcrumbSink(...),
);
final container = ProviderContainer(
overrides: [
appLoggerProvider.overrideWithValue(appLogger),
],
observers: [
if (kDebugMode)
AppLoggerProviderObserver(
appLogger,
include: {
'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));
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"
Enable avoid_print in analysis_options.yaml (flutter_lints includes it).
License #
See LICENSE.