patterncsharpMinor
Injectable logging with NLog and Ninject
Viewed 0 times
logginginjectablenlogwithninjectand
Problem
I have been using NLog for logging purposes in my web applications, but it was not injectable. More precisely, each class using logging declared the logger like this:
Since my logging is very simple, I have defined some extension methods to easily log any message and/or exception information:
It is clear that everything is static and I cannot replace logging while automatic testing takes place, for example. So, I thought about injecting the logging mechanism.
First, I have read this article, but it looks quite complicated for my needs, so I thought of giving a try on my own.
The service
```
public class LoggingService : IL
private static Logger logger = LogManager.GetCurrentClassLogger();Since my logging is very simple, I have defined some extension methods to easily log any message and/or exception information:
public static class NLogExtensions
{
public static void LogEx(this Logger logger, LogLevel level, String message)
{
logger.Log(level, message);
}
public static void LogEx(this Logger logger, LogLevel level, String format, params object[] parameters)
{
logger.Log(level, format, parameters);
}
public static void LogEx(this Logger logger, LogLevel level, IList list)
{
String output = String.Join("; ", list);
LogEx(logger, level, output);
}
public static void LogEx(this Logger logger, LogLevel level, String message, Exception exc)
{
try
{
GlobalDiagnosticsContext.Set("FullExceptionInfo", exc.ToString());
logger.Log(level, message, exc);
}
finally
{
GlobalDiagnosticsContext.Remove("FullExceptionInfo");
}
}
public static void LogEx(this Logger logger, LogLevel level, String format, Exception exc, params object[] parameters)
{
try
{
GlobalDiagnosticsContext.Set("FullExceptionInfo", exc.ToString());
logger.Log(level, format, parameters);
}
finally
{
GlobalDiagnosticsContext.Remove("FullExceptionInfo");
}
}
}It is clear that everything is static and I cannot replace logging while automatic testing takes place, for example. So, I thought about injecting the logging mechanism.
First, I have read this article, but it looks quite complicated for my needs, so I thought of giving a try on my own.
The service
```
public class LoggingService : IL
Solution
Your implementation looks all right. It should be able to injected by any DI tool as you work with abstractions.
But I got couple of improvement notes:
-
Logger type:
This would generate yournamespace.LoggingService as the logger.
I believe key part of your log file is to identify where the log has been originated/written. Therefore create a logger base on the caller's type (where the logger file being used)
Instead of having overload methods think of having self explanatory method and consumers of your logger would have better understanding what method would appropriate for the given situation.
e.g Info, Debug, Exception, LogException, LogExceptionWithParameters etc.
Think about given meaning full names for the following methods in your implementation.
As a side note;
If I'm were you I would implement a Logger factory to create loggers base on the caller's type.
Eg.
Factory
Logger
Usage
But I got couple of improvement notes:
-
Logger type:
private static Logger logger = LogManager.GetCurrentClassLogger();This would generate yournamespace.LoggingService as the logger.
I believe key part of your log file is to identify where the log has been originated/written. Therefore create a logger base on the caller's type (where the logger file being used)
- self explanatory methods:
Instead of having overload methods think of having self explanatory method and consumers of your logger would have better understanding what method would appropriate for the given situation.
e.g Info, Debug, Exception, LogException, LogExceptionWithParameters etc.
Think about given meaning full names for the following methods in your implementation.
void Log(LogLevel level, String format, params object[] parameters)
void Log(LogLevel level, IList list)
void Log(LogLevel level, String message, Exception exc)
void Log(LogLevel level, String format, Exception exc, params object[] parameters)As a side note;
If I'm were you I would implement a Logger factory to create loggers base on the caller's type.
Eg.
Factory
public interface ILoggerFactory
{
ILogger Create() where T : class;
}
public class LoggerFactory:ILoggerFactory
{
public ILogger Create() where T : class
{
return new Loger(typeof(T));
}
}Logger
public interface ILogger
{
string Name { get; }
void Debug(string message);
}
public class Loger:ILogger
{
private readonly NLog.Logger _logger;
public Loger(Type type)
{
if(type==null)
throw new ArgumentNullException("type");
_logger = LogManager.GetCurrentClassLogger();
}
public string Name {
get { return _logger.Name; }
}
public void Debug(string message)
{
_logger.Debug(message);
}
}Usage
var logger = loggerFactory.Create();
logger.Debug("some debug message");Code Snippets
private static Logger logger = LogManager.GetCurrentClassLogger();void Log(LogLevel level, String format, params object[] parameters)
void Log(LogLevel level, IList<String> list)
void Log(LogLevel level, String message, Exception exc)
void Log(LogLevel level, String format, Exception exc, params object[] parameters)public interface ILoggerFactory
{
ILogger Create<T>() where T : class;
}
public class LoggerFactory:ILoggerFactory
{
public ILogger Create<T>() where T : class
{
return new Loger(typeof(T));
}
}public interface ILogger
{
string Name { get; }
void Debug(string message);
}
public class Loger:ILogger
{
private readonly NLog.Logger _logger;
public Loger(Type type)
{
if(type==null)
throw new ArgumentNullException("type");
_logger = LogManager.GetCurrentClassLogger();
}
public string Name {
get { return _logger.Name; }
}
public void Debug(string message)
{
_logger.Debug(message);
}
}var logger = loggerFactory.Create<CallerClass>();
logger.Debug("some debug message");Context
StackExchange Code Review Q#124450, answer score: 3
Revisions (0)
No revisions yet.