steno 0.1.0
steno: ^0.1.0 copied to clipboard
Structured-first, async-safe, pluggable logging for Dart and Flutter. Built around an immutable LogEvent with scopes, spans, redaction, sampling, batching, and multi-sink fan-out.
// A walking tour of the steno API. Run with:
//
// dart run example/steno_example.dart
//
// You should see colored, structured output for each section.
// ignore_for_file: avoid_print
import 'package:steno/steno.dart';
Future<void> main() async {
// 1. Pick a profile. Development gives you colored, verbose output.
Steno.configure(LoggerProfile.development());
final root = Steno.get('app');
root.info('app started', fields: {'pid': 4242});
// 2. Child loggers carry default fields and tags.
final auth = root.child('auth', fields: {'module': 'auth'});
auth.debug('hashing password');
auth.info('user signed in', fields: {'userId': 'u_42'}, tags: ['auth']);
// 3. Scopes attach inherited fields to every event inside the body —
// even across awaits.
await LogScope.run({'requestId': 'r_001'}, () async {
auth.info('parsing token');
await Future<void>.delayed(const Duration(milliseconds: 5));
auth.info('token ok'); // still carries requestId
});
// 4. Spans measure operations and propagate trace ids automatically.
await auth.runSpan('verify-token', (span) async {
span.setField('audience', 'web');
await Future<void>.delayed(const Duration(milliseconds: 12));
auth.info('token claims ok'); // inherits the span's trace id
});
// 5. Reconfigure on the fly. Switch to JSON for production-style output.
Steno.configure(LoggerProfile.production().copyWith(
minLevel: LogLevel.info,
));
root.info('switched to production profile', fields: {
'password': 'should-be-redacted',
'userId': 'u_42',
});
// 6. Errors are first-class. Try/catch produces a real LogEvent.
try {
throw StateError('something blew up');
} catch (e, st) {
root.error('handled exception', error: e, stackTrace: st);
}
// 7. Lazy field building only runs if the level is enabled.
root.debug('this is dropped at info level',
fieldsBuilder: () => <String, Object?>{'expensive': _bigPayload()});
// 8. Diagnostics are exposed via Steno.health.
print('--- health ---');
print(Steno.health.snapshot());
await Steno.flush();
}
Map<String, Object?> _bigPayload() {
print('_bigPayload was called — would not run if log level was debug');
return {'k': 'v'};
}