Modules/Logging/TraceListener.vb

250 lines
8.9 KiB
VB.net

Imports System
Imports System.Configuration
Imports System.Diagnostics
Imports System.Globalization
Imports System.IO
Imports System.Security.Permissions
Imports System.Text.RegularExpressions
<HostProtection(Synchronization:=True)>
Public Class RollingXmlWriterTraceListener
Inherits XmlWriterTraceListener
Private Shared ReadOnly LogFileNumberCaptureName As String = "LogFileNumber"
Private attributesLoaded As Boolean = False
Private logfileSuffixExpression As Regex = New Regex("_(?<" & LogFileNumberCaptureName & ">\d*)\.", RegexOptions.Compiled)
Private currentFileSuffixNumber As Integer = 0
Private _maxTraceFileSize As Long = 128 * 1024 * 1024
Private basicTraceFileName As String = String.Empty
Public Sub New(ByVal filename As String)
MyBase.New(filename)
Me.basicTraceFileName = filename
Me.currentFileSuffixNumber = Me.GetTraceFileNumber()
Me.StartNewTraceFile()
End Sub
Public Sub New(ByVal filename As String, ByVal name As String)
MyBase.New(filename, name)
Me.basicTraceFileName = filename
Me.StartNewTraceFile()
End Sub
Public ReadOnly Property CurrentTraceFileName As String
Get
Return Path.Combine(Path.GetDirectoryName(Me.basicTraceFileName), Path.GetFileNameWithoutExtension(Me.basicTraceFileName) & "_" & Me.currentFileSuffixNumber.ToString().PadLeft(4, "0"c) & Path.GetExtension(Me.basicTraceFileName))
End Get
End Property
Public Property MaxTraceFileSize As Long
Get
If Not Me.attributesLoaded Then
Me.LoadAttributes()
End If
Return Me._maxTraceFileSize
End Get
Set(ByVal value As Long)
If Not Me.attributesLoaded Then
Me.LoadAttributes()
End If
Me._maxTraceFileSize = value
End Set
End Property
Protected ReadOnly Property IsRollingConditionReached As Boolean
Get
Dim streamWriter As StreamWriter = CType(Me.Writer, StreamWriter)
Dim fileStream As FileStream = CType(streamWriter.BaseStream, FileStream)
Dim traceFileName As String = fileStream.Name
Dim traceFileInfo As FileInfo = New FileInfo(traceFileName)
If traceFileInfo.Length > Me._maxTraceFileSize Then
Return True
Else
Return False
End If
End Get
End Property
Public Overrides Sub Fail(ByVal message As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.Fail(message)
End Sub
Public Overrides Sub Fail(ByVal message As String, ByVal detailMessage As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.Fail(message, detailMessage)
End Sub
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.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.TraceData(eventCache, source, eventType, id, data)
End Sub
Public Overrides Sub TraceData(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer, ParamArray data As Object())
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.TraceData(eventCache, source, eventType, id, data)
End Sub
Public Overrides Sub TraceEvent(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.TraceEvent(eventCache, source, eventType, id)
End Sub
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.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.TraceEvent(eventCache, source, eventType, id, message)
End Sub
Public Overrides Sub TraceEvent(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal eventType As TraceEventType, ByVal id As Integer, ByVal format As String, ParamArray args As Object())
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.TraceEvent(eventCache, source, eventType, id, format, args)
End Sub
Public Overrides Sub TraceTransfer(ByVal eventCache As TraceEventCache, ByVal source As String, ByVal id As Integer, ByVal message As String, ByVal relatedActivityId As Guid)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.TraceTransfer(eventCache, source, id, message, relatedActivityId)
End Sub
Public Overrides Sub Write(ByVal o As Object)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.Write(o)
End Sub
Public Overrides Sub Write(ByVal o As Object, ByVal category As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.Write(o, category)
End Sub
Public Overrides Sub Write(ByVal message As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.Write(message)
End Sub
Public Overrides Sub Write(ByVal message As String, ByVal category As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.Write(message, category)
End Sub
Public Overrides Sub WriteLine(ByVal o As Object)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.WriteLine(o)
End Sub
Public Overrides Sub WriteLine(ByVal o As Object, ByVal category As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.WriteLine(o, category)
End Sub
Public Overrides Sub WriteLine(ByVal message As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.WriteLine(message)
End Sub
Public Overrides Sub WriteLine(ByVal message As String, ByVal category As String)
If Me.IsRollingConditionReached Then
Me.StartNewTraceFile()
End If
MyBase.WriteLine(message, category)
End Sub
Protected Overrides Function GetSupportedAttributes() As String()
Return New String(0) {"MaxTraceFileSize"}
End Function
Private Sub StartNewTraceFile()
Dim streamWriter As StreamWriter = CType(Me.Writer, StreamWriter)
Dim fileStream As FileStream = CType(streamWriter.BaseStream, FileStream)
fileStream.Close()
Me.currentFileSuffixNumber += 1
Me.Writer = New StreamWriter(New FileStream(Me.CurrentTraceFileName, FileMode.Create))
End Sub
Private Function GetTraceFileNumber() As Integer
Dim directoryName As String = Path.GetDirectoryName(Me.basicTraceFileName)
Dim basicTraceFileNameWithoutExtension As String = Path.GetFileNameWithoutExtension(Me.basicTraceFileName)
Dim basicTraceFileNameExtension As String = Path.GetExtension(Me.basicTraceFileName)
Dim existingLogFiles As String() = Directory.GetFiles(directoryName, basicTraceFileNameWithoutExtension & "*")
Dim highestNumber As Integer = -1
For Each existingLogFile As String In existingLogFiles
Dim match As Match = Me.logfileSuffixExpression.Match(existingLogFile)
If match IsNot Nothing Then
Dim tempInt As Integer
If match.Groups.Count >= 1 AndAlso Integer.TryParse(match.Groups(LogFileNumberCaptureName).Value, tempInt) AndAlso tempInt >= highestNumber Then
highestNumber = tempInt
End If
End If
Next
Return highestNumber
End Function
Private Sub LoadAttributes()
If Attributes.ContainsKey("MaxTraceFileSize") AndAlso Not String.IsNullOrEmpty(Attributes("MaxTraceFileSize")) Then
Dim tempLong As Long = 0
Dim attributeValue As String = Attributes("MaxTraceFileSize")
If Long.TryParse(attributeValue, tempLong) Then
Me._maxTraceFileSize = Long.Parse(Attributes("MaxTraceFileSize"), NumberFormatInfo.InvariantInfo)
Else
Throw New ConfigurationErrorsException(String.Format("Trace listener {0} has an unparseable configuration attribute ""MaxTraceFileSize"". The value ""{1}"" cannot be parsed to a long value.", Me.Name, attributeValue))
End If
End If
Me.attributesLoaded = True
End Sub
End Class