From f186e3ae4dd305ca44d2092c031f39268e8998ae Mon Sep 17 00:00:00 2001 From: RaidMax Date: Fri, 26 May 2023 21:14:49 -0500 Subject: [PATCH] add command to set log level and develop mode dynamically --- Application/Commands/SetLogLevelCommand.cs | 80 +++++++++++++++++++++ Application/Extensions/StartupExtensions.cs | 32 +++++++-- SharedLibraryCore/Utilities.cs | 2 +- 3 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 Application/Commands/SetLogLevelCommand.cs diff --git a/Application/Commands/SetLogLevelCommand.cs b/Application/Commands/SetLogLevelCommand.cs new file mode 100644 index 000000000..250b139fe --- /dev/null +++ b/Application/Commands/SetLogLevelCommand.cs @@ -0,0 +1,80 @@ +using System; +using System.Threading.Tasks; +using Data.Models.Client; +using Serilog.Core; +using Serilog.Events; +using SharedLibraryCore; +using SharedLibraryCore.Commands; +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Interfaces; + +namespace IW4MAdmin.Application.Commands; + +public class SetLogLevelCommand : Command +{ + private readonly Func _levelSwitchResolver; + + public SetLogLevelCommand(CommandConfiguration config, ITranslationLookup layout, Func levelSwitchResolver) : base(config, layout) + { + _levelSwitchResolver = levelSwitchResolver; + + Name = "loglevel"; + Alias = "ll"; + Description = "set minimum logging level"; + Permission = EFClient.Permission.Owner; + Arguments = new CommandArgument[] + { + new() + { + Name = "Log Level", + Required = true + }, + new() + { + Name = "Override", + Required = false + }, + new() + { + Name = "IsDevelopment", + Required = false + } + }; + + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + var args = gameEvent.Data.Split(" "); + if (!Enum.TryParse(args[0], out var minLevel)) + { + await gameEvent.Origin.TellAsync(new[] + { + $"Valid log values: {string.Join(",", Enum.GetValues())}" + }); + return; + } + + var context = string.Empty; + + if (args.Length > 1) + { + context = args[1]; + } + + var loggingSwitch = _levelSwitchResolver(context); + loggingSwitch.MinimumLevel = minLevel; + + if (args.Length > 2 && (args[2] == "1" || args[2].ToLower() == "true")) + { + AppContext.SetSwitch("IsDevelop", true); + } + else + { + AppContext.SetSwitch("IsDevelop", false); + } + + await gameEvent.Origin.TellAsync(new[] + { $"Set minimum log level to {loggingSwitch.MinimumLevel.ToString()}" }); + } +} diff --git a/Application/Extensions/StartupExtensions.cs b/Application/Extensions/StartupExtensions.cs index 907ac8899..ff4498ee2 100644 --- a/Application/Extensions/StartupExtensions.cs +++ b/Application/Extensions/StartupExtensions.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; +using Serilog.Core; using Serilog.Events; using SharedLibraryCore; using SharedLibraryCore.Configuration; @@ -17,7 +18,10 @@ namespace IW4MAdmin.Application.Extensions { public static class StartupExtensions { - private static ILogger _defaultLogger = null; + private static ILogger _defaultLogger; + private static readonly LoggingLevelSwitch LevelSwitch = new(); + private static readonly LoggingLevelSwitch MicrosoftLevelSwitch = new(); + private static readonly LoggingLevelSwitch SystemLevelSwitch = new(); public static IServiceCollection AddBaseLogger(this IServiceCollection services, ApplicationConfiguration appConfig) @@ -29,21 +33,37 @@ namespace IW4MAdmin.Application.Extensions .Build(); var loggerConfig = new LoggerConfiguration() - .ReadFrom.Configuration(configuration) - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning); + .ReadFrom.Configuration(configuration); + + LevelSwitch.MinimumLevel = Enum.Parse(configuration["Serilog:MinimumLevel:Default"]); + MicrosoftLevelSwitch.MinimumLevel = Enum.Parse(configuration["Serilog:MinimumLevel:Override:Microsoft"]); + SystemLevelSwitch.MinimumLevel = Enum.Parse(configuration["Serilog:MinimumLevel:Override:System"]); + + loggerConfig = loggerConfig.MinimumLevel.ControlledBy(LevelSwitch); + loggerConfig = loggerConfig.MinimumLevel.Override("Microsoft", MicrosoftLevelSwitch) + .MinimumLevel.Override("System", SystemLevelSwitch); if (Utilities.IsDevelopment) { loggerConfig = loggerConfig.WriteTo.Console( outputTemplate: - "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}") - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel.Debug(); + "[{Timestamp:HH:mm:ss} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}") + ; //.MinimumLevel.Override("Microsoft", LogEventLevel.Information) + //.MinimumLevel.Debug(); } _defaultLogger = loggerConfig.CreateLogger(); } + services.AddSingleton((string context) => + { + return context.ToLower() switch + { + "microsoft" => MicrosoftLevelSwitch, + "system" => SystemLevelSwitch, + _ => LevelSwitch + }; + }); services.AddLogging(builder => builder.AddSerilog(_defaultLogger, dispose: true)); services.AddSingleton(new LoggerFactory() .AddSerilog(_defaultLogger, true)); diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 41437d4da..2a30ac1e0 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -1145,7 +1145,7 @@ namespace SharedLibraryCore /// /// public static bool IsDevelopment => - Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"; + Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development" || AppContext.TryGetSwitch("IsDevelop", out _); /// /// replaces any directory separator chars with the platform specific character