Updated deploy script, and reduced logging noise
This commit is contained in:
@@ -7,3 +7,6 @@ POSTGRES_PASSWORD=changeme
|
|||||||
|
|
||||||
# Note: client OIDC values live in src/Budget.Client/.env (committed).
|
# Note: client OIDC values live in src/Budget.Client/.env (committed).
|
||||||
# Override locally in src/Budget.Client/.env.local (gitignored).
|
# Override locally in src/Budget.Client/.env.local (gitignored).
|
||||||
|
|
||||||
|
# Trusted reverse-proxy networks (comma-separated CIDRs). Default covers the Docker bridge range.
|
||||||
|
# Budget__TrustedProxyNetworks=172.16.0.0/12
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|||||||
docker push $image
|
docker push $image
|
||||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
|
||||||
ssh stwaddle_com "cd stwaddlecom && docker compose up -d --pull always budget"
|
ssh stwaddle_com "cd stwaddlecom && docker compose pull budget && docker compose down budget && docker compose up -d budget"
|
||||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
|
||||||
Write-Host "Waiting for container to start..."
|
Write-Host "Waiting for container to start..."
|
||||||
|
|||||||
@@ -41,14 +41,32 @@ var connStr = builder.Configuration.GetConnectionString("DefaultConnection")
|
|||||||
$"Username={builder.Configuration["POSTGRES_USER"] ?? "budget"};" +
|
$"Username={builder.Configuration["POSTGRES_USER"] ?? "budget"};" +
|
||||||
$"Password={builder.Configuration["POSTGRES_PASSWORD"] ?? "changeme"}";
|
$"Password={builder.Configuration["POSTGRES_PASSWORD"] ?? "changeme"}";
|
||||||
|
|
||||||
builder.Services.AddDbContext<AppDbContext>(opt => opt.UseNpgsql(connStr));
|
builder.Services.AddSingleton<Budget.Infrastructure.Data.SlowQueryInterceptor>();
|
||||||
|
builder.Services.AddDbContext<AppDbContext>((sp, opt) =>
|
||||||
|
{
|
||||||
|
opt.UseNpgsql(connStr);
|
||||||
|
opt.AddInterceptors(sp.GetRequiredService<Budget.Infrastructure.Data.SlowQueryInterceptor>());
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||||
{
|
{
|
||||||
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor
|
||||||
options.KnownProxies.Clear();
|
| ForwardedHeaders.XForwardedProto
|
||||||
|
| ForwardedHeaders.XForwardedHost;
|
||||||
|
|
||||||
options.KnownIPNetworks.Clear();
|
options.KnownIPNetworks.Clear();
|
||||||
options.KnownIPNetworks.Add(System.Net.IPNetwork.Parse("172.20.0.0/16"));
|
options.KnownProxies.Clear();
|
||||||
|
|
||||||
|
var trustedNetworks = builder.Configuration["Budget:TrustedProxyNetworks"] ?? "172.16.0.0/12";
|
||||||
|
foreach (var cidr in trustedNetworks.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
||||||
|
{
|
||||||
|
var parts = cidr.Split('/');
|
||||||
|
var prefix = System.Net.IPAddress.Parse(parts[0]);
|
||||||
|
var prefixLength = parts.Length > 1
|
||||||
|
? int.Parse(parts[1])
|
||||||
|
: (prefix.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 ? 128 : 32);
|
||||||
|
options.KnownIPNetworks.Add(new System.Net.IPNetwork(prefix, prefixLength));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var oidc = builder.Configuration.GetSection("Oidc");
|
var oidc = builder.Configuration.GetSection("Oidc");
|
||||||
@@ -127,6 +145,8 @@ while (true)
|
|||||||
jwtOpts.ConfigurationManager!.RequestRefresh();
|
jwtOpts.ConfigurationManager!.RequestRefresh();
|
||||||
await jwtOpts.ConfigurationManager!.GetConfigurationAsync(CancellationToken.None);
|
await jwtOpts.ConfigurationManager!.GetConfigurationAsync(CancellationToken.None);
|
||||||
startupLogger.LogInformation("OIDC discovery succeeded");
|
startupLogger.LogInformation("OIDC discovery succeeded");
|
||||||
|
startupLogger.LogInformation("Trusted proxy networks: {Networks}",
|
||||||
|
app.Configuration["Budget:TrustedProxyNetworks"] ?? "172.16.0.0/12 (default)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning",
|
||||||
|
"Microsoft.EntityFrameworkCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "budget.stwaddle.com",
|
"AllowedHosts": "budget.stwaddle.com",
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Data.Common;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Budget.Infrastructure.Data;
|
||||||
|
|
||||||
|
public class SlowQueryInterceptor(ILogger<SlowQueryInterceptor> logger) : DbCommandInterceptor
|
||||||
|
{
|
||||||
|
private static readonly TimeSpan Threshold = TimeSpan.FromMilliseconds(500);
|
||||||
|
|
||||||
|
public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)
|
||||||
|
{
|
||||||
|
LogIfSlow(command, eventData.Duration);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ValueTask<DbDataReader> ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
LogIfSlow(command, eventData.Duration);
|
||||||
|
return new ValueTask<DbDataReader>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)
|
||||||
|
{
|
||||||
|
LogIfSlow(command, eventData.Duration);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ValueTask<int> NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
LogIfSlow(command, eventData.Duration);
|
||||||
|
return new ValueTask<int>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object? ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object? result)
|
||||||
|
{
|
||||||
|
LogIfSlow(command, eventData.Duration);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ValueTask<object?> ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object? result, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
LogIfSlow(command, eventData.Duration);
|
||||||
|
return new ValueTask<object?>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogIfSlow(DbCommand command, TimeSpan duration)
|
||||||
|
{
|
||||||
|
if (duration >= Threshold)
|
||||||
|
logger.LogWarning("Slow query ({Duration}ms): {CommandText}",
|
||||||
|
(long)duration.TotalMilliseconds, command.CommandText);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user