Files
DocumentService/DocumentOperator.API/Program.cs
TekH 536413bafe feat(logging): Configure Serilog SQLite sink + UI
appsettings.json:
- Add Application:LogDirectory configuration
- Add Serilog WriteTo.SQLite sink (logs.db in LogDirectory)
- Logs table with UTC timestamps

Program.cs:
- Add Serilog.UI usings
- Configure Serilog.UI with SQLite provider
- Mount UI at /serilog-ui endpoint

Web-based log viewer accessible at: https://localhost:7186/serilog-ui
2026-07-21 14:39:32 +02:00

117 lines
3.8 KiB
C#

using Serilog;
using Serilog.Ui.Core.Extensions;
using Serilog.Ui.SqliteDataProvider.Extensions;
using Serilog.Ui.Web.Extensions;
using DocumentOperator.Infrastructure.Configuration;
using DocumentOperator.Application;
using DocumentOperator.Infrastructure;
using DocumentOperator.API.Middleware;
using DocumentOperator.API.Configuration;
var builder = WebApplication.CreateBuilder(args);
// ========================================
// 1. Serilog Configuration
// ========================================
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.Enrich.WithProperty("Application", "DocumentOperator")
.CreateLogger();
builder.Host.UseSerilog();
Log.Information("Starting DocumentOperator API...");
try
{
// ========================================
// 2. Options Pattern Configuration
// ========================================
builder.Services.Configure<DocumentOperatorSettings>(
builder.Configuration.GetSection(DocumentOperatorSettings.SectionName));
builder.Services.Configure<RedisSettings>(
builder.Configuration.GetSection(RedisSettings.SectionName));
builder.Services.Configure<ApiKeySettings>(
builder.Configuration.GetSection(ApiKeySettings.SectionName));
// ========================================
// 3. Services (Clean Architecture Layers)
// ========================================
builder.Services.AddApplication(); // Application Layer (MediatR, FluentValidation, Behaviors)
builder.Services.AddInfrastructure(); // Infrastructure Layer (DevExpress, Services)
builder.Services.AddControllers(); // Controllers (Controller-based API)
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerDocumentation();
// ========================================
// 4. Serilog.UI Configuration
// ========================================
var logDirectory = builder.Configuration.GetValue<string>("Application:LogDirectory")
?? throw new InvalidOperationException("Application:LogDirectory not found in configuration.");
var sqliteDbPath = Path.Combine(logDirectory, "logs.db");
builder.Services.AddSerilogUi(logUIOpt =>
{
logUIOpt.UseSqliteServer(dbOpt =>
{
dbOpt.WithConnectionString($"Data Source={sqliteDbPath}");
dbOpt.WithTable("Logs");
});
});
// ========================================
// 5. Build App
// ========================================
var app = builder.Build();
// ========================================
// 5. Middleware Pipeline (Order matters!)
// ========================================
// Exception Handling FIRST (catches all exceptions from subsequent middleware)
app.UseMiddleware<ExceptionHandlingMiddleware>();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseSerilogRequestLogging(); // Log HTTP Requests
app.UseHttpsRedirection();
// ========================================
// 6. Serilog.UI Dashboard
// ========================================
app.UseSerilogUi(); // Accessible at /serilog-ui
// ========================================
// 7. Endpoints (Controller-based API)
// ========================================
app.MapControllers(); // Maps all [ApiController] controllers
Log.Information("DocumentOperator API started successfully");
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application startup failed");
throw;
}
finally
{
Log.CloseAndFlush();
}
// Make Program class accessible for Integration Tests
/// <summary>
/// Entry point class for the DocumentOperator API.
/// Made partial and public for integration test access.
/// </summary>
public partial class Program { }