We have c# application with several different modules. We are using log4net for logging. What should be done to log the messages:
Create a centralized logging project: The application classes to use centralized logging project's dll's static methods to log the messages. So, no class in application creates the logger, all logging requirements to be fulfilled by this dll OR
All types in the application itself creating their own loggers: Easy to check which type generates which message, easy to manage different type of logging requirements i.e.we can throttle logging behavior of each type independently, like one class logging ALL logs but other only loggin ERROR.
What is the preferred practise?
The approach2 has its own benefit but approach1 looks clean as each class would no longer be responsible for calling "GetLogger(typeOf(className))".
What is the recommended way?
It really depends on the usecase, when making a library it can make sense to use method 1. However when making a complex program method 2 will help you to manage different logger independently. Method 2 will give the also the option to log all in you project like method 1 does. However method 1 does not support differing on logger. So method 2 seems a better choice in most cases.
Related
How it works in Serilog
Every ILogger in Serilog has useful method ForContext which essentially creates completely independent child logger with some properties attached.
This is useful for my case, when inside one ASP .NET Core host there are N independent device API's running, each managing some physically connected device. Each API can get it's own ILogger which will for contain property like DeviceName = "Device1", so one can setup appropriate filters in Seq/Greylog/etc.
How it works ASP .NET Core logging API
However, if one uses ILogger from Microsoft.Extensions.Logging, there is no direct counterpart for the ForContext method. The only alternative is BeginScope, which, unfortunately, does not create new isolated logger instance but instead adds values to the global logger scope, from what I understand.
To mitigate this problem, tools like AsyncLocal and SynchronizationContext are used. From what I understand, this works fine for things like correlating HTTP requests because they usually have clear async processing pipeline.
However, in my case each device API runs a chain of somewhat complex Rx .NET observable sequences on task pool scheduler. Even if it is possible to make all of that preserve SynchronizationContext, this will introduce a lot of unneeded complexity.
Question
Is there any way to create independent loggers and/or logger factories, each with their own scope/state? So that, similar to Serilog, anything that uses such logger will have additional properties attached regardless of calling thread or anything else, but these properties will be invisible to any other logger in the application?
Or should I just use Serilog.ILogger instead of Microsoft API, given that this app currently don't use Web API functionality anyway?
I've created a log4net wrapper class for my project team to use so we can all log from the same instance of log4net in our project. We're unsure what section this could come under i.e. Controller, one suggestion was to create a separate folder altogether for "Helper" classes.
Is there an industry standard to follow for this that we could use?
I can't speak to an 'industry standard' but for our application, putting the logging at the lowest level has worked best for us. We created our own class that wraps the 3rd party functionality in a one of our libraries referenced by nearly all others. Then we implemented our own methods to simplify and standardize logging in our app. This approach makes it possible to use logging anywhere without significant project changes. You'd just have to add static method calls where you need to log something.
No there's no industrial standard for such things. Nevertheless, instead of creating another wrapper for log4net consider using the existing one. Then simply register it in the DI of your choice and inject it via constructor.
I'm using Log4Net to handle logging in my WPF application.
Currently, the logger is configured with the rest of the front-end code. I have to pass a reference to the Service layer and the Repository layer if I want to be able to use the logger in these layers (I'll actually be using StructureMap for this). This means the back-end has a dependency on the front-end and I don't like that.
I'm wondering how best to handle this? Should I configure the logger in the Repository layer?
log4net LogManager.GetLogger(string name) will return an existing logger instance if it has already been created (e.g., in another layer), so there is no need to pass logger objects around.
You do need to be aware of multiple threads/processes trying to write to the same log file at the same time. You can use the log4net MinimalLock, or try this third party solution. Neither is ideal (the codeproject one is inefficient and still hits concurrency problems). I have ended up writing my own (which unfortunately is not publicly available).
Logging is a common cross-cutting concern that I have seen handled in several different ways. The simplest method is to create a static class that lives in a common assembly that is shared by all the layers.
However, since you are using StructureMap for your IoC, a better solution would be to configure StructureMap to inject your logger class (which might be configured as a singleton, depending on your needs) into each instance created. I personally prefer property injection for such cross-cutting concern classes, so that constructors don't get cluttered, but that's a matter of preference.
I am doing something unusual.
I have an application, it runs as a windows service.
what it does is that, it monitor one folder, when ever there is some new file put into that folder, the application will do something to the file.
Whenever there is an error when processing one file. I need to create a text file, and put the error/exception information into that text file. (later i can do something with this file)
so there is something like this
FileWatch, when there is a new file, do following :
try
{
processing file
}
catch(Exception ex)
{
MyLogger write exception message into one new text file
}
So far how i did it is that. I create a class for example MyLogger, whenever i new one MyLogger, it creates a text file (the name matters, need to be a specific format), and there is one method in side MyLogger "WriteError(string message)", it writes text into that file.
Since i used log4net in my application. Do you think i should modify my logger, to extend some class from log4net, so that i can get some benefit? (not sure what kind of benefit i will get, but log4net is a good logging framework, the way it handle text file might have thing that i do not aware)
Thanks
log4net or any other generic logger is helpful if
1) you want to have a consistent logging facility in many places across your application; and/or
2) you want the ability to customize logging format, level and so on.
From your description it sounds like there is a single point in your app where you need to log the exception in a specific way. If this is correct, you will probably gain no benefit from creating a custom logger - just write a method that logs exception to a file in the way you need.
If I misunderstood you, and there is a need for generic logger (that is, either 1) or 2) above is true), extending log4net by inheriting a logger or creating a wrapper is fine.
I've created log4net wrappers before. I find it handy to start this way as you don't always know what the logging requirements are at the start of a project. My rule has been that the log4net library can only be referenced from my own "logging" namespace. This way, the application code only calls the wrapper, and the wrapper is the only point of contact to the log4net functionality.
In the long run, it's probably worth investing in building your own logger. If you encapsulate log4net properly, you should be able to make this upgrade rather easily, without having to change your code.
Why not use Trace Listeners from the .NET framework? They provide many of the benefits of a logging network, without the need to incorporate an external framework.
Benefits include centralized log management and the ability to direct the output logs to one or more sources such as a console window, text file, or the Windows Event Log.
You should spend some time creating your own logger that does exactly what you want. This would be the best way. Is also fairly easy and you have full control on the customization so you can make the output look and feel as in log4net. You could Google for logging sample and start modifying that one.
I am not sure if I would use a log framework for this purpose. I have the impression that writing this text file in the exception case is part of your business process. Logging serves a different purpose that can be turned off without affecting business processes...
My solutions has several projects which includes several libraries and one project for UI. Currently it is a windows forms application and I use log4net for logging. This UI project has only reference to log4net and this project maintains the configuration files. But I would like to log from my libraries as well.
Usual method for doing this is to wrap the logging calls behind an interface. Create a common project something called utilities and add this interface to this project. Now this project can be used in all the projects and can use this interface for logging.
I am thinking about an alternative design which involves passing delegates and reducing coupling and avoiding unnecessary interfaces.
Consider following class is one from my library.
public sealed class Foo
{
Action<string> log;
Action<string, Exception> logException;
public Foo(Action<string> log, Action<string,Exception> logException)
{
this.log = log;
this.logException = logException;
}
public void Work()
{
WL("Starting work");
WL("Completed step1");
.........
}
void WL(string message)
{
if(log != null) log(message);
}
void WL(string message, Exception exception)
{
if(logException != null) logException(message, exception);
}
}
Now from the calling code, I can easily pass the logging method. Something like
Foo foo = new Foo(message => Console.WriteLine(message),
(message, exception) => Console.WriteLine("{0},{1}", message, exception));
foo.Work();
Used a console for explaining, in reality I will use the logging code here.
1 - Do you think this as a better solution? I think this is better as this is more loosely coupled.
2 - Is there any other better solutions available?
This is the only related question I have found here
Any thoughts...?
Don't use delegates if there are multiple signatures flying in close formation. All you're doing is avoiding defining classes and interfaces that would be meaningful. log4net provides an ILog interface which is an excellent example of a simple wrapper interface you can pass in.
If you're going to use a logging framework, especially log4net, don't wrap it and don't create a single global (static OR singleton) entry point. I've written about this before, and you may be interested in the question about best practices as well.
I have a thin layer that exposes a logging API very similar to Log4Net, that uses a provider-model design pattern to allow you to plug in any suitable logging framework. I've implemented providers for:
System.Diagnostics.Trace
log4net
EntLib
This means I can use logging throughout all my apps without any direct dependency on a specific logging framework, and users of my components can plug in their own favorite logging framework.
My advice is to add a reference to log4net to all your projects but leave the logger configuration in the UI project. This still leaves you with the flexibility to define different logging levels on a per assembly basis. Logging is such a low level activity and log4net is such a mature product that I wouldn't spend any time trying to come up with a clever solution just to satisfy "best practices". I might even argue, over a beer or two, that referencing log4net is no different than referencing System.Core.
Unless you have different pieces of code using different logging frameworks, I'd have a singleton LogDispatcher or something similar that all code which would try and log would call into, perhaps passing in a message level to determine the correct logging method. This prevents the delegates for logging from needing to be passed around the entire codebase, and centralizes all of the code which is responsible for the logging policy.
Another approach is to use a framework like Log4Net. Even if you don't end up using it, their design is a good one to base your own logging on.
Google for "AOP logging".
Here's some chat about this from Ayende.
Quoting Jon S. "Simple is almost always better than clever" - IMHO your use of delegates looks more of the latter.
If you want the library projects to log, they should setup-and-use their own logger. I'd not ask clients to pass in a logger (object or interface) - which then travels all the way deep down the type dependency graph. It just pollutes the interface a bit with unnecessary logger object/interface/delegate etc. parameters.
If you're using Log4XXX frameworks, I believe it emphasises the concept of "hierarchical logging architecture" (the names they come up with in s/w ;), where each type/class can maintain and write to its own log file. If the ctor of Foo creates a logger internally, I'd like that. And since it is configurable, specific clients may change the configuration files to redirect the output elsewhere too.
So your problem is one I will soon have to commit to a solution for. The defacto answer is "Use Injection" but in this case it's less inversion of control and more expansion of dependencies. I think your close, so here are my thoughts.
The Pros of your solution
There is no need for additional references by your class or the assembly it's in. Because your using Actions with common types, those references are likely already present.
The benefit of that is that is that 100% of the implementation of logging is left to the assembly that injects your actions. So if you add log4Net of nLog the only reference to it will be where it is implemented. So if you wanted switch later, only that assembly would have to be updated.
The converse of that is if you just inject a chosen logger into each class. That means you have to add a reference in every project to the logger. Even if the interfaces are named and implemented the same, you have to have the reference for it to resolve. In solutions where you have more than 3 projects that can be costly, and you have the same cost any time you would switch loggers.
Possible Improvement
In that lies the beauty of your solution. However it could be improved. I find that when injecting things of similar function or "aspect" it can make sense to put them into an object and inject that instead. You could create interface with both of your actions and inject concretes that implement whatever library you want. This would, again, leave the only reference to the logging library to one project/assembly with only the cost of having to add a reference to your interface to the rest.
Hope this helps and good luck.