Logging
Log.info('post.created id=${post.id}');Log.debug('Cache miss for key $key');Log.warning('Payment retried');Log.error('Checkout failed', error, stackTrace);Every line is written to standard output, and to a file when one is configured:
[2026-09-02 09:48:22] production.ERROR: Checkout failed | Bad state: no gatewayThe format is timestamp, environment, level, message — so local.INFO and production.ERROR are distinguishable when logs from several environments end up in the same place.
Levels
| Method | Use for |
|---|---|
Log.debug |
Detail useful only while diagnosing something. |
Log.info |
Ordinary events worth a record. |
Log.warning |
Something recoverable that should not be normal. |
Log.error |
A failure. |
Each accepts an optional error and stack trace:
Log.error(Object message, [Object? error, StackTrace? stackTrace]);The error is appended after a |, and the stack trace on the following lines.
Configuration
The log path comes from your application config:
Map<String, dynamic> get app => { 'log_path': 'storage/logs/app.log',};The path is resolved against the application’s base path, and directories are created as needed. Remove the key and logs go to standard output only — which is what you usually want in a container, where the runtime collects stdout.
Log.environment is set from APP_ENV when the application is created.
Writing Somewhere Else
Log.sink is a plain StringSink, which makes logging testable and redirectable:
final buffer = StringBuffer();Log.sink = buffer;
Log.info('hello');
expect(buffer.toString(), contains('INFO: hello'));Logging and Error Handling
Unhandled exceptions are reported through Log.error automatically, with their stack trace. You do not need to log an exception you are about to throw — the handler does it.
HttpException and ValidationException are deliberately not logged. A 404 or a failed validation is an ordinary outcome, and recording them buries the failures that matter.
To send errors somewhere else as well, add a reporter rather than replacing the log:
.withExceptions((exceptions) { exceptions.report((error, stackTrace) => errorTracker.send(error, stackTrace));})See Error Handling.
Production Guidance
Write logs to stdout in containers and let the runtime collect them. Avoid passwords, bearer tokens, full request bodies, and other secrets; logs usually outlive the request and are visible to more systems and people than application data.
Use stable event-like messages such as post.created plus identifiers. They are
easier to search than prose that changes from one call site to another.