fix: ajustes diversos
This commit is contained in:
parent
49da9f874a
commit
5ba0d62595
20
.github/workflows/deploy.yml
vendored
20
.github/workflows/deploy.yml
vendored
@ -104,7 +104,6 @@ jobs:
|
||||
--restart unless-stopped \
|
||||
-p 5000:8080 \
|
||||
--add-host=host.docker.internal:host-gateway \
|
||||
-e Serilog__SeqUrl="http://host.docker.internal:5343" \
|
||||
-e ASPNETCORE_ENVIRONMENT=Staging \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:develop
|
||||
EOF
|
||||
@ -127,7 +126,6 @@ jobs:
|
||||
--restart unless-stopped \
|
||||
-p 5000:8080 \
|
||||
--add-host=host.docker.internal:host-gateway \
|
||||
-e Serilog__SeqUrl="http://host.docker.internal:5342" \
|
||||
-e ASPNETCORE_ENVIRONMENT=Staging \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:develop
|
||||
EOF
|
||||
@ -172,14 +170,19 @@ jobs:
|
||||
# Puxa nova imagem
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
# Cria o diretório de chaves no host e define as permissões corretas
|
||||
sudo mkdir -p /app/keys
|
||||
sudo chown -R 1000:1000 /app/keys
|
||||
|
||||
# Executa novo container
|
||||
docker run -d \
|
||||
--name qrrapido-prod \
|
||||
--restart unless-stopped \
|
||||
-p 5001:8080 \
|
||||
--network host \
|
||||
-v /app/keys:/app/keys \
|
||||
-e ASPNETCORE_ENVIRONMENT=Production \
|
||||
-e ASPNETCORE_URLS=http://+:8080 \
|
||||
-e ASPNETCORE_URLS=http://+:5001 \
|
||||
-e Serilog__OpenSearchUrl="http://localhost:9201" \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
# Recarrega NGINX para garantir que está apontando para o novo container
|
||||
@ -198,14 +201,19 @@ jobs:
|
||||
# Puxa nova imagem
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
# Cria o diretório de chaves no host e define as permissões corretas
|
||||
sudo mkdir -p /app/keys
|
||||
sudo chown -R 1000:1000 /app/keys
|
||||
|
||||
# Executa novo container
|
||||
docker run -d \
|
||||
--name qrrapido-prod \
|
||||
--restart unless-stopped \
|
||||
-p 5001:8080 \
|
||||
--network host \
|
||||
-v /app/keys:/app/keys \
|
||||
-e ASPNETCORE_ENVIRONMENT=Production \
|
||||
-e ASPNETCORE_URLS=http://+:8080 \
|
||||
-e ASPNETCORE_URLS=http://+:5001 \
|
||||
-e Serilog__OpenSearchUrl="http://localhost:9202" \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
EOF
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -352,6 +352,7 @@ MigrationBackup/
|
||||
FodyWeavers.xsd
|
||||
|
||||
# Custom
|
||||
keys/
|
||||
appsettings.Local.json
|
||||
appsettings.Production.json
|
||||
*.Development.json
|
||||
|
||||
@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
|
||||
namespace QRRapidoApp.Controllers
|
||||
{
|
||||
@ -14,7 +15,7 @@ namespace QRRapidoApp.Controllers
|
||||
private readonly ILogger<HealthController> _logger;
|
||||
private readonly string _applicationName;
|
||||
private readonly string _version;
|
||||
private static readonly DateTime _startTime = DateTime.UtcNow;
|
||||
private static readonly DateTime _startTime = System.Diagnostics.Process.GetCurrentProcess().StartTime.ToUniversalTime();
|
||||
|
||||
public HealthController(
|
||||
HealthCheckService healthCheckService,
|
||||
@ -228,13 +229,17 @@ namespace QRRapidoApp.Controllers
|
||||
// For Uptime Kuma, we want to return 200 OK for healthy/degraded and 503 for unhealthy
|
||||
var statusCode = overallStatus == "unhealthy" ? 503 : 200;
|
||||
|
||||
var uptimeMinutes = (DateTime.UtcNow - _startTime).TotalMinutes;
|
||||
var memoryBytes = GC.GetTotalMemory(false);
|
||||
var memoryMB = memoryBytes / 1024.0 / 1024.0;
|
||||
|
||||
var response = new
|
||||
{
|
||||
status = overallStatus,
|
||||
application = _applicationName,
|
||||
version = _version,
|
||||
timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"),
|
||||
uptime = $"{(DateTime.UtcNow - _startTime).TotalHours:F1}h",
|
||||
uptime = System.FormattableString.Invariant($"{(DateTime.UtcNow - _startTime).TotalHours:F1}h"),
|
||||
// Include critical metrics for monitoring
|
||||
metrics = new
|
||||
{
|
||||
@ -245,6 +250,14 @@ namespace QRRapidoApp.Controllers
|
||||
}
|
||||
};
|
||||
|
||||
_logger.LogInformation("[HEALTH] Memory: {memoryBytes} MemoryMB: {memoryMB} ThreadPool: {threadPool} ProcessId: {processId} ActiveConnections: {activeConnections} UptimeMinutes: {uptimeMinutes}",
|
||||
memoryBytes,
|
||||
memoryMB,
|
||||
ThreadPool.ThreadCount,
|
||||
Process.GetCurrentProcess().Id,
|
||||
HttpContext.Connection?.Id ?? "null",
|
||||
Math.Round(uptimeMinutes, 1));
|
||||
|
||||
return StatusCode(statusCode, response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
67
Program.cs
67
Program.cs
@ -17,6 +17,7 @@ using Stripe;
|
||||
using System.Globalization;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Serilog.Sinks.OpenSearch;
|
||||
using Serilog.Sinks.SystemConsole.Themes;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
@ -25,23 +26,71 @@ using Microsoft.AspNetCore.RateLimiting;
|
||||
using System.Threading.RateLimiting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
// Fix for WSL path issues - disable StaticWebAssets completely
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
Args = args,
|
||||
ContentRootPath = Directory.GetCurrentDirectory(),
|
||||
WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")
|
||||
};
|
||||
|
||||
// Disable StaticWebAssets for WSL compatibility
|
||||
Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUP__STATICWEBASSETS__ENABLED", "false");
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
// Configure Serilog
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
var loggerConfig = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(builder.Configuration)
|
||||
.Enrich.FromLogContext()
|
||||
.Enrich.WithEnvironmentName()
|
||||
.Enrich.WithProcessId()
|
||||
.Enrich.WithThreadId()
|
||||
.Enrich.WithProperty("ApplicationName", builder.Configuration["ApplicationName"] ?? "QRRapido")
|
||||
.Enrich.WithProperty("Environment", "Dev")
|
||||
.Enrich.WithProperty("Environment", builder.Environment.EnvironmentName)
|
||||
.WriteTo.Async(a => a.Console(
|
||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}",
|
||||
theme: AnsiConsoleTheme.Code))
|
||||
.WriteTo.Async(a => a.Seq(builder.Configuration["Serilog:SeqUrl"],
|
||||
apiKey: builder.Configuration["Serilog:ApiKey"]=="" ? null : builder.Configuration["Serilog:ApiKey"]))
|
||||
.CreateLogger();
|
||||
theme: AnsiConsoleTheme.Code));
|
||||
|
||||
var openSearchUrl = builder.Configuration["Serilog:OpenSearchUrl"];
|
||||
if (!string.IsNullOrEmpty(openSearchUrl))
|
||||
{
|
||||
var environment = builder.Environment.EnvironmentName.ToLower();
|
||||
var envMapping = environment switch
|
||||
{
|
||||
"Production" => "prod",
|
||||
"Staging" => "staging",
|
||||
"Development" => "dev",
|
||||
_ => environment
|
||||
};
|
||||
|
||||
var indexFormat = $"qrrapido-logs-{envMapping}-{{0:yyyy-MM-dd}}";
|
||||
|
||||
try
|
||||
{
|
||||
loggerConfig.WriteTo.Async(a => a.OpenSearch(new OpenSearchSinkOptions(new Uri(openSearchUrl))
|
||||
{
|
||||
IndexFormat = indexFormat,
|
||||
AutoRegisterTemplate = true,
|
||||
BufferBaseFilename = "./logs/buffer",
|
||||
ModifyConnectionSettings = conn => conn
|
||||
.RequestTimeout(TimeSpan.FromSeconds(30))
|
||||
.PingTimeout(TimeSpan.FromSeconds(10)),
|
||||
MinimumLogEventLevel = LogEventLevel.Information,
|
||||
EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog,
|
||||
RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
|
||||
BatchPostingLimit = 50,
|
||||
Period = TimeSpan.FromSeconds(5),
|
||||
}), bufferSize: 10000, blockWhenFull: false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Fails silently, logs will continue on console.
|
||||
loggerConfig.WriteTo.Console(outputTemplate: $"Error setting up OpenSearch sink: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
Log.Logger = loggerConfig.CreateLogger();
|
||||
|
||||
builder.Host.UseSerilog();
|
||||
|
||||
@ -89,8 +138,10 @@ builder.Services.AddMemoryCache();
|
||||
builder.Services.AddSingleton<IDistributedCache, MemoryDistributedCacheWrapper>();
|
||||
|
||||
// ✅ DataProtection compartilhado via FileSystem (ADICIONAR APÓS O CACHE)
|
||||
var keysDirectory = Path.Combine(Directory.GetCurrentDirectory(), "keys");
|
||||
Directory.CreateDirectory(keysDirectory);
|
||||
builder.Services.AddDataProtection()
|
||||
.PersistKeysToFileSystem(new DirectoryInfo("/app/keys"))
|
||||
.PersistKeysToFileSystem(new DirectoryInfo(keysDirectory))
|
||||
.SetApplicationName("QRRapido");
|
||||
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.1-dev-00953" />
|
||||
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.OpenSearch" Version="1.3.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" />
|
||||
<PackageReference Include="Stripe.net" Version="48.4.0" />
|
||||
|
||||
@ -137,22 +137,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="d-grid opacity-controlled disabled-state" id="next-button-group">
|
||||
<button type="button" class="btn btn-success" id="next-btn">
|
||||
<i class="fas fa-arrow-right"></i> Personalizar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="d-grid opacity-controlled disabled-state" id="button-gerar-quick-div">
|
||||
<button type="submit" class="btn btn-primary" id="generate-quick-btn">
|
||||
<i class="fas fa-qrcode"></i> Gerar Rápido
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dynamic QR Section (Premium) -->
|
||||
<div id="dynamic-qr-section" style="display: none;" class="opacity-controlled disabled-state">
|
||||
@ -520,6 +504,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Buttons (Global - appears for all QR types) -->
|
||||
<div class="row mb-4 opacity-controlled disabled-state" id="navigation-buttons">
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="d-grid opacity-controlled disabled-state" id="next-button-group">
|
||||
<button type="button" class="btn btn-success" id="next-btn">
|
||||
<i class="fas fa-arrow-right"></i> Personalizar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="d-grid opacity-controlled disabled-state" id="button-gerar-quick-div">
|
||||
<button type="submit" class="btn btn-primary" id="generate-quick-btn">
|
||||
<i class="fas fa-qrcode"></i> Gerar Rápido
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Advanced customization (collapsible) -->
|
||||
<div class="accordion mb-3 opacity-controlled disabled-state" id="customization-accordion">
|
||||
<div class="accordion-item">
|
||||
@ -1305,6 +1307,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
new SimpleOpacityController('#qr-type', '#wifi-interface');
|
||||
new SimpleOpacityController('#qr-type', '#sms-interface');
|
||||
new SimpleOpacityController('#qr-type', '#email-interface');
|
||||
new SimpleOpacityController('#qr-type', '#navigation-buttons');
|
||||
new SimpleOpacityController('#qr-type', '#customization-accordion');
|
||||
new SimpleOpacityController('#qr-type', '#button-gerar-div');
|
||||
|
||||
|
||||
@ -59,8 +59,7 @@
|
||||
"ApplicationName": "QRRapido",
|
||||
"Environment": "Personal",
|
||||
"Serilog": {
|
||||
"SeqUrl": "http://172.17.0.1:5341",
|
||||
"ApiKey": "",
|
||||
"OpenSearchUrl": "http://localhost:9200",
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user