Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question about effective logging in C#

I've written a simple class for debugging and I call the method Debugger.WriteLine(...) in my code like this:

Debugger.WriteLine("[Draw]", "InProgress",
    "[x,y] = " + x.ToString("0.00") + 
    ", " + y.ToString("0.00") + 
    "; pos = " + lastPosX.ToString() + "x" + 
    lastPosY.ToString() + " -> " + posX.ToString() + 
    "x" + posY.ToString() + "; SS = " + 
    squareSize.ToString() + "; MST = " + 
    startTime.ToString("0.000") + "; Time = " + time.ToString() +
    phase.ToString(".0000") + "; progress = " + 
    progress.ToString("0.000") + "; step = " + 
    step.ToString() + "; TimeMovementEnd = " + 
    UI.MovementEndTime.ToString()
);

The body of the procedure Debugger.WriteLine is compiled only in Debug mode (directives #if, #endif). What makes me worry is that I often need ToString() in Debugger.WriteLine call which is costly because it creates still new strings (for changing number for example). How to solve this problem?

A few points/questions about debugging/tracing:

  • I don't want to wrap every Debugger.WriteLine in an IF statement or to use preprocessor directives in order to leave out debugging methods because it would inevitable lead to a not very readable code and it requires too much typing.

  • I don't want to use any framework for tracing/debugging. I want to try to program it myself.

  • Are Trace methods left out if compiling in release mode? If it is so is it possible that my methods would behave similarly?

  • With the static String.Format method I can do this:

    output = String.Format("You are now {0} years old.", years);

Which seems nice. Is it a solution for my problem with ToString()?

like image 509
Martin Vseticka Avatar asked Dec 29 '22 20:12

Martin Vseticka


2 Answers

Using Reflector I found out that Debug.Writeline is declared this way :

[Conditional("DEBUG")]
public static void WriteLine(string message)

That means that in Release mode all calls to this method are eliminated from code.

For example this code :

public static void Test(int a)
{
    string b = Console.ReadLine();
    Debug.WriteLine(a + " " + b);
    Console.WriteLine(a + " " + b);
}

compiles in release mode to :

public static void Test(int a)
{
    Console.WriteLine(a + " " + Console.ReadLine());
}
like image 183
Catalin DICU Avatar answered Dec 31 '22 15:12

Catalin DICU


Use StringBuilder to create your output strings instead of concatenating each and every value.

And you can create your own custom debugger (MyDbg) class that contains a WriteLine member the contents of which you can surround with compile directives. It wouldn't entirely compile out the debug code but would turn you MyDbg.WriteLine calls into no-ops.

Here's a quick sketch of the class:

using System;
using System.Text ;

public static class MyDbg
{
    public static void WriteLine(string str) // and some other params
    {
        #if DEBUG

        StringBuilder sb = new StringBuilder();
        sb.Append(str);
        // etc. appending other params as you see fit
        #endif
    }
}

OR

[Conditional("DEBUG")]
public static class MyDbg
{
    public static void WriteLine(string str) // and some other params
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(str);
        // etc. appending other params as you see fit
    }
}

You'd modify it to suit your own needs of course. And instead of creating a separate class, you could create a member method if #if DEBUG/#endif built-in for displaying its own state when in the debugger.

like image 27
Paul Sasik Avatar answered Dec 31 '22 15:12

Paul Sasik