views:

508

answers:

4

I'm working on an approach to trace logging for my company's VB.NET project. The .NET framework has pretty versatile trace capabilities and I'd like to use what .NET already provides. My company wants to stay away from 3rd party software, so log4net and whatnot is out of the question.

They want to be able to trace the flow of the web application, and using trace sources, listeners, and switches will make this part pretty easy. However, they want me to trace when variables change throughout the program without having to write Trace.Write("i = " & i) every other line in a calculation.

So, any efficient approaches out there to do this?

Your answers are appreciated. Thanks in advance.


I decided to go with making a class. I simply made a TraceVariable Class that had an IntegerChanged event. This way, the developers of other parts of the code, will be able to control how to handle the variable change, if he wanted to do something other than trace it.

Here's the code (VB):

    Public Class TraceVariable  
        Private mInteger As Integer  
        Public Event IntegerChanged(ByVal mInteger As Integer)  
        Public Property TraceInteger() As Integer
            Get
                TraceInteger = mInteger
            End Get
            Set(ByVal value As Integer)
                mInteger = value
                RaiseEvent IntegerChanged(mInteger)
            End Set
        End Property
    End Class

Thanks for the answers! As for the this being messy, we're only going to use it for critical variables, so no worries. Tracing in our situation is a necessity and a safety precaution.

A: 

If you are talking about primitive variables like int, double etc then this will be tough but if you need to trace access to your custom classes then all you need to do is place a few trace statements in your property setters and methods which modify state (mutators).

Now as for the primitive types you my try using some kind of AOP tool (like postsharp) to patch the IL code (mutators) for these primitive types to emit trace messages same as you might do for a user defined class.

SDX2000
A: 

Tracing when variables change seems pretty extreme... it's probably going to be slow.

I'm not aware of anything built into the framework that does this. Essentially, it's closer to profiling or debugging than to tracing.

Assaf Lavie
+1  A: 

Tracing every variable change would quickly become messy and lead to information overload for any but the most trivial of applications.

If there are specific variables that you want to trace the changes in, wrap them in a simple self-rolled Traceable class with accessors that write out to Trace when you do an update.

Jekke
A: 

You may want to try the following (warning => C#):

    class Program
{
    static void Main(string[] args)
    {
        test(1, "one");
        test(2, "two");
        test(3, "three");
        Console.ReadLine();
    }

    private static void test(int x, string y)
    {
        DisplayParameterNameAndValue(() => x);
        DisplayParameterNameAndValue(() => y);
    }


    static void DisplayParameterNameAndValue(Expression<Func<object>> parameter)
    {
        var expressionBody = parameter.Body;
        MemberExpression memberExpression;
        if (expressionBody is UnaryExpression)
        {
            memberExpression = (MemberExpression)((UnaryExpression)expressionBody).Operand;
        }
        else if (expressionBody is MemberExpression)
        {
            memberExpression = (MemberExpression)expressionBody;
        }
        else
        {
            throw new ArgumentException("parameter");
        }
        string parameterName = memberExpression.Member.Name;
        object parameterValue = parameter.Compile().Invoke();
        Console.WriteLine("{0} => {1}", parameterName, parameterValue);
    }
}

The equivalent code in VB would be:

Module Module1

Sub Main()
    test(1, "one")
    test(2, "two")
    test(3, "three")
    Console.ReadLine()
End Sub
Private Sub test(ByVal x As Integer, ByVal y As String)
    DisplayParameterNameAndValue(Function() x)
    DisplayParameterNameAndValue(Function() y)
End Sub


Private Sub DisplayParameterNameAndValue(ByVal parameter As Expression(Of Func(Of Object)))
    Dim expressionBody = parameter.Body
    Dim memberExpression As MemberExpression
    If TypeOf expressionBody Is UnaryExpression Then
        memberExpression = DirectCast(DirectCast(expressionBody, UnaryExpression).Operand, MemberExpression)
    ElseIf TypeOf expressionBody Is MemberExpression Then
        memberExpression = DirectCast(expressionBody, MemberExpression)
    Else
        Throw New ArgumentException("parameter")
    End If
    Dim parameterName As String = memberExpression.Member.Name
    Dim parameterValue As Object = parameter.Compile().Invoke()
    Console.WriteLine("{0} => {1}", parameterName, parameterValue)
  End Sub
End Module

I have test it, but it does not give me the same results as with c#, bad vb!

Hope this helps.

Jaime Febres
Thanks for the code.Bad VB indeed. If only the high-ups would let us use c#...
Paxenos