Is passive logging possible in .NET? - c#

I'm frequently frustrated by the amount of logging I have to include in my code and it leads me to wonder if there's a better way of doing things.
I don't know if this has been done or if someone has come up with a better idea but I was wondering is there a way anyone knows of to "inject" a logger into an application such that it passively monitors the thread and quietly logs processes as they occur without having to do things like:
public void MyProcess(int a, string b, object c)
{
log(
String.Format(
"Entering process MyProcess with arguments: [a] = [{0}]; [b] = [{1}]; [c] = [{2}]",
a.ToString(),
b,
c.ToString()
);
try
{
int d = DoStuff(a)
log(
String.Format(
"DoStuff({0}) returned value {1}",
a.ToString(),
d.ToString()
)
);
}
catch (Exception ex)
{
log(
String.Format("An exception occurred during process DoStuff({0})\nException:\n{1}",
a.ToString(),
ex.ToString())
)
}
}
What would be great is if I could say to my logger:
Monitor(MyClass.MyMethod)
It would then monitor everything that goes on inside of that method including passed in arguments along with method calls and values passed into those methods, exceptions that occur etc.
Has anyone implemented something like this in the past? Could it even be implemented? Is logging in this fashion just a pipe dream?
I'd love to design something that would do this, but I just don't even know where I'd begin. Of course, I don't want to reinvent the wheel either, if it's already been done, it would be great if someone could point me in the right direction.
Any suggestions would be gratefully received...
Edit: I thought I'd comment on an answer which queried as to the level of detail required in the log. It is frequently required that configurable levels of logging be provided such that if the configuration specifies detailed logging then everything is logged, whereas if critical logging is configured then only certain information is logged along with exceptions. If fatal logging is configured then only information which causes the application to die would be logged. Would something like this be configurable or would AOP require 3 or 4 different builds depending on the number of logging levels?
I frequently use 4 levels: Fatal, Critical, Information, Detailed

You can use PostSharp to log "around" the method. This is exactly the kind of thing AOP is good at. You might want to start with Log4PostSharp - a plugin specifically for logging.

This is the classic example from Aspect Oriented Programming. See PostSharp for a very good CLR-based library.

This is one of the textbook (not sure which textbook has AoP in it but you get the idea) examples of AoP - logging : where you want to stick something before and after a method.
You might want to explore the AoP route, PostSharp is one of the popular ones, along with Microsoft Unity (IoC too), Castle.
One simplistic example of AoP is you add your code before and after methods, instead of adding the method calls inside the actual methods. As you've tagged the question with C# you might want to just look into making an extension method to log it, which is already in this question.
I would take a practical approach: how much actual logging are you doing? Can you get away with just an extension method instead of razzle-dazzle'ing the person reading your code. The logging built into the .NET framework is decent already.

In addition to the logging methods mentioned by Jon, its probably also worth noting another useful feature in VS for tracing program flow, and that is the ability to have non-breaking breakpoints that will simply output a message or run a macro when hit (note you can print variable values as well)
Right click on your breakpoint and choose the When Hit... context menu item.
And of course one other very useful feature is the Trace object and Trace Listners in System.Diagnostics.

I've written a logging library recently that uses the IDisposable interface to wrap regions with logging context. Basically, there's a LogSite disposable object that you use like this:
using(var logger = new LogSite("methodName", new object[] { p1, p2, p3 })
{
// code that does stuff goes here
}
The LogSite object has a bunch of convenient overloads for the constructor such as MethodBase so you can just use MethodBase.GetCurrentMethod() and use reflection to get the actual name of the method and parameters (instead of a hard-coded strings).
The way it works is this -- In the constructor, it writes to the log with all the trace information to indicate it entered the block. In the Dispose method, it writes an exit entry.
While disposing, it also checks Marshal.GetExceptionCode() for a non-zero value to see if the code inside the using threw an exception or exited normally. It doesn't give you the exception, so that will have to be logged explicitly in the catch handler, but it does indicate "pass/fail" for that region. This allows your logging scope to be more specific than just the method, since you could have lots of these blocks in a single method, and know which one threw the exception exactly.
Also, since there's a "logger" object now available, your catch handler just looks like:
try { ... }
catch (Exception ex)
{
logger.LogException(ex);
}
The logger already knows the method name, parameter information, and all that, and has internal methods for formating the exception information.
Getting into the architecture below this high-level object, there's a concept of "LogDisposition" which handles the "pass/fail" we determined earlier, and there's a concept of "LogEntryType" which is a filter (implemented with Flags enum) that indicates what kind of log entry is being passed (Error, Trace, etc).
The thing that actually does the logging is just a publisher/listener pattern. The publisher takes the passed in log entry, and much like a multi-cast delegate, keeps a registry of LogListener instances (should be setup at the start of program, or added in dynamically as needed), and passes the log entry to those instances.
The LogListeners in turn, filter out what kind of log entries they care about.. So if you don't want the method entry and exit points for non-error conditions, they don't have to show up in the log. This can be controlled at run-time to allow the user to do things like turn on and off detailed logging at will. Since the publisher can write to a variety of loglisteners, you can hook up something that writes to a file, or writes to the database, or displays error notifications in the GUI... etc.
It's a pretty good system, and requires a relatively small amount of coding to get relatively rich logging.
I could give you a code sample if you wanted... You can contact me through my (nearly completely inactive) blog (see my account profile).
Hope that helps.

I use the opensource Apache log4net in all of my projects. It's a very simple implementation with all kinds of extensions that allow you to log to databases, zip files, rolling log files, RRS feeds, telnet clients, etc. Logging is basically as simple as:
'Will print stack trace after message'
log.err(ex.message,ex)
log.warn("warn")
log.info("info")
log.debug("debug")
Logging parameters such as the output format and log level to output are all read real time while your app is in runtime.

Related

Contract.Ensures and Exception Handling

I recently discovered the .NET Contracts API, and, although I don't like the way of implementation using methods and not an extended syntax (Sing# did it right, in my opinion), I prefer using them over the old / regular way using if's for e.g. null-checking.
I'm also approaching my first Contract.Ensures-calls and I stumbled over the question how we would deal with Exceptions in a method containing a Contract.Ensures that suffered from an exception while running?
The word Contract.Ensures kinda feels like I have to handle the exceptions inside the method and get my class into correct state again, but what if I couldn't?
Let's say we have this class here:
public class PluginManager
{
private ILoadedFromAtCompileTimeUnknownAssembly extension;
public bool IsFinished { get; private set; }
public void Finish()
{
extension.Finish();
this.IsFinished = true;
}
}
can we use Contract.Ensures to ensure IsFinished is true after the method completed?
Yes. Ensures basically means "Ensures if the method terminates normally", i.e. without exceptions.
I find it very hard to get the concept of code contracts right. Code Contracts are meant to find programming errors. If applied that way you can remove the contracts of your release build and your application will continue to work perfectly.
BUT it is very hard to distinguish programming (aka logic errors) from configuration and input data issues. These checks must remain in your release builds. It is therefore a bad idea to use Code Contracts to check if an extension/plugin did correctly load because it is usually configured into your application. If you remove the contracts in your release build you get differerent behaviour of your application depending if you configure your app wrong in debug or release builds.
Contract violations are reported with only one exception type which makes it impossible to react in upper layers of your application to e.g. a configuration issue or a logic bug in your application. With react I do not mean to continue but to present a remotely useful message to the user/developer what went wrong.
Code Contract do look nice at the surface but I fear that most people use it in the wrong way. It is not meant to replace all of your null checks for input validation in your methods. You should replace only from the methods the null checks with code contracts where your are sure that a logic problem an not the input data is the root cause.
If you expect a file name in your e.g. console application as input and the the user did forget to supply the file name at the command line it is not a good idea to the greet the user with a ContracException.
The error message would be confusing to the user.
You cannot differentate programming errors from user input validation issues.
You cannot catch any specific ContractException because the exception type is internal.
See user documentation.
7.6 ContractException The ContractException type is not a public type and is emitted as a nested private type into each assembly for which
runtime contract checking is enabled. It is thus not possible to write
catch handlers catching only ContractException . Contract exceptions
can thus only be handled as part of a general exception backstop. The
rationale for this design is that programs should not contain control
logic that depends on contract failures, just like programs should not
catch ArgumentNullException or similar validation exceptions.

Handling (possibly-changing) error codes of a library using exceptions

Let's say you are using a library that returns error codes. You'd like to write a wrapper for the library, and you'd like to handle errors with exceptions in the code.
If the library is still in development by someone else, and if the error codes may change (there can be new ones, there can be deprecated ones, or some error codes may change meaning slightly), what would your solution be to handle this?
This is the situation that I'm in right now. In my case, the library is written in C++, and we're using C#. The coder of the library says the error codes may change, and I have to find a way to work with it.
Our initial solution is to:
Create an XML file that has the error codes in different categories (terminal ones, input errors, and so on).
Wrapper fetches these error codes on start.
Throws the appropriate exception by checking the category of the error code.
So let's say a method returns error code 100, then the wrapper checks the category of the error code. If it is a terminal error it throws a terminal error exception, if it is a user input error it throws a user input error exception.
This should work, but I feel like this is not the optimal solution. I'd like to know how good written enterprise software handle change of error codes.
What would you suggest doing?
Edit: I have already questioned the fact that error codes will be changing and the coder of the library says the code is in development. It's an algorithm, so even the way the algorithm works changes as it's original research (he's writing his PhD on that). So he says there may be different errors, or some may be irrelevant in the future.
The data-driven approach you're taking, using the XML file, seems like a good one, given the circumstances. However I'd question why the error codes are changing at all - this suggests that no proper design has been carried out for the library being developed. It ought to have a well-defined structure for its error codes, rather than requiring you to keep changing your interpretation of them.
You may want to try having an overall "library exception" exception class, and subclassing it for each different type of exception you want to throw based on the "type" of the library error. At least that way, you can catch all library errors, even if one of the specific types of exception slips through the net. ie. you'd catch something like LibraryException after trying to catch TerminalErrorException.
I guess you will solve this problem easier if you change your vision of the situation a little bit:
You are dealing with the framework, let's call that an external
framework.
On the other hand, you are writing a wrapper for the
framework - internal framework.
Your code (client application) uses internal framework, assuming that it provides the functionality used for the problem domain. As I understand, and as I believe, client application should not have any idea about the external framework.
Now, the question comes down to the following one: is the internal framework's functionality clearly outlined and finalized? or is that changing too?
If it's changing (possibly because of the external framework), then the internal framework is under the development. This means, client application needs to wait until internal framework is ready to announce a first version ready (possibly after the external framework is complete).
Now error handling:
Errors in the application serve like contracts. Caller of the function expects particular exceptional situations, and particular kinds of errors only. Each possible error is predefined and documented by each function, similar to its input parameters and return values.
What it means for you:
Define the final design of the internal framework (the sooner the better).
Decide what kinds of errors each function of the internal framework can throw.
Use internal framework from your client application and expect only expected and documented exceptions. Don't try/catch anything that is not expected from the internal framework. Basically, follow the contract.
If error code changes, that does not change the concept of the function in the internal framework. It still needs to throw the same kind of error it threw before (according to the contract). The only part that needs to be changed is, how to translate the new code to one of the expected (contracted) errors. You can solve it any way that works better.
Why is the last assumption fine? because we said the internal application's design is final and is not going to change. Error contracts are part of the final design too.
Example:
//external.
int Say(char* message);
//internal.
///<summary>
/// can throw (CONTRACT): WrongMessageException, SessionTimeOutException
void Say(string message) {
int errorCode = External.Say(message);
//translate error code to either WrongMessageException or to SessionTimeOutException.
}
Cannot translate? something is wrong either with current contracted errors or the external framework: maybe you should terminate the process? something went wrong, unexpected!!!
//client.
...
try {
Internal.Say("Hello");
}
catch (WrongMessageException wme) {
//deal with wrong message situation.
}
catch (SessionTimeOutException stoe) {
//deal with session timeout situation.
}
Let me know if anything raises the question.
Translating error codes to Exceptions:
This obviously is some kind of categorizing for each error code. Category can be each destination exception, and exceptions can be categorized by functions. This is exactly what the error contract means: categorize Exceptions by functions; and categorize error codes by exceptions.
Below is a pseudo configuration for this. Take this as an initial idea of how to categorize:
category Say [can throw]: { WrongMessageException, SessionTimeOutException }
category WrongMessageException [by error code]: { 100, 101 }
category SessionTimeOutException [by error code]: { 102, 103, 104 }
Of course you don't need to write a parser for such kind of impressions (this was human readable pseudo configuration). You can store similar sentences using XML or any kind of source, which will help you configure error translation rules and function contracts.
Reference
Book: Jeffrey Richter - CLR via C#, 3rd edition. Chapter 20 - Exceptions and State Management. Sub-Chapter - Guidelines and Best Practices. Sub-Sub-Chapter - Hiding an Implementation Detail to Maintain a "Contract".
This chapter will describe exceptions as contracts and will explain how to categorize contracts thrown by the function. This can confirm the correctness and the credibility of the explanations provided here.
What about this:
You said you have stored Error categories some where (DB or XML file)
lets amuse we have some master detail tables called ErrorCategory(Master) and ErrorDetail(Detail)
I will recommand adding a column (property) to your Errorcategory Table
Called CustomExceptionType, it will be a text property containing full name of assembly and class name of specified exception (ex: CustomExceptions,CustomExceptions.TerminalError )
We will need a base class 4 all of our custom exceptions, lets call it BaseCustomException calss
We will need an ExceptionFactory Class lets call it CustomExceptionFactory class
Our ExceptionFactory will have a method called CreateException, something like this
Public BaseCustomException CreateException(EceptinCategory category, ExceptionDetail detail)
{
var customException = Activator.CreateInstance(category.CustomExceptionType) as BaseCustomException;
customException.SetDetails(detail);
return customException;
}
so in run time our CustomExceptionFactory object will use CustomExceptionType to create a an instance of specific exception using Reflection.
I prefer CustomExceptionFactory & BaseCustomException to be implemented in a assembley
and all derived CustomExceptions be implemented in another assembly so our main application will be non related to CustomExceptions.Dll
In futur by changing of C++ factory, our main application will not need rebuilding and all we need is change in data of tables and impementaion in CustomExceptions.Dll.
(same solution could be implemnted using XML or Configuration file or ...)
Hop this will help.
OK, if you want to be flexible and not to depend on the code I think using reflection to generate custom class when you first run the application would be the best. Here is the rough explanation. If you like it I can explain it further.
The provider of the C++ code should create a class that will hold all error codes - for example public class Errors{public static readonly IOError = 100}.
When you start your application you will check this class for modification and if it is modified you will generate exception class for each error code.
In the above example it you will generate class IoException that inherit Exception .net class.
After that you can use it in the wrapper and catch each exception individually.
Another possible solution is to amend the xml that you are mentioned - for each error code add exception class - using the example the for error code 100 you will have IoException class. after that you need to implement this class and use it...
Better to depreciate old codes and leave their designations reserved than to have your code designations constantly changing. Since your author doesn't seem interested in design, have him report warnings and errors on the stderr stream that you can retrieve.
In addition, it seems simple enough to construct a CSV or XML with code-string pairs that the algorithm writer is free to edit as he sees fit. Reserve certain ranges of code number for different types of errors (1000s for input errors, 2000s for terminal errors, etc) have your wrapper interpret the return code using the code-string pair he wrote.
Then throw your exception based on the type of error, determined by the number range.

Possible to force a developer to handle specific exceptions?

Essentially, I'd like a special form of an Interface for Exceptions that requires anyone who uses my object to wrap it with specific catch implementations.
Example
I have an object that sends data to another host. I expect that the realistic implementations will require a way to handle the following exceptions:
HostNotFoundException
InvalidUsernameException
AccountExpiredException
DataAlreadyExistsException
Similar to how an Interface or an Abstract class is used to force the creation of methods and properties in derived classes, is there any way I can force a consumer to implement exception handling the way I expect?
On a similar note, I'd also like to force methods (created via Interface or Abstract) to be able to generate certain exceptions. Sure they may be NotImplemented, but I want to tell that developer (who doesn't read documentation) that they should be considered.
Goal
The benefit of this exception checking is to enable more robust error handling. This would be accomplished by the consumer using the object, and the object creator.
Solution?
The only approach I can think of is T4 templates, but that isn't as complete of a solution as I would like. I'd love to see this implemented in the language itself.
You can't force a programmer to do anything except jump through hoops. For example, let's say you have some method called Frob that does something, and can throw FrobinatorException. You expect programmers to write:
try
{
var result = Frob(foo);
}
catch (FrobinatorException)
{
// handle exception here
}
But you find that they don't. So force them to by defining Frob like this:
public FrobResult Frob(FrobyThing foo, Action FrobinatorExceptionHandler);
And then programmers have to write something like:
var result = Frob(
foo,
() => { /* handle FrobinatorException here */; });
Programmers will grumble about having to do that and they'll end up writing this:
var StupidExceptionHandler = new Action(() => {});
var result = Frob(foo, StupidExceptionHandler);
And now you're worse off than you were because the exceptions are being swallowed, which hides bugs. It's better if the programmer just ignores the exception handling altogether. At least that way you know when an error occurs.
There's simply no way to force good exception handling. At least, not in C# as it currently exists. You can make it more convenient to handle exceptions, but doing so often makes it easier to hide exceptions by swallowing them.
If I'm reading your question correctly, it sounds like you're kind of looking for checked exceptions. There's an interesting article from much earlier in the development of C# that discusses this, actually.
From a design perspective, I don't really see how you could "force" the consumer of an interface to handle your exceptions. After all, how would you know it's being handled? Does the method which calls your interface need to wrap that call in a try/catch directly? Or would it be sufficient for the method which calls that method to do so? Or for a global exception handler for the application to do so? It should really be up to the consumer of the interface to determine how/when/where to handle exceptions.
The best approach you can take is to document the potential exceptions in the intellisense comments on the interface. But this brings up an interesting problem which you also mention (if I'm reading you correctly). The problem here is that the documentation is on the interface, not on the implementation. What if one or more implementations throw different exceptions than those which are expected by the interface?
In general, I think the balance to be reached here is still to document potential exceptions on the interface. The four examples you give sound like safe assumptions for an interface to make about its implementations. But that depends on what the interface method is accepting as arguments.
For example, if the whole concept of a "host" or a "username" is entirely encapsulated within the implementation (such as hitting a web service from within some kind of service interface, which could just as easily hit a database or some other source of record in other/later implementations) then exceptions about those pieces of data wouldn't make sense at the interface level. It would be better in that case to create an exception type like "DomainException" or "ImplementationException" or "DataRetrievalException" or something like that and just putting the internal implementation details inside of the exception.
To get back to the main point, however... From the perspective of your interfaces and your objects, you shouldn't be concerned with how exceptions are handled by consumers. All you should do is internally handle any exceptions that make sense to internally handle and throw exceptions that make sense to throw. Anything beyond that creates coupling between the consumer and the component.
Although I partly sympathies with your goal of better error handling, I feel that if you forced consumers of your code to handle exceptions correctly then your colleagues would murder you within 20 minutes of checking it in.
Due to C#'s lack of checked exception you're reduced to documenting your code so consumers know what to expect and under what conditions to expect them.
On a side note there is a great plugin for ReSharper called Exceptional that will identify places in your code where you have either not handled a possible exception, or not documented it so callers may do so instead.

Best practices when reporting exception messages to the user

In my ASP.NET MVC application, I do not want to report all exception messages to the user. But there are certain types of exceptions that I'd like to report to the user, so I created an action filter to decide if it's this particular type of exception, and if so then display the exception's message, otherwise display a generic message. So I created a custom exception called ClientException.
My filter looks something like this:
if (filterContext.Exception is ClientException)
message = filterContext.Exception.Message.Replace("\r", " ").Replace("\n", " ");
else
message = "An error occured while attemting to perform the last action. Sorry for the inconvenience.";
filterContext.HttpContext.Response.Status = "500 " + message;
I read this http://blogs.msdn.com/b/kcwalina/archive/2007/01/30/exceptionhierarchies.aspx where the author recommends using existing .NET exception types to report usage errors. However, by introducing my custom exception, I just have to do a single check in my filter. Is my approach okay?
I like this approach for a couple of reasons.
First, it fails safely. If someone doesn't explicity throw a ClientException, then the exception details are not reported. Forgetting to display something is a lesser problem than accidently displaying something.
Secondly, it allows the decision about whether to display the exception to be made at the proper place. Not all IOExceptions are displayed, for example. Some may be, and others wont be. The specific exceptions can be caught and transformed anywhere in the call stack, so that tranformation can be made at a place where it is known to be correct.
Both of those things together mean that a future developer will not innappropriately change a whole class of exception to be displayed, or think that something won't be displayed when it actually will be.
Also, the purpose of the using a particular exception type is to determine later what action to take in response to that exception. "Display this message to the user" is a perfectly good action to specify. Once that decision has been made, then the exact nature of the exception is completely irrelivant. (The original problem may be put in the InnerException property, for logging purposes, of course.)
So, in my opinion, this is a good design.
Your approach is fine IMO but there are alternatives. (We're software developers so there are always alternatives.)
You could harness the Exception Data dictionary to store a flag indicating whether or not an exception is a client exception. Then you could have your filter check for the existence of the flag.
If your approach works for you then it is fine. And are you surprised that a Microsoft blog is recommending that you use their Exception class? ;)
There are some .NET library features and 3rd party OSS stuff that will only work with .NET exceptions however.
To get the best of both worlds you could always extend the .NET Exception object into your own.
I would use different Threshold values based on the type of exceptions, and these Threshold values would be associated with the exception messages.
Based on the particular Threshold value logic you may want to decide whether or not to show exception.
My concerns with this solution is that very likely these exceptions will typically be thrown by objects in a business layer (or model objects in MVC terminology). The usage you describe is really what I would consider to be a presentation concern.
Typically you'd need to rethrow whatever exception you have in your model, only to communicate whether or not the exception can be exposed to the user or not.
What do you expect the user to do with the information? If the user can fix the situation perhaps there should not be an exception to signal the state to begin with?
I would stick to catching specific exceptions per case and do presentation decisions at the spot. You may send out an exception, as caught, used as model to a view though. I would still let the controller decide, not whomever throws the exception.

Using the StackTrace Class in a production environment to get calling method info

We have a "log" class which uses Relection.MethodBase to send current class info to the log.
The reflection.MethodBase stuff happens in the class itself.
However, I'd like to move that stuff to a single external "log" singleton type class.
In this scenario the external log class needs to get the CALLING info, not the current method info. I'm using stacktrace to do this, which isn't in the Reflection namespace.
Can I guarantee that "that" specific information (calling method) will be there in a production environment?
var stackTrace = new StackTrace();
return LogManager.GetLogger(stackTrace.GetFrame(1).GetMethod().DeclaringType);
cheers!
Yes, even in a "release" build without any PDB's you will have the method names in a stack trace. But personally I would consider this a code smell. It implies a very fragile code path (for example what happens if you make a WriteLine method that calls a Write method, do you look at the caller's caller in that case?). It also is probably not cheap to take a snapshot of the stack trace on every logging call.
I recently posted a question about using MEF to inject a logger into my class and I wanted to associate a type name with the log data as well. MEF worked out pretty well for me as I was able to import an ILogger instance for each class that wanted to use it and when the ILogger instance was imported, I would set its Category property to the name of the current class. No reflection, no stack trace. It worked pretty nicely for me.
Josh has it right. Taking stack traces is very expensive and should be avoided. It's a bit hard to understand exactly what you are doing, but it sounds rather bad. My first suggest would be to take another look at your production environment and see what logging services are already in place and how you can use them.
If you cannot, then I'd be looking into already available APIs such as Log4j, SLF4j and Commons logging to see how you could utilise them. Finally, if still not useable, you can at least look at their source to see how they do things. Also the source for JUnit does stack trace analysis if I remember correctly so there's another source of ideas.
But my last word would be to keep things as simple as possible. Don't go around creating stack traces. Generally speaking you are really only concerned about them when an exception happens and then it is handed to you. You don't need to do anything except pass it along.

Categories