Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a better logger library #54

Open
johsoe opened this issue Jul 5, 2022 · 2 comments
Open

Add a better logger library #54

johsoe opened this issue Jul 5, 2022 · 2 comments

Comments

@johsoe
Copy link
Contributor

johsoe commented Jul 5, 2022

We've looked at:

Logger looks best and pretty extensible. The problem is initialization, but @nivisi had an idea of using mixins + configuration via a global function.

@nivisi
Copy link
Contributor

nivisi commented Jul 11, 2022

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!

@nivisi
Copy link
Contributor

nivisi commented Jan 20, 2023

Now it's a separate package: https://pub.dev/packages/contextual_logging

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants