hyper_logger
Composable, beautiful logging for Dart. Zero config. Every environment.

Start logging in one line
import 'package:hyper_logger/hyper_logger.dart';
HyperLogger.info('Server started on port 8080');
No init call. No setup. It auto-detects your environment and picks the right output format. The method name is extracted from the stack trace automatically.
Add a type parameter for richer output
HyperLogger.info<AuthService>('User logged in');
HyperLogger.error<Database>('Query failed', exception: e, stackTrace: st);
The <T> type parameter adds the class name to the log prefix, turning
[main] Server started into [AuthService.login] User logged in. It's
always optional: omit it when you don't need it, add it when you do.
Every environment, one API
LogPrinterPresets.automatic() detects GCP, AWS, CI, and human
and selects the best format:
Terminal (emoji + box + ANSI colors)

IDE Run Console (emoji + ANSI color + prefix, no box)

CI (timestamp + prefix, machine-parseable)

Cloud Run / JSON (structured, Cloud Logging compatible)

Web (DevTools groups with %c CSS styling, console.dir for data)

Works on native, web, Flutter, and pure Dart.
Compose your own
Decorators are order-independent. Just pick what you want:
ComposablePrinter([
const EmojiDecorator(),
const AnsiColorDecorator(),
const BoxDecorator(lineLength: 100),
const PrefixDecorator(),
]);

Add logging to any class
class MyService with HyperLoggerMixin<MyService> {
void doWork() => logInfo('working');
}
That's it. logInfo, logError, logDebug, etc. are available
immediately. The type parameter provides the class name in the prefix.
Want per-class config? Override scopedLogger:
class PaymentService with HyperLoggerMixin<PaymentService> {
@override
final scopedLogger = HyperLogger.withOptions<PaymentService>(
tag: 'payments',
minLevel: LogLevel.warning,
);
void process() {
logInfo('Processing payment');
// Output: 💡 [PaymentService.process] [payments] Processing payment
}
}
Structured data and errors
Pass data: for pretty-printed JSON. Errors and stack traces render
in-box with level-appropriate colors:
HyperLogger.info<Portfolio>('Positions loaded', data: {
'count': 12,
'totalValue': 45230.50,
'currency': 'USD',
});

Full error with data + exception + stack trace:

Scoped loggers
Per-feature tags, level filters, and runtime mode toggling. Cached and
mockable via ScopedLoggerApi<T>:
final log = HyperLogger.withOptions<NoisyService>(
minLevel: LogLevel.warning,
tag: 'noisy',
);
log.info('filtered out'); // no-op
log.warning('gets through'); // only warnings and above
log.mode = LogMode.disabled; // toggle at runtime
Crash reporting
Attach a delegate for Crashlytics or Sentry. It fires automatically on
warning, error, and fatal calls:
HyperLogger.attachServices(
crashReporting: MyCrashReporter(),
);
The delegate fires even in LogMode.silent (output suppressed, reporting
active). See example/crash_reporting_example.dart.
Rate limiting
Put a log line in a build() method that triggers hundreds of times per
second, and your Dart process will freeze while the console tries to
catch up. ThrottledPrinter prevents this by rate-limiting any printer:
HyperLogger.init(
printer: ThrottledPrinter(LogPrinterPresets.terminal(), maxPerSecond: 30),
);
Request-scoped child loggers
Attach key-value context to every log call inside a unit of work (request, transaction, job) without restating the data per call:
void handleRequest(Request req) {
final log = HyperLogger.child<Handler>(context: {'requestId': req.id});
log.info('Received');
log.info('Authenticated', data: {'userId': req.user.id});
// Both lines carry requestId; the second carries userId too.
}
child(...) is uncached — each call returns a fresh logger so per-request
state doesn't leak across unrelated requests. From inside a class, the
mixin shortcut works the same way:
class UserService with HyperLoggerMixin<UserService> {
void handleRequest(Request req) {
final log = child(context: {'requestId': req.id});
log.info('Processing');
}
}
Cloud-shaped printers (GcpJsonPrinter, AwsJsonPrinter) merge the
context into the JSON root so log aggregators can correlate by it.
Interceptors: filter, redact, enrich, sample
HyperLogger.init(interceptors: [...]) runs each entry through a chain
of LogEntry? Function(LogEntry) — return the entry to pass it through,
return null to drop it. A throwing interceptor is isolated and skipped
so one bad hook can't black-hole the pipeline.
HyperLogger.init(
printer: LogPrinterPresets.automatic(),
interceptors: [
// 1. Drop noisy third-party logs entirely.
(e) => e.loggerName.contains('GoTrue') ? null : e,
// 2. Redact secrets from messages before they reach the printer.
(e) => LogEntry(
level: e.level,
message: e.message.replaceAll(RegExp(r'token=\S+'), 'token=***'),
object: e.object,
loggerName: e.loggerName,
time: e.time,
error: e.error,
stackTrace: e.stackTrace,
),
],
);
File output with rotation
RotatingFilePrinter appends entries to a file with optional rotation
(by size or interval), gzip compression, and retention. Async path
providers are supported for Flutter (path_provider):
Flutter snippet: depend on
path_providerand addimport 'package:path_provider/path_provider.dart';. TheRotatingFilePrinterconstructor itself does not transitively expose it.
final filePrinter = RotatingFilePrinter(
baseFilePathProvider: () async {
final dir = await getApplicationSupportDirectory();
return '${dir.path}/logs/app.log';
},
rotations: [
FileRotation.size(10 * 1024 * 1024), // rotate at 10 MB (continuous)
FileRotation.onStart(), // also rotate on every process start
],
retention: FileRetention(maxFiles: 5, compress: true),
onError: (error, stack) {
// surface IO failures to your monitoring; default is stderr
},
);
HyperLogger.init(printer: filePrinter);
// ... at shutdown:
await filePrinter.close(); // flushes pending writes + in-flight gzip
File output requires dart:io; on web the constructor throws
UnsupportedError.
Fan-out to multiple sinks
MultiPrinter dispatches every entry to a list of child printers — use
it when you want, say, a pretty terminal view and a rotating file
archive at the same time:
HyperLogger.init(
printer: MultiPrinter([
LogPrinterPresets.terminal(),
RotatingFilePrinter(
baseFilePathProvider: () => '/var/log/app.log',
rotations: [FileRotation.size(10 * 1024 * 1024)],
retention: FileRetention(maxFiles: 5, compress: true),
),
]),
);
Children are isolated — a throwing child doesn't stop the others from
receiving the entry. After the fan-out, if anything threw, MultiPrinter
raises a MultiPrinterError that the package's pipeline-error hook
catches (HyperLogger.setPipelineErrorHandler), so a broken sink
surfaces instead of disappearing silently. MultiPrinter is itself a
LogPrinter, so it composes: wrap it in ThrottledPrinter to throttle
the whole fan-out, or throttle just one child and leave the others alone.
Cloud platforms
Google Cloud Logging (GcpJsonPrinter), AWS CloudWatch (AwsJsonPrinter),
and Azure Application Insights (AzureJsonPrinter) are all first-class.
LogPrinterPresets.automatic() detects the runtime (GCP / AWS / Azure / CI)
and picks the right printer for you. To pin one explicitly:
HyperLogger.init(printer: LogPrinterPresets.aws());
// or .gcp(), or .azure()
For severity ≥ ERROR with both error and stack trace, the trace is
embedded into the cloud printer's message field so Cloud Error
Reporting (GCP), CloudWatch Logs Insights (AWS), and Application
Insights' search (Azure) auto-surface the exception. Azure's
printer additionally nests user context under customDimensions
to match the AppInsights traces table conventions.
Install
dependencies:
hyper_logger: ^0.1.0
Documentation
| Guide | |
|---|---|
| Configuration | Log levels, log modes, printer presets, filtering, ANSI colors |
| Custom printers | Printer interface, decorators, ThrottledPrinter, custom sinks |
| Scoped loggers | Tags, level filters, mode toggling, caching |
| HyperLoggerMixin | Mixin usage, delegation chain, scoped injection |
| Delegates | Crash reporting, error safety, mode interaction |
| Testing | Suppressing output, capturing logs, mocking, test patterns |
| Flutter integration | Error handling, debugPrint, build modes |
| Firebase Crashlytics | Crashlytics delegate, init ordering, production main.dart |
| Architecture | Pipeline design, internals, performance |
Examples: quick start | all presets | mixin | crash reporting | file logging | buffered remote
License
BSD 3-Clause. See LICENSE.
Libraries
- hyper_logger
- web
- Web-only entry point for
hyper_logger.