Agregar archivos de proyecto.

This commit is contained in:
2026-05-14 09:52:12 +02:00
parent 3a8fc53e4e
commit f8102dd7f1
78 changed files with 34070 additions and 0 deletions

218
TsLogger.vb Normal file
View 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