ArtinSoft's Blogs

Software Migration Experts
Welcome to ArtinSoft's Blogs Sign in | Join | Help
in Search

Mauricio Rojas Blog

May 2006 - Posts

  • More Color to your Traces!

    Most Visual Basic programmers are familiar with using Debug.Print to follow their code's execution. The .NET environment introduces Tracing falicities that allows you to send messages to files or the console.

    However the console output could be improved by using colors to highlight certain events. 
    I developed a simple ColorTraceListener that can be used either with the My.Application.Log object or the Trace.TraceXXX methods. 
    I first thing to do is create a ClassLibrary. It will be called ColorTraceListener. Add a ColorTraceListener.cs File and fill it with the following code:
     

    Imports System

    Imports System.Diagnostics

    Imports System.Globalization

    Imports System.Text

    Imports System.Runtime.InteropServices 

    Public Class ColorTraceListener

        Inherits ConsoleTraceListener

        Public Sub New()

            MyBase.New()

        End Sub 

        Public Sub New(ByVal useErrorStream As Boolean)

            MyBase.New(useErrorStream)

        End Sub 

        Friend Function IsEnabled(ByVal opts As TraceOptions) As Boolean

            Return ((opts And Me.TraceOutputOptions) <> TraceOptions.None)

        End Function 
     
     

        False)> _

        Public Overrides Sub TraceData(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer, ByVal data As Object)

            If ((Me.Filter Is Nothing) OrElse Me.Filter.ShouldTrace(eventCache, source, eventType, id, Nothing, Nothing, Nothing, data)) Then

                Me.WriteHeader(source, eventType, id)

                Dim text1 As String = String.Empty

                If (Not data Is Nothing) Then

                    text1 = data.ToString

                End If

                Me.WriteLine(text1)

                Me.WriteFooter(eventCache)

            End If

        End Sub 

        False)> _

        Public Overrides Sub TraceData(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer, ByVal ParamArray data As Object())

            If ((Me.Filter Is Nothing) OrElse Me.Filter.ShouldTrace(eventCache, source, eventType, id, Nothing, Nothing, Nothing, data)) Then

                Me.WriteHeader(source, eventType, id)

                Dim builder1 As New StringBuilder

                If (Not data Is Nothing) Then

                    Dim num1 As Integer = 0

                    Do While (num1

                        If (num1 <> 0) Then

                            builder1.Append(", ")

                        End If

                        If (Not data(num1) Is Nothing) Then

                            builder1.Append(data(num1).ToString)

                        End If

                        num1 += 1

                    Loop

                End If

                Me.WriteLine(builder1.ToString)

                Me.WriteFooter(eventCache)

            End If

        End Sub 
     

        False)> _

        Public Overrides Sub TraceEvent(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer, ByVal message As String)

            If ((Me.Filter Is Nothing) OrElse Me.Filter.ShouldTrace(eventCache, source, eventType, id, message, Nothing, Nothing, Nothing)) Then

                Me.WriteHeader(source, eventType, id)

                Me.WriteLine(message)

                Me.WriteFooter(eventCache)

            End If

        End Sub 
     

        False)> _

        Public Overrides Sub TraceEvent(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer, ByVal format As String, ByVal ParamArray args As Object())

            If ((Me.Filter Is Nothing) OrElse Me.Filter.ShouldTrace(eventCache, source, eventType, id, format, args, Nothing, Nothing)) Then

                Me.WriteHeader(source, eventType, id)

                If (Not args Is Nothing) Then

                    Me.WriteLine(String.Format(CultureInfo.InvariantCulture, format, args))

                Else

                    Me.WriteLine(format)

                End If

                Me.WriteFooter(eventCache)

            End If

        End Sub 
     
     
     
     

        Private Sub WriteFooter(ByVal eventCache As TraceEventCache)

            If (Not eventCache Is Nothing) Then

                Me.IndentLevel += 1

                If Me.IsEnabled(TraceOptions.ProcessId) Then

                    Me.WriteLine(("ProcessId=" & eventCache.ProcessId))

                End If

                If Me.IsEnabled(TraceOptions.LogicalOperationStack) Then

                    Me.Write("LogicalOperationStack=")

                    Dim stack1 As Stack = eventCache.LogicalOperationStack

                    Dim flag1 As Boolean = True

                    Dim obj1 As Object

                    For Each obj1 In stack1

                        If Not flag1 Then

                            Me.Write(", ")

                        Else

                            flag1 = False

                        End If

                        Me.Write(obj1.ToString)

                    Next

                    Me.WriteLine(String.Empty)

                End If

                If Me.IsEnabled(TraceOptions.ThreadId) Then

                    Me.WriteLine(("ThreadId=" & eventCache.ThreadId))

                End If

                If Me.IsEnabled(TraceOptions.DateTime) Then

                    Me.WriteLine(("DateTime=" & eventCache.DateTime.ToString("o", CultureInfo.InvariantCulture)))

                End If

                If Me.IsEnabled(TraceOptions.Timestamp) Then

                    Me.WriteLine(("Timestamp=" & eventCache.Timestamp))

                End If

                If Me.IsEnabled(TraceOptions.Callstack) Then

                    Me.WriteLine(("Callstack=" & eventCache.Callstack))

                End If

                Me.IndentLevel -= 1

            End If

        End Sub 

        Private Sub WriteHeader(ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer)

            Dim oldColor As ConsoleColor = Console.ForegroundColor

            Select Case eventType

                Case TraceEventType.Error

                    Console.ForegroundColor = ConsoleColor.Red

                Case TraceEventType.Critical

                    Console.ForegroundColor = ConsoleColor.Magenta

                Case TraceEventType.Information

                    Console.ForegroundColor = ConsoleColor.White

                    'Case TraceEventType.Resume

                    'Case TraceEventType.Start

                    'Case TraceEventType.Suspend

                    'Case(TraceEventType.Transfer)

                    'Case TraceEventType.Verbose

                Case TraceEventType.Warning

                    Console.ForegroundColor = ConsoleColor.Yellow

            End Select

            Me.Write(String.Format(CultureInfo.InvariantCulture, "{0} {1}:", New Object() {source, eventType.ToString}))

            Console.ForegroundColor = oldColor

            Me.Write(String.Format(CultureInfo.InvariantCulture, " {0} : ", New Object() {id.ToString(CultureInfo.InvariantCulture)}))

        End Sub

    End Class 

    The methods that handle the headers in the TextWriteListener are private (WriteHeader and WriterFooter) so we need to override them. Reflector comes very handy in this cases. 

    No to test it Create a Vb Console Application: 

    Module Module1 

        Sub Main() 
     

            My.Application.Log.WriteEntry("Error!", TraceEventType.Error)

            My.Application.Log.WriteEntry("Warning", TraceEventType.Warning)

            My.Application.Log.WriteEntry("Info", TraceEventType.Information)

            My.Application.Log.WriteEntry("Info", TraceEventType.Critical) 

            Trace.TraceError("An Error Happened!")

            Trace.TraceInformation("Just letting you know!")

            Trace.TraceWarning("Watch the road ahead") 

        End Sub 

    End Module 

    And use a simple configuration file like the following: 

    xml version="1.0" encoding="utf-8" ?>

    configuration>

        system.diagnostics>

          trace autoflush="true">

            listeners>

              add name="ColorLog" />

            listeners>

          trace>

            sources>

                This section defines the logging configuration for My.Application.Log -->

                source name="DefaultSource" switchName="DefaultSwitch">

                    listeners>

                        add name="ColorLog"/>

                    listeners>

                source>

            sources>

            switches>

                add name="DefaultSwitch" value="Verbose" />

            switches>

           sharedListeners>

              add name="ColorLog" type="Mrojas.ColorTraceListener, ColorTraceListener" />

            sharedListeners>

        system.diagnostics>

    configuration> 
     

Powered by Community Server (Non-Commercial Edition), by Telligent Systems