fix: forçar log no webhook e no program.cs
All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 2s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Build and Push Image (push) Successful in 15m3s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Successful in 1m28s
BCards Deployment Pipeline / Deploy to Staging (x86 - Local) (push) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 0s

This commit is contained in:
Ricardo Carneiro 2025-09-08 19:19:18 -03:00
parent c825fa2736
commit fa422ef685

View File

@ -51,80 +51,60 @@ if (isDevelopment)
.MinimumLevel.Override("Microsoft.AspNetCore.Routing", LogEventLevel.Information) .MinimumLevel.Override("Microsoft.AspNetCore.Routing", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning) .MinimumLevel.Override("System", LogEventLevel.Warning)
// Console sempre ativo - logs garantidos
.WriteTo.Console( .WriteTo.Console(
restrictedToMinimumLevel: LogEventLevel.Information, restrictedToMinimumLevel: LogEventLevel.Debug,
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{Hostname}] {Message:lj} {Properties:j}{NewLine}{Exception}"); outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
// Arquivo local com rotação para Docker logs não ficarem enormes
.WriteTo.File(
"./logs/bcards-dev-.log",
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 2, // Só 2 dias como você quer
restrictedToMinimumLevel: LogEventLevel.Debug,
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}");
var openSearchUrl = builder.Configuration["Serilog:OpenSearchUrl"]; var openSearchUrl = builder.Configuration["Serilog:OpenSearchUrl"];
if (!string.IsNullOrEmpty(openSearchUrl)) if (!string.IsNullOrEmpty(openSearchUrl))
{ {
var indexFormat = "b-cards-dev-{0:yyyy-MM}"; var indexFormat = "b-cards-dev-{0:yyyy-MM}";
Console.WriteLine($"[DEBUG] Configurando OpenSearch HTTP (SEM AUTENTICAÇÃO):");
Console.WriteLine($"[DEBUG] URL: {openSearchUrl}");
Console.WriteLine($"[DEBUG] Index Format: {indexFormat}");
Console.WriteLine($"[DEBUG] Protocol: {(openSearchUrl.StartsWith("https") ? "HTTPS" : "HTTP")}");
try try
{ {
loggerConfig.WriteTo.OpenSearch(new OpenSearchSinkOptions(new Uri(openSearchUrl)) // OpenSearch configurado para ser MUITO agressivo no envio
loggerConfig.WriteTo.Async(a => a.OpenSearch(new OpenSearchSinkOptions(new Uri(openSearchUrl))
{ {
IndexFormat = indexFormat, IndexFormat = indexFormat,
AutoRegisterTemplate = true, AutoRegisterTemplate = true,
BufferBaseFilename = "./logs/buffer", BufferBaseFilename = "./logs/opensearch-buffer", // Buffer em disco
// 🔥 REMOVIDO: BasicAuthentication - SEM AUTENTICAÇÃO
ModifyConnectionSettings = conn => conn ModifyConnectionSettings = conn => conn
.RequestTimeout(TimeSpan.FromSeconds(30)) .RequestTimeout(TimeSpan.FromSeconds(8))
.PingTimeout(TimeSpan.FromSeconds(10)) .PingTimeout(TimeSpan.FromSeconds(4)),
.ThrowExceptions(true)
.OnRequestCompleted(details =>
{
if (details.Success)
{
Console.WriteLine($"[OPENSEARCH] ✅ Request OK: {details.HttpMethod} {details.Uri} - Status: {details.HttpStatusCode}");
}
else
{
Console.WriteLine($"[OPENSEARCH] ❌ Request FAILED: {details.HttpMethod} {details.Uri}");
Console.WriteLine($"[OPENSEARCH] Status: {details.HttpStatusCode}");
Console.WriteLine($"[OPENSEARCH] Exception: {details.OriginalException?.Message}");
if (details.ResponseBodyInBytes != null && details.ResponseBodyInBytes.Length > 0)
{
var responseBody = System.Text.Encoding.UTF8.GetString(details.ResponseBodyInBytes);
Console.WriteLine($"[OPENSEARCH] Response: {responseBody}");
}
}
}),
MinimumLogEventLevel = LogEventLevel.Debug, MinimumLogEventLevel = LogEventLevel.Debug,
EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog, EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog,
RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway, RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
BatchPostingLimit = 5, // Muito pequeno para debug BatchPostingLimit = 10, // Lotes pequenos = envio mais frequente
Period = TimeSpan.FromSeconds(2), Period = TimeSpan.FromSeconds(2), // Envia a cada 2 segundos
// 🔥 CORRIGIDO: Dictionary<string, string> // Configurações para máxima persistência
BufferRetainedInvalidPayloadsLimitBytes = 100 * 1024 * 1024, // 100MB buffer
BufferLogShippingInterval = TimeSpan.FromSeconds(1), // Tenta reenviar rapidamente
TemplateCustomSettings = new Dictionary<string, string> TemplateCustomSettings = new Dictionary<string, string>
{ {
{"number_of_shards", "1"}, {"number_of_shards", "1"},
{"number_of_replicas", "0"}, {"number_of_replicas", "0"}
{"index.mapping.total_fields.limit", "2000"}
} }
}); }),
bufferSize: 10000, // Buffer grande na memória
Console.WriteLine($"[DEBUG] ✅ Serilog configurado para OpenSearch HTTP!"); blockWhenFull: false); // Nunca bloquear aplicação
} }
catch (Exception ex) catch (Exception)
{ {
Console.WriteLine($"[ERROR] ❌ Falha ao configurar OpenSearch: {ex.Message}"); // Falha silenciosa - logs continuam no console e arquivo
Console.WriteLine($"[ERROR] Stack trace: {ex.StackTrace}");
} }
} }
else
{
Console.WriteLine("[WARNING] OpenSearchUrl não configurada!");
}
} }
else else
{ {
// PRODUÇÃO: Mesma lógica sem autenticação // PRODUÇÃO permanece igual, mas também com fallback garantido
loggerConfig loggerConfig
.MinimumLevel.Information() .MinimumLevel.Information()
.MinimumLevel.Override("Microsoft.AspNetCore.Hosting.Diagnostics", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft.AspNetCore.Hosting.Diagnostics", LogEventLevel.Warning)
@ -132,9 +112,10 @@ else
.MinimumLevel.Override("Microsoft.AspNetCore.StaticFiles", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft.AspNetCore.StaticFiles", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning) .MinimumLevel.Override("System", LogEventLevel.Warning)
// 🔥 GARANTIR CONSOLE EM PRODUÇÃO TAMBÉM
.WriteTo.Console( .WriteTo.Console(
restrictedToMinimumLevel: LogEventLevel.Information, restrictedToMinimumLevel: LogEventLevel.Information,
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] [{Hostname}] {Message:lj}{NewLine}{Exception}") outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.WriteTo.File( .WriteTo.File(
"/app/logs/bcards-.log", "/app/logs/bcards-.log",
rollingInterval: RollingInterval.Day, rollingInterval: RollingInterval.Day,
@ -156,44 +137,38 @@ else
var indexFormat = $"b-cards-{envMapping}-{{0:yyyy-MM}}"; var indexFormat = $"b-cards-{envMapping}-{{0:yyyy-MM}}";
loggerConfig.WriteTo.Async(a => a.OpenSearch(new OpenSearchSinkOptions(new Uri(openSearchUrl)) try
{ {
IndexFormat = indexFormat, loggerConfig.WriteTo.Async(a => a.OpenSearch(new OpenSearchSinkOptions(new Uri(openSearchUrl))
AutoRegisterTemplate = false, {
BufferBaseFilename = "./logs/buffer", IndexFormat = indexFormat,
// 🔥 SEM AUTENTICAÇÃO EM PRODUÇÃO TAMBÉM AutoRegisterTemplate = false,
ModifyConnectionSettings = conn => conn BufferBaseFilename = "./logs/buffer",
.RequestTimeout(TimeSpan.FromSeconds(30)) ModifyConnectionSettings = conn => conn
.PingTimeout(TimeSpan.FromSeconds(10)) .RequestTimeout(TimeSpan.FromSeconds(30))
.ServerCertificateValidationCallback((o, certificate, chain, errors) => true), .PingTimeout(TimeSpan.FromSeconds(10)),
MinimumLogEventLevel = LogEventLevel.Information, MinimumLogEventLevel = LogEventLevel.Information,
EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog, EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog,
RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway, RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
BatchPostingLimit = 50, BatchPostingLimit = 50,
Period = TimeSpan.FromSeconds(5), Period = TimeSpan.FromSeconds(5),
}), bufferSize: 10000); }), bufferSize: 10000, blockWhenFull: false);
}
catch (Exception)
{
// Falha silenciosa em produção - logs continuam no console/arquivo
}
} }
} }
// 🔥 LOGS DE TESTE MAIS AGRESSIVOS // 🔥 REMOVER OS Task.Delay E Log.CloseAndFlush desnecessários
var logger = loggerConfig.CreateLogger(); var logger = loggerConfig.CreateLogger();
Log.Logger = logger; Log.Logger = logger;
Console.WriteLine($"[STARTUP] {DateTime.Now:HH:mm:ss} - Testando logs SEM AUTENTICAÇÃO..."); Console.WriteLine($"[STARTUP] {DateTime.Now:HH:mm:ss} - Logger configurado");
Log.Information("=== TESTE DE LOG SEM AUTH ==="); Log.Information("=== APLICAÇÃO INICIANDO ===");
Log.Information("Aplicação BCards iniciando em {Environment} no host {Hostname}", Log.Information("BCards iniciando em {Environment} no host {Hostname}",
builder.Environment.EnvironmentName, hostname); builder.Environment.EnvironmentName, hostname);
Log.Warning("Log de WARNING - teste OpenSearch HTTP");
Log.Error("Log de ERROR - forçando envio imediato");
Log.Debug("Log de DEBUG - verificando conectividade");
// Force flush para garantir que logs sejam enviados
//Log.CloseAndFlush();
await Task.Delay(5000); // Aguardar mais tempo
// Recriar logger após flush
//Log.Logger = loggerConfig.CreateLogger();
Console.WriteLine($"[STARTUP] {DateTime.Now:HH:mm:ss} - Teste de logs concluído");
// Use Serilog for the host // Use Serilog for the host
builder.Host.UseSerilog(); builder.Host.UseSerilog();