Agregar archivos de proyecto.
This commit is contained in:
218
TsLogger.vb
Normal file
218
TsLogger.vb
Normal file
@@ -0,0 +1,218 @@
|
||||
Imports System.Net.Http
|
||||
Imports System.IO
|
||||
Imports Microsoft.Extensions.Logging
|
||||
Imports System.Threading.Tasks
|
||||
Imports System.Configuration
|
||||
|
||||
'// Ejemplo de uso de la extensión LogVariable():
|
||||
'//
|
||||
'// ' Registrar información de una variable
|
||||
'// Dim peassoVariable As String = "Hello, World!"
|
||||
'// logger.LogVariable("peassoVariable", peassoVariable, LogLevel.Debug)
|
||||
|
||||
'// El uso del destino Pushover está limitado a danmun.
|
||||
|
||||
Public NotInheritable Class TsLoggerConfiguration
|
||||
'// Identificador del evento a registrar (0 para todos).
|
||||
Public Property EventId As Integer = 0
|
||||
'// Nivel mínimo de registro.
|
||||
Private Property _minimumLogLevel As LogLevel = LogLevel.Trace
|
||||
Public Property MinimumLogLevel As String
|
||||
Get
|
||||
Return _minimumLogLevel
|
||||
End Get
|
||||
Set(logLevelString As String)
|
||||
If Not [Enum].TryParse(logLevelString, True, _minimumLogLevel) Then
|
||||
'// Valor predeterminado en caso de que no se pueda
|
||||
'// interpretar la configuración.
|
||||
_minimumLogLevel = LogLevel.Trace
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
'// Indica si se debe registrar en la consola.
|
||||
Public Property LogToConsole As Boolean = False
|
||||
'// Indica si se debe registrar en la salida de depuración.
|
||||
Public Property LogToDebug As Boolean = True
|
||||
'// Indica si se debe registrar en un archivo.
|
||||
Public Property LogToFile As Boolean = False
|
||||
'// Ruta base para los archivos de registro (debe ser válida y accesible).
|
||||
Public Property LogFilePath As String
|
||||
Public Property LogToPushover As Boolean = False
|
||||
Public Property PushoverMinimumLogLevel As LogLevel = LogLevel.Error
|
||||
Public Property LogToSlack As Boolean = False
|
||||
Public Property SlackDestination As String = "#notificaciones"
|
||||
Public Property NetworkInSeparateThread As Boolean = False
|
||||
Public Property IncludeSourceInfo As Boolean = False
|
||||
'// Mapeo entre los niveles de registro y los colores de la consola.
|
||||
Friend ReadOnly Property LogLevelToColorMap As Dictionary(Of LogLevel, ConsoleColor) = New Dictionary(Of LogLevel, ConsoleColor) From {
|
||||
{LogLevel.Trace, ConsoleColor.DarkCyan},
|
||||
{LogLevel.Debug, ConsoleColor.Cyan},
|
||||
{LogLevel.Information, ConsoleColor.Green},
|
||||
{LogLevel.Warning, ConsoleColor.DarkYellow},
|
||||
{LogLevel.Error, ConsoleColor.Red},
|
||||
{LogLevel.Critical, ConsoleColor.Magenta}
|
||||
}
|
||||
End Class
|
||||
|
||||
Public NotInheritable Class TsLogger
|
||||
Implements ILogger
|
||||
|
||||
Private ReadOnly _name As String
|
||||
Private ReadOnly _getCurrentConfig As Func(Of TsLoggerConfiguration)
|
||||
Private ReadOnly _config As TsLoggerConfiguration
|
||||
|
||||
'// Constructor con nombre y función para obtener la configuración actual.
|
||||
Public Sub New(name As String, getCurrentConfig As Func(Of TsLoggerConfiguration))
|
||||
If String.IsNullOrEmpty(name) Then Throw New ArgumentException("El nombre no puede estar vacío", NameOf(name))
|
||||
If getCurrentConfig Is Nothing Then Throw New ArgumentNullException(NameOf(getCurrentConfig))
|
||||
_name = name
|
||||
_getCurrentConfig = getCurrentConfig
|
||||
End Sub
|
||||
|
||||
'// Constructor con nombre y configuración directa.
|
||||
Public Sub New(name As String, config As TsLoggerConfiguration)
|
||||
If String.IsNullOrEmpty(name) Then Throw New ArgumentException("El nombre no puede estar vacío", NameOf(name))
|
||||
If config Is Nothing Then Throw New ArgumentNullException(NameOf(config))
|
||||
_name = name
|
||||
_config = config
|
||||
End Sub
|
||||
|
||||
'// Obtener la configuración actual.
|
||||
Private Function GetCurrentConfiguration() As TsLoggerConfiguration
|
||||
Return If(_getCurrentConfig IsNot Nothing, _getCurrentConfig.Invoke(), _config)
|
||||
End Function
|
||||
|
||||
'// Verifica si el nivel de registro está habilitado.
|
||||
Public Function IsEnabled(logLevel As LogLevel) As Boolean Implements ILogger.IsEnabled
|
||||
Return logLevel >= GetCurrentConfiguration().MinimumLogLevel
|
||||
End Function
|
||||
|
||||
'// Registra un mensaje con la configuración dada.
|
||||
Public Sub Log(Of TState)(logLevel As LogLevel, eventId As EventId, state As TState, exception As Exception, formatter As Func(Of TState, Exception, String)) Implements ILogger.Log
|
||||
Try
|
||||
Dim config As TsLoggerConfiguration = GetCurrentConfiguration() '// Obtener la configuración.
|
||||
If Not IsEnabled(logLevel) Then Return
|
||||
|
||||
'// Obtener la información del archivo de código fuente si está habilitado.
|
||||
Dim sourceInfo As String = ""
|
||||
If config.IncludeSourceInfo Then
|
||||
Dim stackTrace As New Diagnostics.StackTrace(True)
|
||||
Dim frame As Diagnostics.StackFrame = stackTrace.GetFrame(1)
|
||||
Dim fileName As String = frame.GetFileName()
|
||||
Dim method As String = frame.GetMethod().Name
|
||||
Dim line As Integer = frame.GetFileLineNumber()
|
||||
sourceInfo = $" [Archivo: {fileName}, Método: {method}, Línea: {line}]"
|
||||
End If
|
||||
|
||||
'// Mensaje básico sin la fecha y hora.
|
||||
Dim basicMessage As String = $"[{eventId.Id,2}: {logLevel,-12}] {_name} - {formatter(state, exception)}{sourceInfo}"
|
||||
'// Agregar la fecha y hora actual al inicio del mensaje para consola y archivo.
|
||||
Dim timestamp As String = DateTime.Now.ToString("yyyy-MM-dd_HH·mm·sszz")
|
||||
Dim messageWithTimestamp As String = $"{timestamp} {basicMessage}"
|
||||
|
||||
'// Registrar en la consola si está habilitado.
|
||||
If config.LogToConsole Then
|
||||
Console.ForegroundColor = config.LogLevelToColorMap(logLevel)
|
||||
Console.WriteLine(messageWithTimestamp)
|
||||
End If
|
||||
|
||||
'// Registrar en la salida de depuración si está habilitado.
|
||||
If config.LogToDebug Then
|
||||
Debug.WriteLine(basicMessage)
|
||||
End If
|
||||
|
||||
'// Registrar en un archivo si está habilitado.
|
||||
If config.LogToFile Then
|
||||
If String.IsNullOrEmpty(config.LogFilePath) Then
|
||||
Debug.WriteLine($"La ruta del archivo de registro no está especificada. Se omite el registro en archivos para el mensaje: {basicMessage}")
|
||||
Else
|
||||
Try
|
||||
'// Intentar crear el directorio si no existe.
|
||||
Directory.CreateDirectory(config.LogFilePath)
|
||||
Dim folderPath As String = Path.Combine(config.LogFilePath, DateTime.Now.ToString("yyyy\\MM"))
|
||||
Directory.CreateDirectory(folderPath)
|
||||
|
||||
Dim fileName As String = $"{DateTime.Now:yyyy-MM-dd_HH·mm·sszz}_{_name}.log"
|
||||
Dim filePath As String = Path.Combine(folderPath, fileName)
|
||||
|
||||
Using writer As New StreamWriter(filePath, append:=True)
|
||||
writer.WriteLine(messageWithTimestamp)
|
||||
End Using
|
||||
Catch ex As IOException
|
||||
Debug.WriteLine($"Error al intentar crear o acceder a la ruta del archivo de registro '{config.LogFilePath}'. Error: {ex}")
|
||||
End Try
|
||||
End If
|
||||
End If
|
||||
|
||||
'// Enviar notificación a Pushover si está habilitado.
|
||||
If config.LogToPushover AndAlso logLevel >= config.PushoverMinimumLogLevel Then
|
||||
Dim parameters As New Dictionary(Of String, String) From {
|
||||
{"token", "a42g7oaz2t4u7unbdg5nm7qaqocht6"},
|
||||
{"user", "uxzAV6NcPoxkAGLSNWSsZX9SfPeUo5"},
|
||||
{"message", basicMessage},
|
||||
{"title", $"{_name}"}, '// Utilizar el nombre del registrador como título.
|
||||
{"priority", GetPushoverPriority(logLevel)} '// Establecer la prioridad en función del nivel de registro.
|
||||
}
|
||||
If config.NetworkInSeparateThread Then
|
||||
Task.Run(Sub()
|
||||
Using client As New HttpClient()
|
||||
Dim response = client.PostAsync("https://api.pushover.net/1/messages.json", New FormUrlEncodedContent(parameters)).Result
|
||||
Debug.WriteLine(response.ToString)
|
||||
End Using
|
||||
End Sub)
|
||||
Else
|
||||
Using client As New HttpClient()
|
||||
Dim response = client.PostAsync("https://api.pushover.net/1/messages.json", New FormUrlEncodedContent(parameters)).Result
|
||||
Debug.WriteLine(response.ToString)
|
||||
End Using
|
||||
End If
|
||||
End If
|
||||
|
||||
'// Enviar notificación a Slack si está habilitado.
|
||||
If config.LogToSlack Then
|
||||
If config.NetworkInSeparateThread Then
|
||||
Task.Run(Sub()
|
||||
tsl5.Utilidades.EnviarNotificacionSlack(basicMessage, otroTexto:=timestamp, descripcionRemitente:=$"TsLogger {_name}", destinatario:=config.SlackDestination)
|
||||
End Sub)
|
||||
Else
|
||||
tsl5.Utilidades.EnviarNotificacionSlack(basicMessage, otroTexto:=timestamp, descripcionRemitente:=$"TsLogger {_name}", destinatario:=config.SlackDestination)
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Debug.WriteLine($"Excepción en TsLogger: {ex}")
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'// Implementación básica de BeginScope (no se necesita un manejo detallado de alcance en esta implementación).
|
||||
Private Function ILogger_BeginScope(Of TState)(state As TState) As IDisposable Implements ILogger.BeginScope
|
||||
Return New EmptyDisposable()
|
||||
End Function
|
||||
|
||||
'// Clase auxiliar para cumplir con la interfaz IDisposable requerida por BeginScope.
|
||||
Private Class EmptyDisposable
|
||||
Implements IDisposable
|
||||
Public Sub Dispose() Implements IDisposable.Dispose
|
||||
'// No se requiere ninguna acción aquí.
|
||||
End Sub
|
||||
End Class
|
||||
' Método auxiliar para convertir el nivel de registro en una prioridad para Pushover.
|
||||
Private Function GetPushoverPriority(logLevel As LogLevel) As String
|
||||
Select Case logLevel
|
||||
Case LogLevel.Critical
|
||||
Return "1" ' Prioridad alta
|
||||
Case LogLevel.Error
|
||||
Return "1" ' Prioridad alta
|
||||
Case LogLevel.Warning
|
||||
Return "0" ' Prioridad normal
|
||||
Case LogLevel.Information
|
||||
Return "-1" ' Prioridad baja
|
||||
Case LogLevel.Debug
|
||||
Return "-1" ' Prioridad baja
|
||||
Case LogLevel.Trace
|
||||
Return "-2" ' Prioridad mínima
|
||||
Case Else
|
||||
Return "0" ' Prioridad normal
|
||||
End Select
|
||||
End Function
|
||||
End Class
|
||||
|
||||
Reference in New Issue
Block a user