diff --git a/NEW/src/JdeScoping.Host/JdeScoping.Host.csproj b/NEW/src/JdeScoping.Host/JdeScoping.Host.csproj
index 4653504..23b0dcb 100644
--- a/NEW/src/JdeScoping.Host/JdeScoping.Host.csproj
+++ b/NEW/src/JdeScoping.Host/JdeScoping.Host.csproj
@@ -14,6 +14,10 @@
+
+
+
+
diff --git a/NEW/src/JdeScoping.Host/Program.cs b/NEW/src/JdeScoping.Host/Program.cs
index c9f6f3c..4bfd54e 100644
--- a/NEW/src/JdeScoping.Host/Program.cs
+++ b/NEW/src/JdeScoping.Host/Program.cs
@@ -4,82 +4,117 @@ using JdeScoping.DataSync.Options;
using JdeScoping.ExcelIO.Options;
using JdeScoping.Database;
using JdeScoping.Host.Startup;
-using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using Serilog;
+using Serilog.Events;
-var builder = WebApplication.CreateBuilder(args);
+// Configure Serilog with console and daily rolling file
+var logsPath = Path.Combine(AppContext.BaseDirectory, "logs");
+Directory.CreateDirectory(logsPath);
-// Windows Service support (no-op on non-Windows)
-builder.Host.UseWindowsService();
+Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Information()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
+ .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
+ .Enrich.FromLogContext()
+ .WriteTo.Console(
+ outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
+ .WriteTo.File(
+ path: Path.Combine(logsPath, "scoping-.log"),
+ rollingInterval: RollingInterval.Day,
+ retainedFileCountLimit: 30,
+ outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
+ .CreateLogger();
-// Run database migrations (skip in Testing environment)
-// Note: IDatabaseMigrator interface enables mocking for integration tests
-if (!builder.Environment.IsEnvironment("Testing"))
+try
{
- // Create early logger for startup diagnostics
- using var loggerFactory = LoggerFactory.Create(b => b
- .AddConfiguration(builder.Configuration.GetSection("Logging"))
- .AddConsole());
- var startupLogger = loggerFactory.CreateLogger("JdeScoping.Host.Startup");
+ var builder = WebApplication.CreateBuilder(args);
- IDatabaseMigrator migrator = new DatabaseMigrator(builder.Configuration);
- var migrationResult = migrator.Migrate();
+ // Windows Service support (no-op on non-Windows)
+ builder.Host.UseWindowsService();
- if (!migrationResult.Successful)
+ // Replace default logging with Serilog
+ builder.Services.AddLogging(logging =>
{
- startupLogger.LogError(migrationResult.Error, "Database migration failed: {ErrorMessage}", migrationResult.Error?.Message);
- return 1;
- }
-}
+ logging.ClearProviders();
+ logging.AddSerilog(dispose: true);
+ });
-// ASP.NET Core services
-builder.Services.AddRazorPages();
-
-// Module registration (in dependency order)
-builder.Services
- .AddDataAccess(builder.Configuration) // 1. Database access + search processing
- .AddInfrastructure(builder.Configuration) // 2. Infrastructure (JDE/CMS/Auth)
- .AddDataSyncServices(builder.Configuration) // 3. Data sync background service
- .AddExcelIO(builder.Configuration) // 4. Result export
- .AddWebApi(builder.Configuration); // 5. Web API (controllers, auth, SignalR)
-
-var app = builder.Build();
-
-// Configuration validation (skip in Testing environment)
-if (!app.Environment.IsEnvironment("Testing"))
-{
- var configLogger = app.Services.GetRequiredService()
- .CreateLogger("JdeScoping.Host.ConfigurationValidation");
-
- if (!ConfigurationValidationRunner.ValidateConfiguration(app.Services, configLogger))
+ // Run database migrations (skip in Testing environment)
+ // Note: IDatabaseMigrator interface enables mocking for integration tests
+ if (!builder.Environment.IsEnvironment("Testing"))
{
- configLogger.LogCritical("Application startup aborted due to configuration validation failures");
- return 1;
+ IDatabaseMigrator migrator = new DatabaseMigrator(builder.Configuration);
+ var migrationResult = migrator.Migrate();
+
+ if (!migrationResult.Successful)
+ {
+ Log.Error(migrationResult.Error, "Database migration failed: {ErrorMessage}", migrationResult.Error?.Message);
+ return 1;
+ }
}
+
+ // ASP.NET Core services
+ builder.Services.AddRazorPages();
+
+ // Module registration (in dependency order)
+ builder.Services
+ .AddDataAccess(builder.Configuration) // 1. Database access + search processing
+ .AddInfrastructure(builder.Configuration) // 2. Infrastructure (JDE/CMS/Auth)
+ .AddDataSyncServices(builder.Configuration) // 3. Data sync background service
+ .AddExcelIO(builder.Configuration) // 4. Result export
+ .AddWebApi(builder.Configuration); // 5. Web API (controllers, auth, SignalR)
+
+ var app = builder.Build();
+
+ // Configuration validation (skip in Testing environment)
+ if (!app.Environment.IsEnvironment("Testing"))
+ {
+ var configLogger = app.Services.GetRequiredService()
+ .CreateLogger("JdeScoping.Host.ConfigurationValidation");
+
+ if (!ConfigurationValidationRunner.ValidateConfiguration(app.Services, configLogger))
+ {
+ Log.Fatal("Application startup aborted due to configuration validation failures");
+ return 1;
+ }
+ }
+
+ // Startup validation - verify critical services are registered
+ ValidateServices(app.Services);
+
+ // Configure the HTTP request pipeline
+ if (app.Environment.IsDevelopment())
+ {
+ app.UseWebAssemblyDebugging();
+ }
+
+ app.UseStaticFiles();
+ app.UseBlazorFrameworkFiles();
+ app.UseRouting();
+
+ // Configure Web API middleware (authentication, authorization, controllers, SignalR hub)
+ app.UseWebApi();
+
+ app.MapRazorPages();
+ app.MapFallbackToFile("index.html");
+
+ // Register shutdown handler for clean Serilog disposal
+ app.Lifetime.ApplicationStopping.Register(Log.CloseAndFlush);
+
+ app.Run();
+
+ return 0;
}
-
-// Startup validation - verify critical services are registered
-ValidateServices(app.Services);
-
-// Configure the HTTP request pipeline
-if (app.Environment.IsDevelopment())
+catch (Exception ex)
{
- app.UseWebAssemblyDebugging();
+ Log.Fatal(ex, "Application terminated unexpectedly");
+ return 1;
+}
+finally
+{
+ Log.CloseAndFlush();
}
-
-app.UseStaticFiles();
-app.UseBlazorFrameworkFiles();
-app.UseRouting();
-
-// Configure Web API middleware (authentication, authorization, controllers, SignalR hub)
-app.UseWebApi();
-
-app.MapRazorPages();
-app.MapFallbackToFile("index.html");
-
-app.Run();
-
-return 0;
// Validates that critical services are properly registered
static void ValidateServices(IServiceProvider services)