Multiple logger instance for each application modules - c#

I started to create a log system based on Observable Pattern. For that I use Reactive Extensions.
I have an IObservable called ILogInfo and a IObserver called ILogObserver.
I have a main application with various modules that used shared libraries. Each module implements an observer of ILogInfo and the modules can work in parallel. My problem here, is that I would like to observe only the ILogInfo registered in the scope of my module.
In this scheme I have two modules (Module A and Module B), each module uses many libraries which push information via ILogInfo. When LibC push a new ILogInfo I would like that only the calling module catch (observe) the information. For example when the call comes from Module B, I don't the information to be observed by Module A. How could I do this ?

This isn't a question about Rx really. You need to be able to get calling context from the ILogInfo to route it appropriately.
You can provide either provide that context explicitly from the caller (the sender suggestion in the comments seems like a simple, workable suggestion of this) or do an expensive stackwalk to determine the calling module (which won't work in asynchronous situations) or otherwise you'll have to maintain the caller in ExecutionContext by setting data in the LogicalCallContext - this works in more asynchronous situations but is more complex.
I don't know about your specific situation, but given the need to isolate logging so throughly, I wonder if hosting multiple copies of the libraries in separate per-Module AppDomains might be easier, giving you complete isolation.
I hope there's a really good reason for this requirement, because it feels very complicated when existing logging frameworks have good solutions for providing context (like activity tracing in the logging application block and in WCF for example).

I agree with James here. This isn't really an Rx question.
I also have a question of how will you deal with logging where many modules reference the same library?
Is there a reason you are not considering a common Logging solution like Log4Net?

Related

Subscribe to whatever method is being executed

In my app I'm creating an auditing package that obtains various information, one such type of information should provide different information regarding what method is executed (time it took to execute, method name, method class, assembly, etc).
I'm not looking to use an existing package or framework, but to create my own.
I can imagine that this is a complicated thing to do, but I'm looking for some pointers to get me started .
One option you may be interested in is DI-level interception. Since container is responsible for your objects instantiation, sometimes it can be configured with proxy generators to enable call interception.
You can choose between Autofac, or Unity.
The most popular tasks to solve with this approach are cross-cutting concerns, like: logging, measurements, run-time application structure analysis. If you don't want to pollute your code base with repetitive diagnostic code, just delegate this task to an interceptor.
Similiar idea is AOP. I havn't seen popular AOP packages for a long time, and havn't used them, but it's worth to do a research on this topic too:
What is the best implementation for AOP in .Net?
DI Interception vs. AOP

Intercept ALL services

We have small lifetime scopes in our applications. It would be interesting to be able to intercept all services registered in autofac. By doing so we can see exactly which path the code takes for every lifetime scope and which method arguments are used. Not really usable for production but when really great for debugging/diagnostics/refactoring as you ge the whole picture and not just unit level.
But AFAIK it's only possible to register an interceptor for each single registration?
Nothing like this is supported out of the box with the Autofac.Extras.DynamicProxy2 library. You could potentially implement something like a module that handles OnActivating for every component using code similar to the stuff in Autofac.Extras.DynamicProxy2, but you'll run into trouble like...
Do you want class interceptors or interface interceptors? The type of service being resolved vs. the limit type of the component backing it will influence what kind of dynamic proxy you want to make. I believe the current A.E.D2 code only generates interception for either/or - not every interface a class implements, etc.
Do you use WCF client proxies? Client proxies are an interesting beast of their own so you have to special-case them. You'll see that in A.E.D2.
Generally problems like this get solved by aspect-oriented programming solutions (e.g., PostSharp) or profilers (e.g., ANTS)... or a combination of both. You might want to look into those solutions if you have the ability.
For an example of what sort of module implementation I'm talking about, check out the log4net integration page on the Autofac wiki. That shows how to handle OnPreparing for every component in the system. You can do the same thing, but handle OnActivating instead and use the sample on the Lifetime Events wiki page to show you how to swap one resolved thing for another (swap the real object for the generated proxy).

What are the guidelines for designing an application-wide logging system?

I'm learning about layered architecture at the moment and I'm wondering how to add a logging system to such a design.
Now let's say we have three layers:
Presentation Layer
Business Layer
Data Access Layer
And assume that only a higher level layer is aware of the layer one level below. For example, the Presentation Layer is aware of the Business Layer but not the other way around.
Where should you implement a general logger class?
If I implement it in a different project, it means all the layers have a dependency on a common assembly, which may or may not be good. Though this can be overcome with dependency injection.
If I implement it in the highest level (in our case the Presentation Layer), it will defy the Single Responsibility Principle.
What is a good place to implement a logging mechanism?
And after implementing it, what is a way to use such a system?
It should ideally be able to catch uncaught exceptions and save the exception description somewhere.
Where should you catch exceptions? Should they be caught in the highest layer (the Presentation Layer)? Or should they be caught somewhere else?
And what is the way to use to pass a logger to a class? Does it make sense to add a method/constructor overload to everything in the project that accepts an interface like ILogger?
As you can see I'm pretty confused about the subject, and in my current job there's no one that has any knowledge about enterprise application design / layered design, even though they are designing enterprise applications. So any help showing me the right direction will be appreciated.
Logging is a cross-cutting concern. This means that it encompasses all layers of your architecture, and it makes sense to implement it as a separate library. However, this would only make sense as an exercise, since there are already very good solutions like Log4Net, NLog, and even .NET's own TraceSources.
I tend to prefer those which support hierarchical logging (e.g. log4net). This make it much easier to configure the desired tracing level in production systems. E.g. you could set general tracing level for MyApp.SomeNamespace to Warning, but also have set a specific type like MyApp.SomeNamespace.AnInterestingClass to Debug.
I am not sure I understood the "what is a way to use such a system" part.
You use logging everywhere it is needed, in all layers of your app, in each method which needs it. I am under impression that you have an idea of centralized place where all errors are handled and logged, but these are separate things.
It should ideally be able to catch uncaught exceptions and save the
exception description somewhere.
No, it shouldn't. Loggers write stuff to logs, they don't handle exceptions. Logging is not used only for reporting errors. You also want to log the execution of your application and many internal information (but with varying tracing levels), for the sake of troubleshooting the system in production or post mortem analysis.
Where should you catch exceptions?
At all levels. Many methods in your code will be handling the exceptions relevant to current context. I suppose that you really want to know where to handle the exceptions which were not caught elsewhere - some kind of catch-all handler. For this, often it makes sense to do it in the topmost layer, i.e. in your .exe or, more generally, in the layer which contains the types which represent the application itself. There are many ways to do it - from simply registering the handlers for the unhandled exceptions (ThreadException/UnhandledException) to HandleError/Application_Error in ASP.NET MVC to using something like exception handling application block, which I personally dislike (as most of Enterprise Library).
And what is the way to use to pass a logger to a class? Does it make sense to add a method/constructor overload to everything in the project that accepts an interface like ILogger?
It depends on your implementation. It seems that you want to go down the dependency injection path. Since logger is not an essential dependency (i.e. it is not related to functional behavior of types, but to the implementation), I would prefer to handle it via property injection as an optional dependency, instead of doing it via constructor which, IMO, should be used only for primary dependencies - those which are required for the type to function properly.
However, you might not want to use DI. Then you need some other way to get to logger. One option is discussed here.

How do I make a class library that works in ASP.NET and non-ASP.NET applications?

I want to write a class library that works in ASP.NET and standalone applications. Some differences in behavior are needed when running under ASP.NET. What is the recommended way to check if the library is running in an ASP.NET application?
I can check HttpContext.Current, as it appears to reliably return null when not running under ASP.NET. However, when running on a background thread in ASP.NET, it also returns null.
Any opinions on HttpContext.Current or other solutions?
ADDED: Thanks for all the advice on how to achieve a separation of concerns. However, I would like to add that this library will not be for general-purpose use, so for my particular case I do not need a lot of flexibility. In my mind, the best so far (not mentioned in this thread) is to check the HttpRuntime.AppDomainAppId static for null as it seems to work okay even for ASP.NET background threads. However, the various solutions contributed here will surely be helpful to others with more general needs.
I would push all the code common to both ASP.NET and desktop applications into a core library and test this, then create libraries that sit above the core application to provide deployment specifics - your HttpContext calls for example. You can then test reliably in both scenarios, knowing you only have to test the core application block once.
With regards checking HttpContext from a background thread - this doesn't make sense and will always return null because HttpContext is defined by the asp.net request processor. If your code starts a background thread, HttpContext will be null in the new thread. Sorry about that :)
As a work around you could try adding each new session to a global collection
and then call into the collection from the background thread. You'd need to be careful about synchronising access to your session collection though..
I think it's pretty common to separate your UI code from your application logic.
I would put all of your application logic into the shared library. Raise events from the library as appropriate. You can then handle those events in whatever app you'd like Asp.Net, WPF, etc.
If your applications needs things that might be in HttpContext, like session, you should pass those variables in as arguments to your methods so the library does not rely on HttpContext.
One approach you could take is to factor out the behaviors that vary between Web and non-Web applications into classes with a common interface (i.e. IPlatform), then use an IOC container or dependency injection to configure your application to use the proper IPlatform implementation. However, this could be over-engineering, depending on your needs. You may want to add to your question the specific behavior you want to vary among platforms.
Why not, instead, have a public property that the calling code can set to tell instances of your class whether they should use the logic they intended for ASP.NET?
Accessing HttpContext when you don't really need it, along with not working right in all cases (as you've discovered), is giving that class too much reach back into its environment. Let it simply perform its job, and let the calling code tell it which set of logic to use.

Using delegates or interfaces to decouple the logging - Best practices - C#

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.

Categories