Transports
Transports are the key to Crispin. While Crispin itself acts as a "Singleton", transports are instantiated and given to Crispin as such
Crispin().addTransport(...)
.
Please note that no Transports come bundled with pub add crispin
Channels (under consideration)
While we currently don't support channels, we are thinking of supporting channel specific transports (e.g. Crispin('user_stuff').addTransport(//Transport configured for User logs)
).
Transport Foundational Understanding
All transports must extend CrispinTransport
abstract class. This class allows you to easily understand the available methods and parameters for each method, while controlling exactly what happens.
Enabling Log Levels
isEnabled
is not required it can provide granular control of a given transport. For instance, instead of using an environment key to conditionally add a given transport, you can decide what levels are available via environment key or whatever you want. That said, we do recommend controlling the enabling of levels via parameters to a given transport.
import 'package:crispin/crispin.dart';
import 'package:logger_crispin_transport/logger_crispin_transport.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
void main() {
Crispin().addTransport(LoggerCrispinTransport(LoggerCrispinTransportOptions(level: dotenv.get('LOGGER_LEVEL', 'warn'))));
}
Another way is to simply not implement the method
@override
Future<void> silly(String message, {Object? meta}) async {
// You can just fully ignore implementing a method but doing so means you're aware that you didn't implement it.
}
Project Specific Transports
If you'd like to make your own transport specific to a given project simply extend the CrispinTransport
abstract as shown in following:
import 'package:crispin/crispin.dart';
class PrintTransport extends CrispinTransport {
PrintTransport(this.highestLevel);
final String highestLevel;
bool isEnabled(int level) {
final isEnabled = CrispinLoggerLevel.isValidName(highestLevel);
if (isEnabled && highestLevel.isNotEmpty) {
return level <= CrispinLoggerLevel.getFromName(highestLevel);
}
return false;
}
///
@override
Future<void> info(String message, {Object? meta}) async {
if (isEnabled(CrispinLoggerLevel.info)) {
print('INFO: $message');
if (meta != null) {
print(' meta: $meta');
}
print('');
}
}
///
@override
Future<void> warn(String message, {Object? meta}) async {
if (isEnabled(CrispinLoggerLevel.warn)) {
print('WARN: $message');
if (meta != null) {
print(' meta: $meta');
}
print('');
}
}
///
@override
Future<void> debug(String message, {Object? meta}) async {
if (isEnabled(CrispinLoggerLevel.debug)) {
print('DEBUG: $message');
if (meta != null) {
print(' DEBUG meta: $meta');
}
print('');
}
}
///
@override
Future<void> silly(String message, {Object? meta}) async {
// You can just fully ignore implementing a method but doing so means you're aware that you didn't implement it.
}
///
@override
Future<void> error(String message, {Object? error, StackTrace? stackTrace}) async {
if (isEnabled(CrispinLoggerLevel.error)) {
print('ERROR: $message');
if (error != null) {
print(' error: ${error.toString()}');
}
if (stackTrace != null) {
print(' stackTrace: ${stackTrace.toString()}');
}
print('');
}
}
}
void main() {
Crispin().addTransport(PrintTransport('warn'));
Crispin().warn('this is a warning');
Crispin().info('Not enabled');
try {
throw Exception('Error for example');
} catch (error, stackTrace) {
Crispin().error('Handling Error', error: error, stackTrace: stackTrace);
}
}