using Serilog; using Serilog.Events; namespace ScadaLink.Host; /// /// Builds the Serilog for the Host process. /// /// REQ-HOST-8 / Host-011: the configured minimum level comes from /// ScadaLink:Logging:MinimumLevel (bound to ) so an /// operator editing that key changes the effective log level. /// /// REQ-HOST-8 / Host-014: the console and file sinks are read from the standard /// Serilog configuration section via ReadFrom.Configuration — the sink /// set, console output template, file path and rolling interval are all /// configuration-driven (defined in appsettings.json), not hard-coded. The /// explicit MinimumLevel.Is below pins the floor from . /// public static class LoggerConfigurationFactory { public static LoggerConfiguration Build( IConfiguration configuration, string nodeRole, string siteId, string nodeHostname) { var loggingOptions = new LoggingOptions(); configuration.GetSection("ScadaLink:Logging").Bind(loggingOptions); var minimumLevel = ParseLevel(loggingOptions.MinimumLevel); return new LoggerConfiguration() .ReadFrom.Configuration(configuration) .MinimumLevel.Is(minimumLevel) .Enrich.WithProperty("SiteId", siteId) .Enrich.WithProperty("NodeHostname", nodeHostname) .Enrich.WithProperty("NodeRole", nodeRole); } /// /// Parses a Serilog name, falling back to /// for null/blank/unrecognised values. /// private static LogEventLevel ParseLevel(string? level) { return Enum.TryParse(level, ignoreCase: true, out var parsed) ? parsed : LogEventLevel.Information; } }