Imports System.IO
Imports System.Text
Imports System.Collections.Concurrent
Public Module Logger
Private ReadOnly logDirectory As String = "c:\\logs"
Private ReadOnly maxLogSizeBytes As Long = 10 * 1024 * 1024 ' 每个文件最大10MB
Private ReadOnly logRetentionDays As Integer = 1
Private ReadOnly logLock As New Object()
Private ReadOnly logQueue As New ConcurrentQueue(Of String)()
Private ReadOnly logWritingTask As Task
Public Enum LogLevel
Info
Warn
[Error]
Debug
End Enum
'''
''' 初始化日志写入任务
'''
Sub New()
logWritingTask = Task.Run(AddressOf ProcessLogQueue)
End Sub
'''
''' 异步写入带等级的日志
'''
Public Sub WriteLog(level As LogLevel, message As String)
Dim logEntry As String = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} [{level.ToString().ToUpper()}] {message}"
logQueue.Enqueue(logEntry)
End Sub
'''
''' 定期从队列中取出日志并写入文件
'''
Private Async Sub ProcessLogQueue()
While True
' 确保日志写入任务不会频繁创建线程
If logQueue.IsEmpty Then
Await Task.Delay(500) ' 等待一段时间再检查队列
End If
' 使用 TryDequeue 从队列中获取 logEntry
Dim logEntry As String = Nothing
If logQueue.TryDequeue(logEntry) Then
WriteLogToFile(logEntry)
End If
End While
End Sub
'''
''' 写入日志到文件
'''
Private Sub WriteLogToFile(logEntry As String)
Try
SyncLock logLock
If Not Directory.Exists(logDirectory) Then
Directory.CreateDirectory(logDirectory)
End If
CleanupOldLogs()
Dim todayFile As String = Path.Combine(logDirectory, $"{Date.Today:yyyy-MM-dd}.log")
If File.Exists(todayFile) Then
Dim fileInfo As New FileInfo(todayFile)
If fileInfo.Length > maxLogSizeBytes Then
BackupAndClear(todayFile)
End If
End If
Using sw As New StreamWriter(todayFile, append:=True, encoding:=Encoding.UTF8)
sw.WriteLine(logEntry)
End Using
End SyncLock
Catch
' 忽略日志写入错误
End Try
End Sub
'''
''' 清理过期的日志文件
'''
Private Sub CleanupOldLogs()
Try
Dim files = Directory.GetFiles(logDirectory)
For Each file In files
Dim fileName = Path.GetFileNameWithoutExtension(file)
Dim dateStr = fileName.Split("_"c).FirstOrDefault()
If Date.TryParse(dateStr, Nothing) Then
Dim fileDate = Date.Parse(dateStr)
If (Date.Today - fileDate).Days >= logRetentionDays Then
file.Remove(file)
End If
End If
Next
Catch
' 忽略清理错误
End Try
End Sub
'''
''' 备份并清空日志文件
'''
Private Sub BackupAndClear(filePath As String)
Try
Dim bakFile As String = filePath.Replace(".log", $"_{DateTime.Now:HHmmss}.bak")
File.Copy(filePath, bakFile, overwrite:=True)
File.WriteAllText(filePath, "") ' 清空日志内容
Catch
' 忽略备份错误
End Try
End Sub
'''
''' 快捷方法:写 Info 日志
'''
Public Sub Info(message As String)
'WriteLog(LogLevel.Info, message)
End Sub
'''
''' 快捷方法:写 Warning 日志
'''
Public Sub Warn(message As String)
'WriteLog(LogLevel.Warn, message)
End Sub
'''
''' 快捷方法:写 Error 日志
'''
Public Sub [Error](message As String)
'WriteLog(LogLevel.Error, message)
End Sub
'''
''' 快捷方法:写 Debug 日志
'''
Public Sub Debug(message As String)
'WriteLog(LogLevel.Debug, message)
End Sub
End Module