Use Singleton pattern for error logging class? - c#

I currently have a class written in C# which does some simple error logging stuff. It's been used quite extensively throughout my project.
class LogError
{
//constructor
public LogError() { }
//public methods
public void saveToTextFile() { }
//other similar methods...
}
But, it doesn't seems a good design of this class, as every time I have to create an instance of LogError class before saveToTextFile() method can be used.
So I am thinking of re-designing this class. Would this be a good case to apply Singleton pattern? What about making it static class instead? Any suggestions? Thanks.

The problem with Singleton is that it's hard to use different logging behaviour. Image you want to introduce a "Send an email instead of write to text file" later. It's basically the same if you have
new LogError().DoSomething();
or
LogError.Instance.DoSomething();
except for performance and/or implementation of the LogError class itself.
If you want to add flexibility, you'd better use Dependency Injection (which makes your code clearer than with the Singleton, in addition) or Dependency Lookup (which is somewhere in between).

I would look at Apache log4net. You don't have to worry about anything. You can configure it to log to multiple targets from your configuration file (or in code). The log message template is fully customizable. You can filter and route different log levels (debug/info/warning/error). It's really not worth reinventing the wheel here.

Yes make it singleton and also thread safe

If you are using , any container ( Autofac, Unity etc) then you can make use of the container.
Singleton can be broken ( By using Reflection so be informed )
one of the implementation would be ( this would not required explicit locking )
public class MySingleton
{
private static readonly MySingleton _singtonInstance = new MySingleton();
private MySingleton()
{
}
public static MySingleton SingtonInstance
{
get { return _singtonInstance; }
}
}

You can use interface as your log system facade, like
interface ILoggerFacade{
void Error(Exception e);
void Warning(Exception e);
....
}
after that you need to make interface implementation
class SimpleLogger:ILoggerFacade{
void Error(Exception e){//logging error};
...
}
and finnaly you need enter point to your logger. I ussually use static class but singleton is variant also.
static class sample:
class StaticLogger{
private ILoggerFacade _logger;
StaticLogger(){
//choose ILoggerFacade implementation
_logger=new SimpleLogger();
}
public static ILoggerFacade Logger{
get{ return _logger;}
}
}
If you will use facade interface you can easy change loggers in your project if it will be need.

There is a solution where you have a logging method that is being called once there are exceptions happen anywhere in your application. All you need to have is a general or common exception handler. Here's how.
On your Program.cs (inside your Main() method before the Application.Run) add this code.
Application.ThreadException += CommonExceptionHandler;
Create CommonExceptionHandler event on your Program.cs file let's say next to Main method.
private static void CommonExceptionHandler(object sender, ThreadExceptionEventArgs t)
{
LogError(t.Exception);
}
Create LogError Method on your Program.cs
public static void LogError(Exception ex)
{
var errMsg = ex.Message;
errMsg += ex.InnerException != null ? ex.InnerException.Message : string.Empty;
//TODO: Do what you want if an error occurs
}
This will catch all exceptions occur in your application. You don't need to worry anymore whether you would call your error log class for every catch block in all of your methods

Related

How to make wrapper around TraceSource class thread safe

I have written a wrapper (Custom Logger class) around TraceSource class to have more control over the way other developers will use this custom Logger and log data/messages at various levels.
Below is the code with implementation just for verbose, error and info levels.
public class Logger : ILogger
{
private const int DEF_ERROR_EVENT_ID = 2;
private const int DEF_INFORMATION_EVENT_ID = 4;
private const int DEF_DEBUG_EVENT_ID = 5;
private static TraceSource source = null;
public Logger(string nameOfComponent)
{
source = new TraceSource(nameOfComponent);
}
public void LogDebug(Type type, string methodName)
{
if (type!=null)
throw new ArgumentNullException(type.ToString());
source.TraceEvent(TraceEventType.Verbose, DEF_DEBUG_EVENT_ID, string.Format("{0}.{1}",type.ToString(),methodName));
}
public void LogError(string message, Exception ex)
{
if (String.IsNullOrEmpty(message) && ex == null)
throw new ArgumentNullException(message, ex.ToString());
source.TraceData(TraceEventType.Error, DEF_ERROR_EVENT_ID, message, ex);
}
public void LogInformation(string message)
{
if (String.IsNullOrEmpty(message))
throw new ArgumentNullException(message);
source.TraceInformation(message);
}
}
I'm initializing a static variable "source" in the Logger class' non-default constructor (given the fact that this code is going to run in a multi-threaded environment) is this practice fine in terms of thread-safety ? Though MSDN documentation says that TraceSource is thread-safe and various methods such as TraceSource.TraceData(),TraceSource.TraceEvent() etc. also take thread-safety into consideration around all the trace listeners writing out trace logs.Since I'm planning to instantiate Logger class individually across each class in my web app as below.
private ILogger log = new Logger("name of the source/class");
What would the best way to do so in a multi-threaded environment? Will using a DI container like Ninject or Autofac make Logger class thread-safe or shall I create a singleton and use it or reuse it across the entire app to make it thread-safe. The problem that I'm facing if I create a singleton instance of Logger class is that I won't be able to pass a string as parameter to Logger class' non-default constructor and eventually the same string to TraceSource class to know the name of the source or component on the run or on the fly.
Some of you might say why am I re-inventing the wheels and creating a wrapper around TraceSource rather than using TraceSource directly as such. But as mentioned in the beginning of my question is that I want to have more control over what is being sent as a log to a file or database.
I can't comment yet- so would have asked why you're creating a custom logger rather than using NLog. If you did this then static log instances in NLog are threadsafe:
private static Logger logger = LogManager.GetLogger("MyClassName");
Because loggers are thread-safe, you can simply create the logger once and store it in a static variable.
See more here: https://github.com/NLog/NLog/wiki/Tutorial
Nlog is highly configurable, and appears to be fit for purpose for the use case you described.
HTH

How can I wire StructureMap with 2 different objects (log4net loggers) of the same interface

I have a class named MyClass, which uses two different loggers named Logger1 and Logger2. I use log4net for logging, and want to use StructureMap for DI.
Without StructureMap, my class would look like this:
public class MyClass
{
private static readonly ILog Logger1 = LogManager.GetLogger("Logger1"); // Loggers are configured in a config file
private static readonly ILog Logger2 = LogManager.GetLogger("Logger2");
public void DoSomething()
{
...
Logger1.Info("did something");
...
Logger2.Info("need to log this elsewhere");
}
}
Introducing DI, with StructureMap (using v3.0.3), I would make the loggers instance members, and inject them into the constructor, like this:
public class MyClass
{
private readonly ILog Logger1;
private readonly ILog Logger2;
myClass(ILog logger1, ILog logger2)
{
this.Logger1 = logger1;
this.Logger2 = logger2;
}
public void DoSomething()
{
...
Logger1.Info("did something");
...
Logger2.Info("need to log this elsewhere");
}
}
The thing is, I cannot get StructureMap to wire this up for me properly. I tried wiring the loggers like this:
For<ILog>.Use(()=> LogManager.GetLogger("Logger1")).Named("Logger1");
For<ILog>.Use(()=> LogManager.GetLogger("Logger2")).Named("Logger2");
Doing this Gets me empty (unconfigured) loggers). Replacing Use() with Add() gives my an exception due to not having a default instance registered for ILog.
Does anybody know how I can do this?
If the loggers perform different roles then I would create two interfaces inheriting from ILog to reflect this. That way you would have no problem configuring StructureMap to handle them.
I ended up doing the following: I created two interfaces as per Rob's advice: ILogger1 and ILogger2. Since the both have the same API, as I need the same kind of functionality from them, they both inherit from the same interface - though not log4net.ILog as per Steven's advice:
interface IMyLog
{
void Info(object message);
void Info(string format, params object[] args);
}
interface ILogger1 : IMyLog { }
interface ILogger2 : IMyLog { }
Also, since the implementation of this API is the same for my needs, I have one concrete class MyLogger, implementing both ILogger1 and ILogger2. If I ever need the implementations to be different it will be easy for me to have explicit interface implementation, or separate classes. Only My Logger takes a dependency on log4net, as it uses it for its implementation:
enum LoggerType { Logger1, Logger2 }
internal class MyLogger : ILogger1, ILogger2
{
private readonly ILog _log;
public MyLogger(LoggerType loggerName)
{
switch (loggerName)
{
case LoggerType.Logger1:
_log = LogManager.GetLogger("first-log");
break;
case LoggerType.Logger2:
_log = LogManager.GetLogger("second-log");
break;
default:
throw new ArgumentException("Invalid logger name", "loggerName");
}
}
public void Info(object message)
{
_log.Info(message);
}
public void Info(string format, params object[] args)
{
_log.InfoFormat(format, args);
}
}
In order to register it with StructureMap, I used the following code in the registry:
For<ILogger1>().Use<MyLogger>().Ctor<LoggerType>("loggerName").Is(LoggerType.Logger1).Singleton(); // I want only one logger per type
For<ILogger2>().Use<MyLogger>().Ctor<LoggerType>("loggerName").Is(LoggerType.Logger2).Singleton();
It all works wonderfully. So, thanks to Steven and Rob for their advice. I really learned something. I wish I could upvote an answer and a response more than once.
So, to summarize, I:
Created a separate interface for each kind of logger (even saying it now sounds intuitive).
Created a base interface for the logger interfaces, because for my needs they have the same API (YMMV)
Created one concrete logger adapter that implements both interfaces because that suits my needs (YMMV again)
Share the implementation of the interfaces' API, for the above reasons
Registered each interface to create a concrete logger with a different type passed in the constructor
configured the concrete logger with log4net using a Factory Method to determine which logger to use
As an alterative to the answers above, this can be solved exclusively in StructureMap (and I believe works for the SM version used in the question). You can tell StructureMap exactly how to build MyClass by also including the following in a Registry.
For<MyClass>().Use(x => new MyClass(x.GetInstance<ILog>("Logger1"), x.GetInstance<ILog>("Logger2")));

Extension Methods needing a Unity Resolve

I have a few extension methods that are fairly core to my app. I use them to route all calls to my OData service through a central Exception Handler. It looks like this:
var results = Entites.Customers.Where(x=>x.IsActive).Invoke();
The Invoke() is my extension method, and it all works great!
But when I get an exception, I would like to log it.
The problem I finding is that my ILogger cannot be resolved inside a static class (the class must be static for it to have extension methods.)
Is there any way to resolve a unity managed interface inside of a static Class? Or is the Dependency Injection pattern just not able to cope with this C# feature?
One option would be to just not have any implementation in the static class. Create a non-static class that contains the implementation of the method (not as an extension method) then have the extension method do nothing besides call the non-extension implementation.
After doing that the implementation is no longer in a static class.
public static class MyExtension
{
public static void Invoke<T>(this IQueryable<T> query)
{
MyExtensionImplementation.Invoke(query);
}
}
internal class MyExtensionImplementation
{
public static void Invoke<T>(IQueryable<T> query)
{
//actual work
}
}
A bad news - there is no way to do this, a good news - you don't need to log exceptions inside your extension methods. Just let an exception to be throwen outside the static class and handle it in a proper way.
IResult results;
try
{
results = Entites.Customers.Where(x=>x.IsActive).Invoke();
}
catch(YourOwnException ex)
{
Log(ex, "The Business logic error.");
}
catch(ArgumentException ex)
{
Log(ex, "Invalid arguments.")
}
...
catch(Exception ex)
{
Log(ex, "Unknown error.");
}
EDIT:
Most of them are communications related and would be handled in the
extension method. Just a few that are business related will be
rethrown.
If exceptions are "communications related" or 3-rd party, maybe you don't need to log them. In this case I would create a TryInvoke() method without logging, which returns TRUE for a success operation and has an OUT parameter. If you want to log them you should inject ILogger inside your Invoke() method.
if(Entites.Customers.Where(x=>x.IsActive).TryInvoke(out results))
{
// Success
}

Implementing DI in a particular situation

I'm trying to implement DI in a class, but I'm not sure that my design is appropriate.
The relevent code in the class I want to add DI to
class DoerValidation
{
public DoerValidation()
{
compileData();
}
private void compileData()
{
doersActive = Doer.GetActiveDoers();
//...
}
}
And in my Doer class
public partial class Doer
{
private static readonly DoerRepository repository = new DoerRepository();
public static IEnumerable<Doer> GetActiveDoers()
{
return repository.Doers.Where(c => c.Person.IsActive);
}
}
I just don't get how I could implement DI in this situation. Maybe the GetActiveDoers method is bad design? Where would you put this method otherwise?
Would it be a good practice to start adding new methods directly in the repository? Some people told me it should stay clean so it implements only this
public interface IDoerRepository
{
IQueryable<Doer> Doers { get; }
void SaveDoer(Doer doer);
void DeleteDoer(Doer doer);
}
It sounds like you need to inject the DoerRepository into DoerValidation basically - pass it into the constructor.
Both the GetActiveDoers and the static variable go against the principles of DI, IMO.
Static methods and properties are procedural in nature. If you expose your GetActiveDoers() method statically, there is no way to inject its functionality -- clients can only ignore it or use it inline wherever it's needed.
If you're committed to DI and to a static implementation, you need to write an instance wrapper for that static class and inject the instance wrapper.

Log4net - optimal strategy when using inheritance

I have integrated log4net in my app. I have a few helper methods to assist in logging which call log4net. When refactoring, I plan to move these methods to base class so that the code is not repeated in other derived classes.
Without the inheritance model, following worked correctly in each class
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
Placing the above in the base class will return the declaring type as base class and not derived class.
What is an optimal way to move this declaration to the base class?
At present, I can think of a few ways to achieve this but don't find them optimal.
I think I would do this:
LogManager.GetLogger(this.GetType());
Based on Sefan's answer here's how I declared it in the base class
/// <summary>
/// This is delay loaded to allow us to capture the class type of the inherited class on request
/// </summary>
private ILog log = null;
protected ILog Log
{
get
{
if (log == null)
{
log = LogManager.GetLogger(this.GetType());
}
return log;
}
}
We just redeclare it in each class that needs a logger (the point of it being a private static) and use a code snippet to make that as simple as typing log<tab><tab> if you wanted to get extra fancy though you could do something like:
public class Loggable<T> where T : Loggable<T>
{
private static readonly ILog log = LogManager.GetLogger(typeof(T));
protected static ILog Log
{
get
{
return log;
}
}
}
And punch T through your inheritance hierarchy so that it is the most derived class.
The problem with all of the answers here is that you lose information about where log messages are coming from, so I would personally stick to your original code despite the added boilerplate.

Categories