An extensible and simple logging framework.
The cable
package provides a re-usable interface for logging and defining
custom logging destinations, such as:
- in-memory
- terminals
- file I/O
- remote web services
... and more.
Add cable
as under dependencies
in your pubspec.yaml
file:
dependencies:
cable: ^0.1.0
And that's it! See usage for details.
Out of the box cable
provides two top-level methods, log
and logLazy
.
For simple string messages, use log
:
void main() {
log('Hello World!');
}
And for more complex messages that will need to be computed, use logLazy
:
void main() {
logLazy(() => 'The 100th digit of PI is ${computePiDigits(100)}');
}
Depending on the severity level, the closure for logLazy
may not be invoked.
Both of these methods are intended to be for simpler use cases, with drawbacks:
- They just
print
string-like objects to console. - The default severity is
Severity.debug
(all messages). - They don't (immediately) support custom formatting, destinations, severity.
HINT: Define a default
Severity
using Dart declaration variables.In the VM, set
CABLE_DEFAULT_SEVERITY
to4
, orSeverity.warning
.$ dart bin/app.dart -dCABLE_DEFAULT_SEVERITY=4Read more about Dart declaration variables.
A Logger
class can be created and used for dependency injection:
void main() {
final logger = new Logger();
final service = new Service(logger: logger);
// ...
}
You can also set the severity threshold:
void main() {
final logger = new Logger(
severity: Severity.warning,
);
}
Or define a simple string formatter:
void main() {
final logger = new Logger(
// Writes string logs in the format of {name}: {message}.
formatter: (record) => '${record.origin}: ${record.payload}',
);
}
By default, a Logger
just prints to the console. You can also configure one:
NOTE: This package intentionally is sparse on opinions or specific destinations in order to reduce your transitive dependencies to an absolute minimum. We encourage you to write and contribute to
cable_*
packages that provide interesting destinations/endpoints forcable
!
void main() {
final logger = new Logger(
destinations: [
// Any class that implements Sink<Record>
],
);
}
Several built-in classes are available cross platform:
void main() {
final logger = new Logger(
destinations: [
// Does nothing.
LogSink.nullSink,
// Prints to console.
LogSink.printSink,
// Use any Sink<String> instance, such as a `StreamController`.
new LogSink.writeToSink(someEventController),
// Use any StringSink instance, such as a `StringBuffer`.
new LogSink.writeToBuffer(stringBuffer),
],
);
}
It's also easy to create your own plugin packages!
class FileSink implements Sink<Record> {
@override
void add(Record data) { /* Write to a file. */ }
@override
void close() { /* Close the file stream. */ }
}
void main() {
final logger = new Logger(
destinations: [new FileSink(/*...*/)],
);
}
It's possible to replace log
and logLazy
to forward to your own configured
Logger
instance at runtime - use scope
:
void runLogged(Logger logger) {
logger.scope(() => startApplication());
}
Using zones, any calls to log
or logLazy
inside of context of
startApplication()
will now use your custom logger
class, not the default
top-level function behavior.
We welcome a diverse set of contributions, including, but not limited to:
- Filing bugs and feature requests
- Send a pull request
- Or, create something awesome using this API and share with us and others!
For the stability of the API and existing users, consider opening an issue first before implementing a large new feature or breaking an API. For smaller changes (like documentation, minor bug fixes), just send a pull request.
All pull requests are validated against travis, and must pass.
Ensure code passes all our analyzer checks:
$ dartanalyzer .
Ensure all code is formatted with the latest dev-channel SDK.
$ dartfmt -w .
Run all of our unit tests:
$ pub run test