diff --git a/ECMJobRunner.WebCron/ECMJobRunner.WebCron.csproj b/ECMJobRunner.WebCron/ECMJobRunner.WebCron.csproj
index 71515d1..bd7960d 100644
--- a/ECMJobRunner.WebCron/ECMJobRunner.WebCron.csproj
+++ b/ECMJobRunner.WebCron/ECMJobRunner.WebCron.csproj
@@ -14,8 +14,12 @@
+
+
+
+
diff --git a/ECMJobRunner.WebCron/Program.cs b/ECMJobRunner.WebCron/Program.cs
index fedb01b..397da17 100644
--- a/ECMJobRunner.WebCron/Program.cs
+++ b/ECMJobRunner.WebCron/Program.cs
@@ -5,13 +5,35 @@ using Hangfire;
using Hangfire.SqlServer;
using Microsoft.Data.SqlClient;
using Serilog;
+using Serilog.Ui.Core.Extensions;
+using Serilog.Ui.SqliteDataProvider.Extensions;
+using Serilog.Ui.Web.Extensions;
-// Configure Serilog from appsettings.json
+// Enable Serilog self-diagnostics
+Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine($"[SERILOG] {msg}"));
+
+// Build temporary configuration to read log directory
+var tempConfig = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .Build();
+
+// Get log directory from configuration
+var logDirectory = tempConfig.GetValue("Logging:LogDirectory")
+ ?? throw new InvalidOperationException("Logging:LogDirectory not found in configuration.");
+var sqliteDbPath = Path.Combine(logDirectory, "logs.db");
+
+Console.WriteLine($"[INFO] SQLite Log Database Path: {sqliteDbPath}");
+
+// Configure Serilog with SQLite sink
Log.Logger = new LoggerConfiguration()
- .ReadFrom.Configuration(new ConfigurationBuilder()
- .AddJsonFile("appsettings.json")
- .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
- .Build())
+ .MinimumLevel.Information()
+ .MinimumLevel.Override("Microsoft.AspNetCore", Serilog.Events.LogEventLevel.Warning)
+ .MinimumLevel.Override("Microsoft.EntityFrameworkCore", Serilog.Events.LogEventLevel.Warning)
+ .MinimumLevel.Override("Hangfire", Serilog.Events.LogEventLevel.Information)
+ .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
+ .WriteTo.SQLite(sqliteDbPath, storeTimestampInUtc: true)
+ .Enrich.FromLogContext()
.CreateLogger();
try
@@ -78,6 +100,20 @@ builder.Services.AddHangfireServer();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
+// Add Serilog.UI with SQLite provider - use same path from configuration
+var serilogUiLogDirectory = builder.Configuration.GetValue("Logging:LogDirectory")
+ ?? throw new InvalidOperationException("Logging:LogDirectory not found in configuration.");
+var serilogUiDbPath = Path.Combine(serilogUiLogDirectory, "logs.db");
+
+builder.Services.AddSerilogUi(logUIOpt =>
+{
+ logUIOpt.UseSqliteServer(dbOpt =>
+ {
+ dbOpt.WithConnectionString($"Data Source={serilogUiDbPath}");
+ dbOpt.WithTable("Logs");
+ });
+});
+
var app = builder.Build();
// Configure the HTTP request pipeline.
@@ -97,6 +133,9 @@ app.UseHangfireDashboard("/hangfire", new DashboardOptions
Authorization = new[] { new AllowAllDashboardAuthorizationFilter() }
});
+// Add Serilog.UI Dashboard
+app.UseSerilogUi();
+
app.MapControllers();
app.Run();
diff --git a/ECMJobRunner.WebCron/appsettings.Development.json b/ECMJobRunner.WebCron/appsettings.Development.json
index 1db0dc9..9173c8c 100644
--- a/ECMJobRunner.WebCron/appsettings.Development.json
+++ b/ECMJobRunner.WebCron/appsettings.Development.json
@@ -1,22 +1,10 @@
{
- "Serilog": {
- "Using": [ "Serilog.Sinks.Console" ],
- "MinimumLevel": {
+ "Logging": {
+ "LogLevel": {
"Default": "Debug",
- "Override": {
- "Microsoft.AspNetCore": "Warning",
- "Microsoft.EntityFrameworkCore": "Warning",
- "Hangfire": "Information"
- }
- },
- "WriteTo": [
- {
- "Name": "Console",
- "Args": {
- "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
- }
- }
- ],
- "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
+ "Microsoft.AspNetCore": "Warning",
+ "Microsoft.EntityFrameworkCore": "Warning",
+ "Hangfire": "Information"
+ }
}
}
diff --git a/ECMJobRunner.WebCron/appsettings.json b/ECMJobRunner.WebCron/appsettings.json
index 320dc21..7899564 100644
--- a/ECMJobRunner.WebCron/appsettings.json
+++ b/ECMJobRunner.WebCron/appsettings.json
@@ -1,32 +1,10 @@
{
- "Serilog": {
- "Using": [ "Serilog.Sinks.File" ],
- "MinimumLevel": {
- "Default": "Information",
- "Override": {
- "Microsoft.AspNetCore": "Warning",
- "Microsoft.EntityFrameworkCore": "Warning",
- "Hangfire": "Information"
- }
- },
- "WriteTo": [
- {
- "Name": "File",
- "Args": {
- "path": "Logs/log-.txt",
- "rollingInterval": "Day",
- "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message:lj}{NewLine}{Exception}",
- "retainedFileCountLimit": 30
- }
- }
- ],
- "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
- },
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
- }
+ },
+ "LogDirectory": "E:\\LogFiles\\Digital Data\\ECMJobRunner.WebCron"
},
"ConnectionStrings": {
"SDD-VMP04-SQL17": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;"