Generic logging of function parameters in exception handling

后端 未结 7 1051
渐次进展
渐次进展 2020-12-14 01:15

A lot of my C# code follows this pattern:

void foo(string param1, string param2, string param3)
{
    try
    {
         // do something...
    }
    catch(E         


        
相关标签:
7条回答
  • 2020-12-14 01:40

    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));
    }
    
    0 讨论(0)
  • 2020-12-14 01:43

    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;
    }
    
    0 讨论(0)
  • 2020-12-14 01:46

    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!

    0 讨论(0)
  • 2020-12-14 01:56

    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);
    
    0 讨论(0)
  • 2020-12-14 01:59

    There are scenarios of a few parameters or Large number of parameters...

    1. Few parameters, without much ado, better write them as part of the logging/exception message.

    2. 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

    0 讨论(0)
  • 2020-12-14 02:00

    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);
        }
    
    0 讨论(0)
提交回复
热议问题