logger icon indicating copy to clipboard operation
logger copied to clipboard

Is it worth to put logger in a singleton?

Open hectorAguero opened this issue 4 years ago • 5 comments

So, currently I use logger like this way

///logger.dart file
final Logger logger = Logger(printer: PrettyPrinter());
///main.dart file
void main() {
  logger.d(
      'Run with either `dart example/main.dart` or `dart --enable-asserts example/main.dart`.');
}

But I read some info about singleton in dart, so don't know if I win something using it this way

///logger.dart file
class Log {
  factory Log() => _instance;
  Log._privateConstructor();
  static final Log _instance = Log._privateConstructor();

  final Logger log = Logger(
    printer: PrettyPrinter(), // Use the PrettyPrinter to format and print log
  );
}
///main.dart file
void main() {
  Log().log.d(
      'Run with either `dart example/main.dart` or `dart --enable-asserts example/main.dart`.');
}

hectorAguero avatar Jul 24 '20 17:07 hectorAguero

I don't think it matters in this case. I would keep your code simple to understand. And I don't think the singleton pattern helps to make the code understandable.

In general I'm not a fan of globals and I pass my logger instances to my classes directly. It is a dependency of my class and as such I want to treat it that way. It goes counter to the accepted norm but I believe explicitness matters.

haarts avatar Jul 27 '20 08:07 haarts

I agree with @hectorAguero it is more intuitive becase we use print("some text") not Printer().print("some text")

for my side project I use logger as singleton and here is example code


class LoggerService {
  Logger _logger;

  static final LoggerService _instance = LoggerService._internal();

  static Logger instance = Logger();

  factory LoggerService() {
    return _instance;
  }

  LoggerService._internal() {
    // add initialization logic if needed example: Logger(printer: PrettyPrinter(methodCount: 0));
    _logger = Logger();
  }
}

void main() {
  LoggerService.instance.d('Log message with 2 methods');

  LoggerService.instance.i('Info message');

  LoggerService.instance.w('Just a warning!');

  LoggerService.instance.e('Error! Something bad happened', 'Test Error');

  LoggerService.instance.v({'key': 5, 'value': 'something'});
}

sultanmyrza avatar Jul 28 '20 11:07 sultanmyrza

I would also prefer the singleton approach.

fernando-s97 avatar Aug 06 '20 17:08 fernando-s97

I suspect that, though I haven't tested it, the initialisation clock needs to be a singleton so that it has the same offset for different Logger instances, no?

IanWorthington avatar Mar 19 '21 09:03 IanWorthington


class Log {
  late Logger _logger;

  Log._internal() {

    _logger = Logger();
  }

  static Logger to = _instance._logger;

  factory Log() => _instance;

  static late final Log _instance = Log._internal();

  static void v(dynamic message) {
    to.v(message);
  }

  static void d(dynamic message) {
    to.d(message);
  }

  static void i(dynamic message) {
    to.i(message);
  }

  static void w(dynamic message) {
    to.w(message);
  }

  static void e(dynamic message) {
    to.e(message);
  }

  static void wtf(dynamic message) {
    to.wtf(message);
  }
}

// if u use a singleton instance 
// use with
// Log.i(...)

yyong37 avatar Jan 12 '22 04:01 yyong37