Add a better `logger` library
We've looked at:
- https://pub.dev/packages/logger
- https://pub.dev/packages/loggy
Logger looks best and pretty extensible. The problem is initialization, but @nivisi had an idea of using mixins + configuration via a global function.
Speaking of logger.
We can use a global method to get a preconfigured logger instance:
file_output.FileOutput _fileOutput = file_output.FileOutput();
PrettyConsoleOutput _prettyConsoleOutput = PrettyConsoleOutput();
Logger getLogger({dynamic forObject}) {
return Logger(
printer: SimpleLogPrinter(forObject: forObject),
output: MultiOutput([_fileOutput, _prettyConsoleOutput]),
filter: ProductionFilter(),
level: kDebugMode ? Level.verbose : Level.info,
);
}
And then create a mixin:
mixin LoggableMixin {
@protected
late final Logger logger = getLogger(forObject: this);
@override
String toString() {
return runtimeType.toString();
}
}
So in the code we could do:
class AnyClassImpl extends AnyClass with LoggableMixin {
Future<void> anyMethod() {
logger.i('This is a logger message!');
return Future.value();
}
}
// This will be printed
01.02.03 04:05 [I] AnyClassImpl : This is a logger message!
Note: the message above contains the AnyClassImpl string that makes that line of information contextualized. To achieve this, SimpleLogPrinter that is created in the getLogger method does forObject.toString() under the hood. Once we obfuscate our code the toString overriding in the LoggableMixin will stop working. To fix this, we need to change the mixin a bit:
mixin LoggableMixin {
@protected
late final Logger logger = getLogger(forObject: this);
// This property will be used by the logger printer later on
// Could be overwritten in the class itself!
final String loggableName = runtimeType.toString();
}
So the simple printer could do sth like this to get the context name:
final contextName = forObject is LoggableMixin ? forObject.loggableName : forObject.toString();
Then in our AnyClass:
class AnyClassImpl extends AnyClass with LoggableMixin {
@override
final String loggableName = 'AnyClassImpl =)';
Future<void> anyMethod() {
logger.i('This is a logger message!');
return Future.value();
}
}
// This will be printed
01.02.03 04:05 [I] AnyClassImpl =) : This is a logger message!
Now it's a separate package: https://pub.dev/packages/contextual_logging