Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a good practice to have logger as a singleton?

I had a habit to pass logger to constructor, like:

public class OrderService : IOrderService {      public OrderService(ILogger logger) {      } } 

But that is quite annoying, so I've used it a property this for some time:

private ILogger logger = NullLogger.Instance; public ILogger Logger {     get { return logger; }     set { logger = value; } } 

This is getting annoying too - it is not dry, I need to repeat this in every class. I could use base class, but then again - I'm using Form class, so would need FormBase, etc. So I think, what would be downside of having singleton with ILogger exposed, so veryone would know where to get logger:

    Infrastructure.Logger.Info("blabla"); 

UPDATE: As Merlyn correctly noticed, I've should mention, that in first and second examples I am using DI.

like image 728
Giedrius Avatar asked Dec 12 '11 10:12

Giedrius


People also ask

Should my logger be a singleton?

It is better to have an explicit dependency than to hide it via a singleton. But if singletons save you significant time, including all refactoring you will ever have to do (crystal ball time!), I suppose you might be able to live with them. If ever there were a use for a Singleton, this might be it.

Why the logger uses a singleton design pattern?

It is used where only a single instance of a class is required to control the action throughout the execution. A singleton class shouldn't have multiple instances in any case and at any cost. Singleton classes are used for logging, driver objects, caching and thread pool, database connections.

Is Python logging a singleton?

Singleton Logging ServiceLogging service that is guaranteed to be a singleton. Based on Python logging, but every instantiation of LoggingService from any of an application's modules returns the same logger instance.

Should service classes be singletons?

3 Answers. Show activity on this post. IMHO yes, services should not hold state and should therefore be made singleton.


2 Answers

I put a logger instance in my dependency injection container, which then injects the logger into the classes which need one.

like image 95
Daniel Rose Avatar answered Sep 25 '22 10:09

Daniel Rose


This is getting annoying too - it is not DRY

That's true. But there is only so much you can do for a cross-cutting concern that pervades every type you have. You have to use the logger everywhere, so you must have the property on those types.

So lets see what we can do about it.

Singleton

Singletons are terrible <flame-suit-on>.

I recommend sticking with property injection as you've done with your second example. This is the best factoring you can do without resorting to magic. It is better to have an explicit dependency than to hide it via a singleton.

But if singletons save you significant time, including all refactoring you will ever have to do (crystal ball time!), I suppose you might be able to live with them. If ever there were a use for a Singleton, this might be it. Keep in mind the cost if you ever want to change your mind will be about as high as it gets.

If you do this, check out other people's answers using the Registry pattern (see the description), and those registering a (resetable) singleton factory rather than a singleton logger instance.

There are other alternatives that might work just as well without as much compromise, so you should check them out first.

Visual Studio code snippets

You could use Visual Studio code snippets to speed up the entrance of that repetitive code. You will be able to type something like loggertab, and the code will magically appear for you.

Using AOP to DRY off

You could eliminate a little bit of that property injection code by using an Aspect Oriented Programming (AOP) framework like PostSharp to auto-generate some of it.

It might look something like this when you're done:

[InjectedLogger] public ILogger Logger { get; set; } 

You could also use their method tracing sample code to automatically trace method entrance and exit code, which might eliminate the need to add some of the logger properties all together. You could apply the attribute at a class level, or namespace wide:

[Trace] public class MyClass {     // ... }  // or  #if DEBUG [assembly: Trace( AttributeTargetTypes = "MyNamespace.*",     AttributeTargetTypeAttributes = MulticastAttributes.Public,     AttributeTargetMemberAttributes = MulticastAttributes.Public )] #endif 
like image 40
Merlyn Morgan-Graham Avatar answered Sep 21 '22 10:09

Merlyn Morgan-Graham