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.0And 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
printstring-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
Severityusing Dart declaration variables.In the VM, set
CABLE_DEFAULT_SEVERITYto4, 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