Generic logging of function parameters in exception handling - c#

A lot of my C# code follows this pattern:
void foo(string param1, string param2, string param3)
{
try
{
// do something...
}
catch(Exception ex)
{
LogError(String.Format("Error in foo(param1={0}, param2={1}, param3={2}), exception={3}", param1, param2, param3, ex.Message));
}
}
Is there a way in .NET to get a Key/Value list of the parameters to a function so that I can call another function to construct my error logging string?
OR
Do you have a more generic / better way of doing this?

You could use Reflection and the convention that you must pass the parameters to the LogError with the right order:
private static void MyMethod(string s, int x, int y)
{
try
{
throw new NotImplementedException();
}
catch (Exception ex)
{
LogError(MethodBase.GetCurrentMethod(), ex, s, x, y);
}
}
private static void LogError(MethodBase method, Exception ex, params object[] values)
{
ParameterInfo[] parms = method.GetParameters();
object[] namevalues = new object[2 * parms.Length];
string msg = "Error in " + method.Name + "(";
for (int i = 0, j = 0; i < parms.Length; i++, j += 2)
{
msg += "{" + j + "}={" + (j + 1) + "}, ";
namevalues[j] = parms[i].Name;
if (i < values.Length) namevalues[j + 1] = values[i];
}
msg += "exception=" + ex.Message + ")";
Console.WriteLine(string.Format(msg, namevalues));
}

You could use aspect oriented programming with PostSharp (have a look at http://www.postsharp.org, and the tutorial at http://www.codeproject.com/KB/cs/ps-custom-attributes-1.aspx). Basically you could do something like this:
public class LogExceptionAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionEventArgs eventArgs)
{
log.error("Exception occurred in method {0}", eventArgs);
}
}
[LoggingOnExceptionAspect]
public foo(int number, string word, Person customer)
{
// ... something here throws an exception
}
Perhaps not quite what you want, but I'm sure it can be adapted to suit your needs.

No there isn't a way to do this.
The normal practice is to not catch exceptions unless you can handle them.
I.e. you would normally only catch exceptions and log them in a top-level exception handler. You will then get a stack trace, but won't of course get details of all the parameters of all method calls in the stack.
Obviously when debugging you want as much detail as possible. Other ways to achieve this are:
Use Debug.Assert statements liberally to test assumptions you are making.
Instrument your application with logging that can be activate selectively. I use Log4Net, but there are also other alternatives, including using the System.Diagnostics.Trace class.
In any case, if you do catch exceptions only to log them (I'd do this at a tier boundary in an n-tier application, so that exceptions are logged on the server), then you should always rethrow them:
try
{
...
}
catch(Exception ex)
{
log(ex);
throw;
}

When I have done this I just created a generic dictionary for the logging.
I have this LogArgs class. And logging in a base class that I call when I have an exception.
public class LogArgs
{
public string MethodName { get; set; }
public string ClassName { get; set; }
public Dictionary<string, object> Paramters { get; set; }
public LogArgs()
{
this.Paramters = new Dictionary<string, object>();
}
}
Then at the start of every method I do
LogArgs args = new LogArgs { ClassName = "ClassName", MethodName = "MethodName" };
args.Paramters.Add("Param1", param1);
args.Paramters.Add("Param2", param2);
args.Paramters.Add("Param3", param3);
base.Logger.MethodStartLog(args);
When I have an error I log it this way.
base.Logger.LogError(args, ex);

You could use a similar style of constructing the message, but add the params keyword in your LogError method to handle the arguments. For example:
public void LogError(string message, params object[] parameters)
{
if (parameters.Length > 0)
LogError(string.Format(message, parameters));
else
LogError(message);
}

This is little dated post but just in case someone comes across this like I did - I solved this issue by using PostSharp.
It's not practically free though. The Express license (downloadable via NuGet in VS) allows you to decorate your method with [Log] attribute and then choose your already configured mechanism for logging, like log4net nLog etc. Now you will start seeing Debug level entries in your log giving parameter details.
With express license I could only decorate a maximum of 50 methods in my project. If it fits your needs you're good to go!

Late to the party but I did something along these lines a year or so ago:
Github Repo
The idea of this setup is much like what your after, but with the ability to hook it up globally, there is more code than I would like there but it works and once plugged in, works for what your after.
If you take a quick look at the ProxyLogger.cs, consider this a wrapper, it will encapsulate any method it is given and execute it while handling the logging of the error as set here. This can then be setup with dependency injection for anything and everything you wish to log, e.g.:
public void ConfigureServices(HostBuilderContext hostBuilder, IServiceCollection services)
{
services.AddOptions();
services.AddSingleton<IHostedService, HostedService>();
services.AddSingleton<IMyClass, MyClass>();
// Logging added for both the hosted service and the example class
services.Decorate<IMyClass, ProxyLogger<IMyClass>>();
services.Decorate<IHostedService, ProxyLogger<IHostedService>>();
}
You register your services as normal, but on top of that, you can decorate them with the proxy logger to handle the execution and log the details before, after, on failure etc, with FULL params.
I was obsessed with this for a while and this is as best as I could get it, but it works really well.

There are scenarios of a few parameters or Large number of parameters...
Few parameters, without much ado, better write them as part of the logging/exception message.
In large parameters, a multi-layer application would be using ENTITIES ( like customer, CustomerOrder...) to transfer data between layers. These entities should implement
override ToString() methods of class Object, there by,
Logmessage(" method started " + paramObj.ToString()) would give the list of data in the object..
Any opinions? :)
thanks

Related

Can a method within a class inherit a subroutine that executes at the start and end of the method?

I have a logger that I am adding to my project. Right now for every method I'm going to have to write Logger.DebugLog("Starting Method") at the start of each method and Logger.DebugLog("Completed Method")
this logger - when Debug enabled - allows me to track exactly what methods were called on this run so that if there is an issue I can see how far it got before breaking making it easy to debug. Assume that the method name and line are being captured - my goal here is I do not want to add those two lines on every one of the +100 public or private methods
namespace myProject
{
public class myClass
{
public bool MyPublicMethod(string Message = "someRandomMessage")
{
try
{
myPrivateMethod(1);
writeToLog(Message);
return true;
}
catch(){
return false;
}
}
private bool myPrivateMethod(int passedNumber)
{
try
{
writeToLog(passedNumber);
return true;
}
catch(){
return false;
}
}
}
}
my log file should look like this:
04:00:00 - Starting Method:MyPublicMethod
04:00:00 - Starting Method:myPrivateMethod
04:00:01 - 1
04:00:01 - Completed Method:myPrivateMethod
04:00:02 - someRandomMessage
04:00:02 - Completed Method:MyPublicMethod
What I am forced to do now which looks cluttered is:
namespace myProject
{
public class myClass
{
public bool MyPublicMethod(string Message = "someRandomMessage")
{
try
{
writeToLog("Starting Method");
myPrivateMethod(1);
writeToLog(Message);
writeToLog("Completed Method");
return true;
}
catch(){
return false;
}
}
private bool myPrivateMethod(int passedNumber)
{
try
{
writeToLog("Starting Method");
writeToLog(passedNumber);
writeToLog("Completed Method");
return true;
}
catch(){
return false;
}
}
}
}
is this even possible in .NET or do I have to explicitly list that logging method if I want to use it?
4/6/18 Edit: It is possible - see AOP. Heres a pretty decent article on it http://www.dotnetcurry.com/patterns-practices/1305/aspect-oriented-programming-aop-csharp-using-solid
Here is a good summary of exactly what I was looking for:
Consider the following code:
public class DocumentSource : IDocumentSource
{
//..
public Document[] GetDocuments(string format)
{
try
{
using (var context = CreateEFContext())
{
var documents =
context
.Documents
.Where(c => c.Name.EndsWith("." + format))
.ToArray();
logger.LogSuccess(
"Obtained " + documents.Length + " documents of type " + format +
Environment.NewLine +
"Connection String: " + connectionString);
return documents;
}
}
catch (Exception ex)
{
logger.LogError(
"Error obtaining documents of type " + format +
Environment.NewLine +
"Connection String: " + connectionString, ex);
throw;
}
}
//..
}
Here is how the method would look like without logging:
public Document[] GetDocuments(string format)
{
using (var context = CreateEFContext())
{
return
context
.Documents
.Where(c => c.Name.EndsWith("." + format))
.ToArray();
}
}
Clearly, the logging code has made the original method less readable. It has tangled the real method code with logging code.
This is also a violation of the Single Responsibility Principle.
Also, we expect to find the same logging pattern in many methods all over the code base. Basically, we expect to find the following pattern:
try
{
//Do something here
logger.LogSuccess(…
//..
}
catch (Exception ex)
{
logger.LogError(…
throw;
}
There are some Fody Add-ins that will allow you to add this kind of code into your compiled output at compile-time rather than having to write it yourself.
For example, MethodDecorator allows you to define a specific attribute, and any method you decorate with that attribute will call specific methods prior to entering and leaving the method.
I should note that for a project of any reasonable size, logging the entry and exit for every single method is going to produce more log messages than anyone can reasonably expect to read. I'd suggest you be judicious in which methods add log messages, and what information you include in those log messages.
The vast majority of the time a more useful strategy is to use guard statements to test your assumptions along the way, throwing an exception the moment anything is out of place, and then wrapping exceptions with more useful information (via InnerException) as they go up the call chain, then finally logging the results of those exceptions at the top level of your application. That way, you only produce log messages when something appears to go in a way you don't expect, and the log message in that case has all the information you're likely to need.
I'm not sure this is exactly what you're looking for, but it might point you in the right direction. For demonstration purposes I'm logging to the Console, but you could log to a file instead.
You could create a method that takes in another method to execute, which executes the function and returns the value, and which wraps the beginning and ending of the method call with writes to your log file:
// For methods that return a value
private static TResult LogMethod<TResult>(string displayName, Func<TResult> method)
{
Console.WriteLine($"{DateTime.Now} - Starting method: {displayName}");
TResult result = method();
Console.WriteLine($"{DateTime.Now} - Completed method: {displayName}");
return result;
}
// For void methods
private static void LogMethod(string displayName, Action method)
{
Console.WriteLine($"{DateTime.Now} - Starting method: {displayName}");
method();
Console.WriteLine($"{DateTime.Now} - Completed method: {displayName}");
}
As an example of how to use this, let's say we have the following methods:
private static int GetNumberFromUser(string prompt)
{
int result;
do
{
Console.Write(prompt);
} while (!int.TryParse(Console.ReadLine(), out result));
return result;
}
private static int AddNumbers(int first, int second)
{
return first + second;
}
private static void Tell(string message)
{
Console.WriteLine(message);
}
Now, instead of calling these methods directly, we can call them through our LogMethod function:
private static void Main()
{
var firstNumber = LogMethod("GetNumber",
() => GetNumberFromUser("Enter first number: "));
var secondNumber = LogMethod("GetNumber",
() => GetNumberFromUser("Enter second number: "));
var result = LogMethod("AddNumber",
() => AddNumbers(firstNumber, secondNumber));
LogMethod("Tell", () => Tell($"{firstNumber} + {secondNumber} = {result}"));
GetKeyFromUser("\nDone!! Press any key to exit...");
}
Output

Performance Tricks for C# Logging

I am looking into C# logging and I do not want my log messages to spend any time processing if the message is below the logging threshold. The best I can see log4net does is a threshold check AFTER evaluating the log parameters.
Example:
_logger.Debug( "My complicated log message " + thisFunctionTakesALongTime() + " will take a long time" )
Even if the threshold is above Debug, thisFunctionTakesALongTime will still be evaluated.
In log4net you are supposed to use _logger.isDebugEnabled so you end up with
if( _logger.isDebugEnabled )
_logger.Debug( "Much faster" )
I want to know if there is a better solution for .net logging that does not involve a check each time I want to log.
In C++ I am allowed to do
LOG_DEBUG( "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" )
since my LOG_DEBUG macro does the log level check itself. This frees me to have a 1 line log message throughout my app which I greatly prefer. Anyone know of a way to replicate this behavior in C#?
If you can target .NET 3.5 (C# 3.0) you can use extension methods to wrap the if statements.
so you can do the equivalent "macro":
logger.Log_Debug("Much faster");
logger.Log_Debug(() => { "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" });
by wrapping the check in this method:
public class Log4NetExtensionMethods {
// simple string wrapper
public void Log_Debug(this log4net.ILog logger, string logMessage) {
if(logger.isDebugEnabled) {
logger.Debug(logMessage);
}
}
// this takes a delegate so you can delay execution
// of a function call until you've determined it's necessary
public void Log_Debug(this log4net.ILog logger, Func<string> logMessageDelegate) {
if(logger.isDebugEnabled) {
logger.Debug(logMessageDelegate());
}
}
}
17.4.2 The Conditional attribute
The attribute Conditional enables the definition of conditional methods. The Conditional attribute indicates a condition by testing a conditional compilation symbol. Calls to a conditional method are either included or omitted depending on whether this symbol is defined at the point of the call. If the symbol is defined, the call is included; otherwise, the call (including evaluation of the parameters of the call) is omitted.
[ Conditional("DEBUG") ]
public static void LogLine(string msg,string detail)
{
Console.WriteLine("Log: {0} = {1}",msg,detail);
}
public static void Main(string[] args)
{
int Total = 0;
for(int Lp = 1; Lp < 10; Lp++)
{
LogLine("Total",Total.ToString());
Total = Total + Lp;
}
}
The problem here is that all method parameters must be evaluated before the method is invoked. There is no way around this, given the syntax you are using. Since C# does not have a real preprocessor or macros, you can't do anything like "LOG_DEBUG". The best you could do is use if (logger.isDebugEnable) as suggested.
The only thing I can think of is maybe using something like a lambda expression to delay evaluation. But I would warn you that this will almost certainly have more of a performance hit in the end.
internal class Sample
{
private static void Main(string[] args)
{
DelayedEvaluationLogger.Debug(logger, () => "This is " + Expensive() + " to log.");
}
private static string Expensive()
{
// ...
}
}
internal static class DelayedEvaluationLogger
{
public static void Debug(ILog logger, Func<string> logString)
{
if (logger.isDebugEnabled)
{
logger.Debug(logString());
}
}
}
Without a preprocessor you're SOL. Of course there's nothing preventing you from using one before feeding your code to the C# compiler.

Passing a random method as a parameter?

Is there any way in C# to pass a random method as a parameter?
To explain my question:
I want to write a simple Logger-Tool that reports the entering and leaving of a method with the passed arguments an the class and method name:
The log file I'm aiming at:
ENTERING: ClassOfDoom::MethodOfDoom( arg1={1} [int], arg2={true} [bool] )
LEAVING: ClassOfDoom::MethodOfDoom RETURNING 1 [int]
The code I have in mind:
class ClassOfDoom {
// Remeber: MethodOfDoom is a _random_ method with _random_ arguments
public int MethodOfDoom(int arg1, bool arg2) {
Log.Entering(this, this.MethodOfDoom, arg1, arg2);
...
return Log.Returing(this, this.MethodOfDoom, 1);
}
}
Is there a way to achieve this? Or isn't C# as flexible as that?
Thanks in advance!
You can make your logging function take a MethodBase argument and use MethodBase.GetCurrentMethod to pass the current method info as an argument.
Then, in the logger, you could check its properties Name and DeclaringType to get the method information. Also, passing parameters is easy by declaring a params object[] args parameter in the logging function:
public static void Entering(object obj, MethodBase methodInfo,
params object[] args) {
Console.WriteLine("ENTERING {0}:{1}", methodInfo.DeclaringType.Name,
methodInfo.Name);
...
}
I'm not sure I entirely understand your question, but if you are trying to make a call to Log.Entering and Log.Returning inside an arbitrary (random) method and using the method's actual parameters, you should check out PostSharp. It will allow you to inject code in a method body and then do some work based on the reflected method information you get from the .NET framework (and the actual parameters passed to the method at runtime).
You could do it with Expression easily enough - it would look something like:
Log.Capture(() => this.MethodOfDoom(arg1, arg2));
Here's an example; I've been a bit lazy using Compile().DynamicInvoke() to read the arg-values - for real code I'd try to read it more directly:
using System;
using System.Diagnostics;
using System.Linq.Expressions;
class Program
{
DateTime MethodOfDoom(string s, int i)
{
return DateTime.Today;
}
public void RunTest()
{
int i =123;
Log.Capture(() => this.MethodOfDoom("abc", i));
}
static void Main()
{
new Program().RunTest();
}
}
static class Log
{
public static T Capture<T>(Expression<Func<T>> method)
{
MethodCallExpression mce = method.Body as MethodCallExpression;
if (mce == null) throw new InvalidOperationException(
"Method-call expected");
string name = mce.Method.Name;
try
{
int i = 0;
foreach(var param in mce.Method.GetParameters())
{
object argValue = Expression.Lambda(mce.Arguments[i++])
.Compile().DynamicInvoke();
Trace.WriteLine(param.Name + "=" + argValue, name);
}
Trace.WriteLine("ENTERING", name);
T result = method.Compile().Invoke();
Trace.WriteLine("EXITING: " + result, name);
return result;
}
catch (Exception ex)
{
Trace.WriteLine("EXCEPTION: " + ex, name);
throw;
}
}
}
If widely used in your code, this scenario is best implemented using Aspect Oriented Programming (AOP) techniques. There are different frameworks that can be used (such as Spring.NET AOP), which you can use in your .NET application. Here is a reference article that might help you get started:
http://www.developer.com/lang/article.php/10924_3795031_2
The referenced article gives you the logging enter/exit scenario as an example.
I have used PostSharp to do this very thing before.

Writing code to fire the last method to throw an exception in a multi-threaded web app

I was writing some try-catch blocks for various methods today, and thought to myself it would be good to have utility method which would automatically call the method again for a number of times specified in a parameter, at a certain time.
However, I thought to myself, the method/property etc which will cause an exception will be at the top of the stacktrace (do property calls get put on the stacktrace?) in a single threaded application (so an application with no code relating to threading). So I can simply get the method name at the top and dynamically call it again.
So I would have code like:
string s = StackTrace.GetFrame(0).GetMethodName; (I can't remember the exact syntax).
With this method, I can execute it using an activator or one of several other ways.
But in a multi-threaded application, I could have several methods firing at once and I wouldn't know which one finishes first/last. So I can't expect a method for which I write a try-catch block to be at the top of the stack.
How would I go about achieving this?
Please don't do this. It's a really, really, really, really, really bad idea.
Maybe not as bad as deleting files randomly, if the hard drive runs out of room - but just about as bad.
While I question the need for an auto retrying mechanism (does randomly retrying really help you out in so many situations that you need a utility method?) - using StackTrace and Reflection is, at best, a terribly complicated solution.
Not that I suggest that anyone actually use this code, but I'd probably go with a delegate based approach to this particular problem:
public static class Extensions {
public static void Try(this Action a, int maxTries) {
new (Func<bool>(() => { a(); return true; })).Try(maxTries);
}
public static TResult Try<TResult>(this Func<TResult> f, int maxTries) {
Exception lastException = null;
for (int i = 0; i < maxTries; i++) {
try {
return f();
} catch (Exception ex) {
lastException = ex;
}
}
throw lastException;
}
}
Usage is a bit unorthodox, but fairly clear I think:
// Set a property
new Action(() => myObject.Property = 5).Try(5);
// With a return value
var count = new Func<int>(() => myList.Count).Try(3);
You can't inline a lambda to a method, but you could have a somewhat fluent interface:
Utilities.Try(
() => MyObject.Property = 5
).Repeat(5);
And multi line methods:
Utilities.Try(() => {
MyObject.Property1 = 5;
MyObject.Property2 = 6;
MyObject.Property3 = 7;
}).Repeat(5);
Mark's code is probably better, but here's mine...
If you really want to do something like this, I'd use code something like this. Yes, you still have to manually call it, but your idea of indiscriminately retrying ALL excepting methods is a really, really bad idea.
public class TryAgain
{
public delegate void CodeToTryAgain ();
public static void Repeat<E>(int count, CodeToTryAgain code) where E : Exception
{
while (count-- > 0)
{
try
{
code();
return;
}
catch (E ex)
{
Console.WriteLine("Caught an {0} : {1}", typeof(E).Name, ex.Message);
// ignoring it!
}
}
}
}
And then you'd call your failing method, ThrowTwice, or whatever you want to do, like this:
TryAgain.Repeat<MyException>(5, delegate()
{
ThrowTwice();
});
In this example, the Repeat method will ignore all exceptions of type MyException, trying to call ThrowTwice up to 5 times...
You can add your own sleeping and time-outs, and whatever.

Reducing duplicate error handling code in C#?

I've never been completely happy with the way exception handling works, there's a lot exceptions and try/catch brings to the table (stack unwinding, etc.), but it seems to break a lot of the OO model in the process.
Anyway, here's the problem:
Let's say you have some class which wraps or includes networked file IO operations (e.g. reading and writing to some file at some particular UNC path somewhere). For various reasons you don't want those IO operations to fail, so if you detect that they fail you retry them and you keep retrying them until they succeed or you reach a timeout. I already have a convenient RetryTimer class which I can instantiate and use to sleep the current thread between retries and determine when the timeout period has elapsed, etc.
The problem is that you have a bunch of IO operations in several methods of this class, and you need to wrap each of them in try-catch / retry logic.
Here's an example code snippet:
RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
try
{
// do some file IO which may succeed or fail
success = true;
}
catch (IOException e)
{
if (fileIORetryTimer.HasExceededRetryTimeout)
{
throw e;
}
fileIORetryTimer.SleepUntilNextRetry();
}
}
So, how do you avoid duplicating most of this code for every file IO operation throughout the class? My solution was to use anonymous delegate blocks and a single method in the class which executed the delegate block passed to it. This allowed me to do things like this in other methods:
this.RetryFileIO( delegate()
{
// some code block
} );
I like this somewhat, but it leaves a lot to be desired. I'd like to hear how other people would solve this sort of problem.
This looks like an excellent opportunity to have a look at Aspect Oriented Programming. Here is a good article on AOP in .NET. The general idea is that you'd extract the cross-functional concern (i.e. Retry for x hours) into a separate class and then you'd annotate any methods that need to modify their behaviour in that way. Here's how it might look (with a nice extension method on Int32)
[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
//.. code to just delete the archive
}
Just wondering, what do you feel your method leaves to be desired? You could replace the anonymous delegate with a.. named? delegate, something like
public delegate void IoOperation(params string[] parameters);
public void FileDeleteOperation(params string[] fileName)
{
File.Delete(fileName[0]);
}
public void FileCopyOperation(params string[] fileNames)
{
File.Copy(fileNames[0], fileNames[1]);
}
public void RetryFileIO(IoOperation operation, params string[] parameters)
{
RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
try
{
operation(parameters);
success = true;
}
catch (IOException e)
{
if (fileIORetryTimer.HasExceededRetryTimeout)
{
throw;
}
fileIORetryTimer.SleepUntilNextRetry();
}
}
}
public void Foo()
{
this.RetryFileIO(FileDeleteOperation, "L:\file.to.delete" );
this.RetryFileIO(FileCopyOperation, "L:\file.to.copy.source", "L:\file.to.copy.destination" );
}
You could also use a more OO approach:
Create a base class that does the error handling and calls an abstract method to perform the concrete work. (Template Method pattern)
Create concrete classes for each operation.
This has the advantage of naming each type of operation you perform and gives you a Command pattern - operations have been represented as objects.
Here's what I did recently. It has probably been done elsewhere better, but it seems pretty clean and reusable.
I have a utility method that looks like this:
public delegate void WorkMethod();
static public void DoAndRetry(WorkMethod wm, int maxRetries)
{
int curRetries = 0;
do
{
try
{
wm.Invoke();
return;
}
catch (Exception e)
{
curRetries++;
if (curRetries > maxRetries)
{
throw new Exception("Maximum retries reached", e);
}
}
} while (true);
}
Then in my application, I use c#'s Lamda expression syntax to keep things tidy:
Utility.DoAndRetry( () => ie.GoTo(url), 5);
This calls my method and retries up to 5 times. At the fifth attempt, the original exception is rethrown inside of a retry exception.

Categories

Resources