diff --git a/tsNotificacionesClient.vb b/tsNotificacionesClient.vb index bcba859..a6c7e86 100644 --- a/tsNotificacionesClient.vb +++ b/tsNotificacionesClient.vb @@ -5,9 +5,29 @@ Imports System.Net.Http Imports System.Net.Http.Headers Imports System.Net.Http.Json Imports Microsoft.Extensions.Configuration +Imports Microsoft.Extensions.Logging +Imports System.Diagnostics Public Class TsNotificacionesClient + ' ============================================================ + ' LOGGER MULTIPLATAFORMA (Windows → EventLog, Linux → journald) + ' ============================================================ + Private NotInheritable Class LogProvider + Private Shared ReadOnly _factory As ILoggerFactory = LoggerFactory.Create( + Sub(builder) + builder.AddConsole() ' Linux → journald + builder.AddEventLog() ' Windows → Event Viewer + End Sub) + + Public Shared Function CreateLogger(Of T)() As ILogger(Of T) + Return _factory.CreateLogger(Of T)() + End Function + End Class + + ' ============================================================ + ' CAMPOS DE INSTANCIA + ' ============================================================ Private ReadOnly _http As HttpClient Private ReadOnly _idAplicacion As Integer @@ -15,64 +35,132 @@ Public Class TsNotificacionesClient _idAplicacion = idAplicacion ServicePointManager.ServerCertificateValidationCallback = Function(s, c, ch, e) True ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 Or SecurityProtocolType.Tls11 + _http = New HttpClient() With {.BaseAddress = New Uri(baseUrl)} _http.DefaultRequestHeaders.Add("X-Api-Key", apiKey) End Sub - Public Shared Async Function RegistrarAsync(titulo As String, descripcion As String, TipoNotificacion As TipoNotificacionEnum, Optional Fichero As Byte() = Nothing) As Task + ' ============================================================ + ' MÉTODO PRINCIPAL: REGISTRAR NOTIFICACIÓN + ' ============================================================ + Public Shared Async Function RegistrarAsync(titulo As String, descripcion As String, TipoNotificacion As TipoNotificacionEnum, Optional Fichero As Byte() = Nothing, Optional IncluirMensajeEnLogDelSistema As Boolean = True) As Task Try + Dim logger = LogProvider.CreateLogger(Of TsNotificacionesClient)() + ServicePointManager.ServerCertificateValidationCallback = Function(s, c, ch, e) True ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 Or SecurityProtocolType.Tls11 - 'Dim baseUrl = ConfigurationManager.AppSettings("TsNotificaciones:ApiUrl") - 'Dim idAplicacion = Integer.Parse(ConfigurationManager.AppSettings("TsNotificaciones:IdAplicacion")) - 'Dim apiKey = ConfigurationManager.AppSettings("TsNotificaciones:ApiKey") - 'Dim http = New HttpClient() With {.BaseAddress = New Uri(baseUrl)} - 'Dim NombreServidor = ConfigurationManager.AppSettings("TsNotificaciones:ApiKey") - 'If NombreServidor = "" Then NombreServidor = System.Environment.MachineName + Dim config = New ConfigurationBuilder(). + SetBasePath(Directory.GetCurrentDirectory()). + AddJsonFile("appsettings.json", [optional]:=False). + Build() - Dim config = New ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", [optional]:=False).Build() Dim apiUrl = If(config("TsNotificaciones:ApiUrl"), "http://localhost:7159") Dim idAplicacion = Integer.Parse(If(config("TsNotificaciones:IdAplicacion"), "1")) + Dim Origen = If(config("TsNotificaciones:Origen"), "Tecnosis") + Dim Aplicacion = If(config("TsNotificaciones:Aplicacion"), idAplicacion.ToString) Dim apiKey = If(config("TsNotificaciones:ApiKey"), String.Empty) Dim nombreServidor = If(config("TsNotificaciones:NombreServidor"), Environment.MachineName) + + Dim EsWindows = OperatingSystem.IsWindows() + + If IncluirMensajeEnLogDelSistema Then + + ' ============================================================ + ' LOGGING MULTIPLATAFORMA + ' ============================================================ + If EsWindows Then + ' --- WINDOWS: Event Viewer --- + If Not EventLog.SourceExists(Origen) Then + EventLog.CreateEventSource(Origen, Aplicacion) + End If + + Dim ele As EventLogEntryType + Select Case TipoNotificacion + Case TipoNotificacionEnum.INFO + ele = EventLogEntryType.Information + Case TipoNotificacionEnum.ADVERTENCIA + ele = EventLogEntryType.Warning + Case TipoNotificacionEnum.ERROR, TipoNotificacionEnum.CRÍTICO + ele = EventLogEntryType.Error + End Select + + EventLog.WriteEntry(Origen, $"{titulo} {descripcion}", ele) + + Else + ' --- LINUX: ILogger → journald --- + Select Case TipoNotificacion + Case TipoNotificacionEnum.INFO + logger.LogInformation($"{titulo} {descripcion}") + Case TipoNotificacionEnum.ADVERTENCIA + logger.LogWarning($"{titulo} {descripcion}") + Case TipoNotificacionEnum.ERROR, TipoNotificacionEnum.CRÍTICO + logger.LogError($"{titulo} {descripcion}") + End Select + End If + End If + + ' ============================================================ + ' LLAMADA A LA API + ' ============================================================ Dim http = New HttpClient() With {.BaseAddress = New Uri(apiUrl)} Dim Tipo = CInt(TipoNotificacion) Dim request = New HttpRequestMessage(HttpMethod.Post, "/api/alertas/registrar") request.Headers.Add("X-Api-Key", apiKey) + Dim ipServidor As String = ObtenerIp() - request.Content = JsonContent.Create(New With {idAplicacion, nombreServidor, ipServidor, titulo, descripcion, Tipo}) + + request.Content = JsonContent.Create(New With { + idAplicacion, + nombreServidor, + ipServidor, + titulo, + descripcion, + Tipo + }) + Dim response = Await http.SendAsync(request) Dim body As System.Text.Json.JsonElement = Await response.Content.ReadFromJsonAsync(Of System.Text.Json.JsonElement)() Dim id = body.GetProperty("id").GetInt32() + If Fichero IsNot Nothing Then Await SubirFichero(http, apiKey, id, Fichero) End If + Catch ex As Exception Throw New Exception(ex.Message, ex) End Try End Function + ' ============================================================ + ' SUBIR FICHERO + ' ============================================================ Private Shared Async Function SubirFichero(ByVal http As HttpClient, ByVal apiKey As String, ByVal alertaId As Integer, ByVal datos As Byte()) As Task Try Dim fileContent = New ByteArrayContent(datos) fileContent.Headers.ContentType = New MediaTypeHeaderValue("image/png") + Dim multipart = New MultipartFormDataContent() multipart.Add(fileContent, "archivo", "Imagen.png") + Dim request = New HttpRequestMessage(HttpMethod.Post, $"/api/alertas/{alertaId}/archivo") request.Headers.Add("X-Api-Key", apiKey) request.Content = multipart + Dim response = Await http.SendAsync(request) - Dim ok As Boolean = response.IsSuccessStatusCode - If Not ok Then Throw New Exception($"Subida fallida ({response.StatusCode}): {Await response.Content.ReadAsStringAsync()}") + If Not response.IsSuccessStatusCode Then + Throw New Exception($"Subida fallida ({response.StatusCode}): {Await response.Content.ReadAsStringAsync()}") + End If + Catch httpEx As Exception - Throw New Exception + Throw New Exception(httpEx.Message, httpEx) End Try End Function - - + ' ============================================================ + ' OBTENER IP + ' ============================================================ Private Shared Function ObtenerIp() As String For Each addr In Dns.GetHostAddresses(Dns.GetHostName()) If addr.AddressFamily = Sockets.AddressFamily.InterNetwork Then Return addr.ToString() @@ -80,13 +168,14 @@ Public Class TsNotificacionesClient Return "127.0.0.1" End Function - 'Private Shared Function EscaparJson(s As String) As String - ' Return s.Replace("\", "\\").Replace("""", "\""").Replace(vbCr, "\r").Replace(vbLf, "\n") - 'End Function + ' ============================================================ + ' ENUMERACIÓN + ' ============================================================ Public Enum TipoNotificacionEnum INFO = 0 ADVERTENCIA = 1 [ERROR] = 2 CRÍTICO = 3 End Enum -End Class \ No newline at end of file + +End Class diff --git a/tsUtilidades.vbproj b/tsUtilidades.vbproj index 17a21f1..5e1c53f 100644 --- a/tsUtilidades.vbproj +++ b/tsUtilidades.vbproj @@ -16,11 +16,12 @@ net8.0 tsUtilidades net8.0, libreria - 1.1.10 + 1.1.11 Manuel Tecnosis S.A Utilidades Varias + - 2026-04-28 1.1.11 Se añade log del sistema a tsNotificacionesClient - 2026-04-10 1.1.10 Se corrige tsNotificacionesClient - 2026-04-10 1.1.9 Se corrige tsNotificacionesClient - 2026-04-09 1.1.8 Se añade la clase tsNotificacionesClient