diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index 015d82b..4b08430 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -12,7 +12,7 @@ using Serilog.Core; using Serilog.Events; using Serilog.Formatting.Json; using Crestron.SimplSharp.CrestronDataStore; -using System.Linq; +using PepperDash.Core.Logging; namespace PepperDash.Core { @@ -22,6 +22,7 @@ namespace PepperDash.Core public static class Debug { private static readonly string LevelStoreKey = "ConsoleDebugLevel"; + private static readonly string WebSocketLevelStoreKey = "WebsocketDebugLevel"; private static readonly Dictionary _logLevels = new Dictionary() { @@ -33,7 +34,7 @@ namespace PepperDash.Core {2, LogEventLevel.Verbose }, }; - private static readonly Logger _logger; + private static Logger _logger; private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch; @@ -101,29 +102,61 @@ namespace PepperDash.Core private static readonly Dictionary IncludedExcludedKeys; + private static readonly LoggerConfiguration _defaultLoggerConfiguration; + + private static LoggerConfiguration _loggerConfiguration; + + public static LoggerConfiguration LoggerConfiguration => _loggerConfiguration; + static Debug() { CrestronDataStoreStatic.InitCrestronDataStore(); - var defaultConsoleLevel = GetStoredLogEventLevel(); + var defaultConsoleLevel = GetStoredLogEventLevel(LevelStoreKey); - _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Information); + var defaultWebsocketLevel = GetStoredLogEventLevel(WebSocketLevelStoreKey); - _consoleLoggingLevelSwitch.MinimumLevel = defaultConsoleLevel; + _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel); + + _websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel); - _websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Verbose); _websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true)); - // Instantiate the root logger - _logger = new LoggerConfiguration() + var logFilePath = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? + $@"{Directory.GetApplicationRootDirectory()}{Path.DirectorySeparatorChar}user{Path.DirectorySeparatorChar}debug{Path.DirectorySeparatorChar}app{InitialParametersClass.ApplicationNumber}{Path.DirectorySeparatorChar}global-log.log" : + $@"{Directory.GetApplicationRootDirectory()}{Path.DirectorySeparatorChar}user{Path.DirectorySeparatorChar}debug{Path.DirectorySeparatorChar}room{InitialParametersClass.RoomId}{Path.DirectorySeparatorChar}global-log.log"; + + CrestronConsole.PrintLine($"Saving log files to {logFilePath}"); + + _defaultLoggerConfiguration = new LoggerConfiguration() .MinimumLevel.Verbose() .WriteTo.Sink(new DebugConsoleSink(new JsonFormatter(renderMessage: true)), levelSwitch: _consoleLoggingLevelSwitch) .WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch) - .WriteTo.File(@"\user\debug\global-log-{Date}.txt" - , rollingInterval: RollingInterval.Day - , restrictedToMinimumLevel: LogEventLevel.Debug) - .CreateLogger(); + .WriteTo.File(logFilePath, + rollingInterval: RollingInterval.Day, + restrictedToMinimumLevel: LogEventLevel.Debug, + retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60 + ); + try + { + if (InitialParametersClass.NumberOfRemovableDrives > 0) + { + CrestronConsole.PrintLine("{0} RM Drive(s) Present. Initializing CrestronLogger", InitialParametersClass.NumberOfRemovableDrives); + _defaultLoggerConfiguration.WriteTo.Sink(new DebugCrestronLoggerSink()); + } + else + CrestronConsole.PrintLine("No RM Drive(s) Present. Not using Crestron Logger"); + } + catch (Exception e) + { + CrestronConsole.PrintLine("Initializing of CrestronLogger failed: {0}", e); + } + + // Instantiate the root logger + _loggerConfiguration = _defaultLoggerConfiguration; + + _logger = _loggerConfiguration.CreateLogger(); // Get the assembly version and print it to console and the log GetVersion(); @@ -170,50 +203,48 @@ namespace PepperDash.Core if(DoNotLoadConfigOnNextBoot) CrestronConsole.PrintLine(string.Format("Program {0} will not load config after next boot. Use console command go:{0} to load the config manually", InitialParametersClass.ApplicationNumber)); - try - { - if (InitialParametersClass.NumberOfRemovableDrives > 0) - { - CrestronConsole.PrintLine("{0} RM Drive(s) Present.", InitialParametersClass.NumberOfRemovableDrives); - CrestronLogger.Initialize(2, LoggerModeEnum.DEFAULT); // Use RM instead of DEFAULT as not to double-up console messages. - } - else - CrestronConsole.PrintLine("No RM Drive(s) Present."); - } - catch (Exception e) - { - - CrestronConsole.PrintLine("Initializing of CrestronLogger failed: {0}", e); - } - _consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) => { Console(0, "Console debug level set to {0}", _consoleLoggingLevelSwitch.MinimumLevel); }; } - private static LogEventLevel GetStoredLogEventLevel() + public static void UpdateLoggerConfiguration(LoggerConfiguration config) + { + _loggerConfiguration = config; + + _logger = config.CreateLogger(); + } + + public static void ResetLoggerConfiguration() + { + _loggerConfiguration = _defaultLoggerConfiguration; + + _logger = _loggerConfiguration.CreateLogger(); + } + + private static LogEventLevel GetStoredLogEventLevel(string levelStoreKey) { try { - var result = CrestronDataStoreStatic.GetLocalIntValue(LevelStoreKey, out int logLevel); + var result = CrestronDataStoreStatic.GetLocalIntValue(levelStoreKey, out int logLevel); if (result != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) { - CrestronConsole.Print($"Unable to retrieve stored log level.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n"); + CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n"); return LogEventLevel.Information; } if(logLevel < 0 || logLevel > 5) { - CrestronConsole.PrintLine($"Stored Log level not valid: {logLevel}. Setting level to {LogEventLevel.Information}"); + CrestronConsole.PrintLine($"Stored Log level not valid for {levelStoreKey}: {logLevel}. Setting level to {LogEventLevel.Information}"); return LogEventLevel.Information; } return (LogEventLevel)logLevel; } catch (Exception ex) { - CrestronConsole.PrintLine($"Exception retrieving log level: {ex.Message}"); + CrestronConsole.PrintLine($"Exception retrieving log level for {levelStoreKey}: {ex.Message}"); return LogEventLevel.Information; } } @@ -349,10 +380,10 @@ namespace PepperDash.Core public static void SetWebSocketMinimumDebugLevel(LogEventLevel level) { - _websocketLoggingLevelSwitch.MinimumLevel = level; - var levelInt = _logLevels.FirstOrDefault((l) => l.Value.Equals(level)).Key; + _websocketLoggingLevelSwitch.MinimumLevel = level; + + var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint) level); - var err = CrestronDataStoreStatic.SetLocalUintValue("WebsocketDebugLevel", levelInt); if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) Console(0, "Error saving websocket debug level setting: {0}", err); @@ -632,14 +663,15 @@ namespace PepperDash.Core /// or above the level provided, then the output will be written to both console and the log. Otherwise /// it will only be written to the log. /// + [Obsolete("Use LogMessage methods")] public static void ConsoleWithLog(uint level, string format, params object[] items) { LogMessage(level, format, items); - var str = string.Format(format, items); + // var str = string.Format(format, items); //if (Level >= level) // CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, str); - CrestronLogger.WriteToLog(str, level); + // CrestronLogger.WriteToLog(str, level); } /// @@ -647,12 +679,13 @@ namespace PepperDash.Core /// or above the level provided, then the output will be written to both console and the log. Otherwise /// it will only be written to the log. /// + [Obsolete("Use LogMessage methods")] public static void ConsoleWithLog(uint level, IKeyed dev, string format, params object[] items) { LogMessage(level, dev, format, items); - var str = string.Format(format, items); - CrestronLogger.WriteToLog(string.Format("[{0}] {1}", dev.Key, str), level); + // var str = string.Format(format, items); + // CrestronLogger.WriteToLog(string.Format("[{0}] {1}", dev.Key, str), level); } /// diff --git a/src/Pepperdash Core/Logging/DebugConsoleSink.cs b/src/Pepperdash Core/Logging/DebugConsoleSink.cs index 2102a24..a59928d 100644 --- a/src/Pepperdash Core/Logging/DebugConsoleSink.cs +++ b/src/Pepperdash Core/Logging/DebugConsoleSink.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; namespace PepperDash.Core { - internal class DebugConsoleSink : ILogEventSink + public class DebugConsoleSink : ILogEventSink { private readonly ITextFormatter _textFormatter; diff --git a/src/Pepperdash Core/Logging/DebugCrestronLoggerSink.cs b/src/Pepperdash Core/Logging/DebugCrestronLoggerSink.cs new file mode 100644 index 0000000..0814453 --- /dev/null +++ b/src/Pepperdash Core/Logging/DebugCrestronLoggerSink.cs @@ -0,0 +1,29 @@ +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronLogger; +using Serilog.Core; +using Serilog.Events; + +namespace PepperDash.Core.Logging +{ + public class DebugCrestronLoggerSink : ILogEventSink + { + public void Emit(LogEvent logEvent) + { + if (!Debug.IsRunningOnAppliance) return; + + string message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}]{logEvent.RenderMessage()}"; + + if (logEvent.Properties.TryGetValue("Key", out var value) && value is ScalarValue sv && sv.Value is string rawValue) + { + message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}][{rawValue}]: {logEvent.RenderMessage()}"; + } + + CrestronLogger.WriteToLog(message, (uint)logEvent.Level); + } + + public DebugCrestronLoggerSink() + { + CrestronLogger.Initialize(1, LoggerModeEnum.RM); + } + } +} diff --git a/src/Pepperdash Core/PepperDash_Core.csproj b/src/Pepperdash Core/PepperDash_Core.csproj index d6880a4..2da71dc 100644 --- a/src/Pepperdash Core/PepperDash_Core.csproj +++ b/src/Pepperdash Core/PepperDash_Core.csproj @@ -29,7 +29,7 @@ - D +