How do I log everywhere in the program, without having to declare ILogger parameter in every class? I would like best practice to log everywhere within program.
MyClass(ILogger<MyClass> logger)
{
_logger = logger;
}
Should I utilize a static class as described here?
public class ApplicationLogging
{
private static ILoggerFactory _Factory = null;
public static void ConfigureLogger(ILoggerFactory factory)
{
factory.AddDebug(LogLevel.None).AddStackify();
factory.AddFile("logFileFromHelper.log"); //serilog file extension
}
public static ILoggerFactory LoggerFactory
{
get
{
if (_Factory == null)
{
_Factory = new LoggerFactory();
ConfigureLogger(_Factory);
}
return _Factory;
}
set { _Factory = value; }
}
public static ILogger CreateLogger() => LoggerFactory.CreateLogger();
}
I think it's not a good idea to use a logger a static dependency. Personally, I would inject it in the constructor of the class. Why? Well, static dependencies in form of a static property have the following problems:
In the case of unit tests, they are hard to mock. If you inject the logger in the CTOR you can libs like Moq to change the logging to e.g. stdout (ok, that's also possible with e.g. log4net's config file).
Using static properties can make your code "non-determistic". Why? A static property is initialized when the class is referenced the first time. So if you change your code the static property initialization may be called earlier or later. If you've a bug in the initialization it will be hard to find. Why? Because you've no logging.
If you want to change the logging framework, you've to find all static references to it. Ok, that's not a that hard task with grep or modern IDEs. However, if you inject the logger dependency the compiler will show (based on the compile errors) which lines of code you've to change (simply remove the logger reference from the solution file).
Hope that helps.
Related
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
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")));
I'm using log4net in an application for logging.
I want to avoid a discussion about implementing a logging facade, but essentially, I'm creating some classes which will allow an ILog implementation to be injected via the constructor. Eg:
abstract class MigratorBase<T> : IMigrator<T>
{
private ILog logger;
public MigratorBase(ILog logger)
{
this.logger = logger;
}
}
I also would like to provide a default constructor on the class, which if called, essentially disables logging (or logs to nothing). Instead of scattering fragments of code that check if the logger is null, such as this:
if (this.logger != null)
Log.DebugFormat("Connecting to {0}", this.href);
I thought a better way to accomplish this functionality would be to assign an implementation of ILog that was purely empty methods. I could call it a NullLog, and would look similar to this:
class NullLog : ILog
{
public void Debug(object message, Exception exception) { }
public void Debug(object message) { }
public void DebugFormat(IFormatProvider provider, string format, params object[] args) { }
...
...
}
and then in the default constructor I could assign an object of this type to the class's private member, as such:
abstract class MigratorBase<T> : IMigrator<T>
{
private ILog logger;
public MigratorBase(ILog logger)
{
this.logger = logger;
}
public MigratorBase()
{
this.logger = new NullLog();
}
}
This approach seems more object oriented to me, so I think I like it, but googling seems to reveal people suggesting that it's a bad idea to implement an interface with empty methods.
Can anyone suggest why the above might be a bad idea? Or is it in fact an ok idea?
What you describe is called the Null Object pattern. Martin Fowler coined this term and explains it thoroughly in the book Patterns of Enterprise Application Architecture.
I think this is a great pattern to remove all the if-conditions in the code to check for not null. A downside could be that you have to explain a pattern in you development team and maybe add a comment about not adding functionality inside your NullLog class. Otherwise I couldn’t find a downside with this pattern.
I have a class with a static constructor which I use to read the app.config values. How do I unit test the class with different configuration values. I'm thinking of running each test in different app domain so I can have static constructor executed for each test - but I have two problems here:
1. I do not know how to run each test run in separate app domain and
2. how do I change configuration settings at run time?
Can someone please help me with this? Or anyone has a better solution? Thanks.
Personally I would just stick your static constructor into a static method then execute that method in the static block.
You don't need to test .Net being able to load data from config files.
Instead, try to concentrate on testing your own logic.
Change your class so that it gets the configuration values from its constructor (or via properties), and then test it as you would with any other dependency.
Along the way you have also moved your class towards SRP.
As per the configuration loading - concentrate this logic in a separate, non-static class.
EDIT:
Separate the configuration logic into another class. something like this:
public static class ConfigurationLoader
{
static ConfigurationLoader()
{
// Dependency1 = LoadFromConfiguration();
// Dependency2 = LoadFromConfiguration();
}
public static int Dependency1 { get; private set; }
public static string Dependency2 { get; private set; }
}
Then, when you instantiate your class, inject it with the dependencies:
public class MyClass
{
private readonly int m_Dependency1;
private readonly string m_Dependency2;
public MyClass(int dependency1, string dependency2)
{
m_Dependency1 = dependency1;
m_Dependency2 = dependency2;
}
public char MethodUnderTest()
{
if (m_Dependency1 > 42)
{
return m_Dependency2[0];
}
return ' ';
}
}
public class MyClassTests
{
[Fact]
public void MethodUnderTest_dependency1is43AndDependency2isTest_ReturnsT()
{
var underTest = new MyClass(43, "Test");
var result = underTest.MethodUnderTest();
Assert.Equal('T', result);
}
}
...
var myClass = new MyClass(ConfigurationLoader.Dependency1, ConfigurationLoader.Dependency2);
You could go on and use IOC containers, but your problem of testing MyClass with different inputs is solved by this simple testable design.
If you read from (Web)ConfigurationManager.AppSettings, that is just a NameValueCollection, so you can replace your code that reads ConfigurationManager.AppSettings directly with code, that reads from any NameValueCollection.
Just move out your actual configuration parsing to a static method from the static ctor. Static ctor calls that static method and passes ConfigurationManager.AppSettings, but you can call that parser method from the test code, and verify the config parsing without actually touching a file, or messing with appdomains.
But on the long run, really inject your configuration parameters as seldary suggested. Create a configuration class, read the actual values at application start, and set up your IoC container to supply the same configuration instance to all requesters.
This makes further testing easier too, because you classes don't read from a global static configuration instance. You can just pass in a specific configuration instance for differet tests. Of course create a factory method for your tests, to construct a global configuration, so you don't have to do it manually all the time...
I had the same exact problem recently. The only difference was that the configuration value was coming from database instead of app.config. I was able to resolve it using TypeInitializer.
[Test]
public void TestConfigurationInStaticConstructor()
{
// setup configuraton to test
// ...
// init static constructor
ReaderTypeInit();
// Assert configuration effect
// ...
// reset static ctor to prevent other existing tests (that may depend on original static ctor) fail
ReaderTypeInit();
}
// helper method
private void ReaderTypeInit()
{
typeof(< your class with static ctor>).TypeInitializer.Invoke(null, new object[0]);
}
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.