From ada8b7e1626060e026bc59d9daf7d19dcda5bdad Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 8 Mar 2024 08:47:43 -0600 Subject: [PATCH 1/6] fix: update logging format to include key --- .gitignore | 1 + src/Pepperdash Core/Logging/Debug.cs | 19 ++++++++++--------- .../Logging/DebugConsoleSink.cs | 18 ++++++++++-------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 8a30d25..6c7cb0d 100644 --- a/.gitignore +++ b/.gitignore @@ -396,3 +396,4 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml +*.projectinfo diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index 4fec380..6648aff 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -24,11 +24,11 @@ public static class Debug private static Dictionary _logLevels = new Dictionary() { {0, LogEventLevel.Information }, - {1, LogEventLevel.Warning }, - {2, LogEventLevel.Error }, - {3, LogEventLevel.Fatal }, - {4, LogEventLevel.Debug }, - {5, LogEventLevel.Verbose }, + {3, LogEventLevel.Warning }, + {4, LogEventLevel.Error }, + {5, LogEventLevel.Fatal }, + {1, LogEventLevel.Debug }, + {2, LogEventLevel.Verbose }, }; private static Logger _logger; @@ -104,7 +104,7 @@ static Debug() _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Information); _consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) => { - Debug.Console(0, "Console debug level set to {0}", _consoleLoggingLevelSwitch.MinimumLevel); + Console(0, "Console debug level set to {0}", _consoleLoggingLevelSwitch.MinimumLevel); }; _websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Verbose); _websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true)); @@ -116,7 +116,7 @@ static Debug() .WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch) .WriteTo.File(@"\user\debug\global-log-{Date}.txt" , rollingInterval: RollingInterval.Day - , restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Debug) + , restrictedToMinimumLevel: LogEventLevel.Debug) .CreateLogger(); // Get the assembly version and print it to console and the log @@ -455,6 +455,7 @@ private static void LogMessage(uint level, string format, params object[] items) if (!_logLevels.ContainsKey(level)) return; var logLevel = _logLevels[level]; + _logger.Write(logLevel, format, items); } @@ -464,8 +465,8 @@ private static void LogMessage(uint level, IKeyed keyed, string format, params o var logLevel = _logLevels[level]; - var log = _logger.ForContext("Key", keyed.Key); - log.Write(logLevel, format, items); + var logger = _logger.ForContext("Key", keyed.Key); + logger.Write(logLevel, format, items); } diff --git a/src/Pepperdash Core/Logging/DebugConsoleSink.cs b/src/Pepperdash Core/Logging/DebugConsoleSink.cs index e991429..2102a24 100644 --- a/src/Pepperdash Core/Logging/DebugConsoleSink.cs +++ b/src/Pepperdash Core/Logging/DebugConsoleSink.cs @@ -20,19 +20,21 @@ internal class DebugConsoleSink : ILogEventSink public void Emit(LogEvent logEvent) { - if (!Debug.IsRunningOnAppliance) return; + if (!Debug.IsRunningOnAppliance) return; - CrestronConsole.PrintLine("[{0}][App {1}][Lvl {2}]: {3}", logEvent.Timestamp, - InitialParametersClass.ApplicationNumber, - logEvent.Level, - logEvent.RenderMessage()); + 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()}"; + } + + CrestronConsole.PrintLine(message); } - public DebugConsoleSink(ITextFormatter formatProvider) + public DebugConsoleSink(ITextFormatter formatProvider ) { - _textFormatter = formatProvider ?? new JsonFormatter(); - } } From 32caa005a33f985f7e922a53973ed24fafd43e6a Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 13 Mar 2024 08:21:15 -0500 Subject: [PATCH 2/6] fix: add console log level recall --- src/Pepperdash Core/Logging/Debug.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index 6648aff..d628d75 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -21,6 +21,7 @@ namespace PepperDash.Core /// public static class Debug { + private static string LevelStoreKey = "ConsoleDebugLevel"; private static Dictionary _logLevels = new Dictionary() { {0, LogEventLevel.Information }, @@ -101,7 +102,9 @@ public static DebugWebsocketSink WebsocketSink static Debug() { - _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Information); + var defaultConsoleLevel = GetStoredLogEventLevel(); + + _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel); _consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) => { Console(0, "Console debug level set to {0}", _consoleLoggingLevelSwitch.MinimumLevel); @@ -187,6 +190,24 @@ static Debug() } } + private static LogEventLevel GetStoredLogEventLevel() + { + try + { + var result = CrestronDataStoreStatic.GetLocalUintValue(LevelStoreKey, out uint logLevel); + + if(result != CrestronDataStore.CDS_ERROR.CDS_SUCCESS || logLevel > 5 || logLevel < 0) + { + return LogEventLevel.Information; + } + + return _logLevels[logLevel]; + } catch + { + return LogEventLevel.Information; + } + } + private static void GetVersion() { var assembly = Assembly.GetExecutingAssembly(); From b41f4190bec6ef098da46640a9bc81248a4cc902 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 20 Mar 2024 10:24:27 -0500 Subject: [PATCH 3/6] feat: add public LogMessage methods Also add logic to allow using string like `Information` with `appdebug` console command. --- src/Pepperdash Core/Logging/Debug.cs | 62 ++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index d628d75..ae63c25 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -280,11 +280,25 @@ public static void SetDebugFromConsole(string levelString) return; } - var level = Convert.ToUInt32(levelString); + if(int.TryParse(levelString, out var levelInt)) + { + if(levelInt < 0 || levelInt > 5) + { + CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5"); + return; + } + SetDebugLevel((LogEventLevel)levelInt); + return; + } - if (_logLevels.ContainsKey(level)) - SetDebugLevel(level); - } + if(Enum.TryParse(levelString, out var levelEnum)) + { + SetDebugLevel(levelEnum); + return; + } + + CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level"); + } catch { CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [0-5]"); @@ -297,15 +311,28 @@ public static void SetDebugFromConsole(string levelString) /// Valid values 0-5 public static void SetDebugLevel(uint level) { - if (_logLevels.ContainsKey(level)) - _consoleLoggingLevelSwitch.MinimumLevel = _logLevels[level]; + if(!_logLevels.TryGetValue(level, out var logLevel)) + { + logLevel = LogEventLevel.Information; + + CrestronConsole.PrintLine($"{level} not valid. Setting level to {logLevel}"); + + SetDebugLevel(logLevel); + } + + SetDebugLevel(logLevel); + } + + public static void SetDebugLevel(LogEventLevel level) + { + _consoleLoggingLevelSwitch.MinimumLevel = level; CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}", InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel); - var err = CrestronDataStoreStatic.SetLocalUintValue("ConsoleDebugLevel", level); + var err = CrestronDataStoreStatic.SetLocalUintValue("ConsoleDebugLevel", (uint) level); if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - CrestronConsole.PrintLine("Error saving console debug level setting: {0}", err); + CrestronConsole.PrintLine($"Error saving console debug level setting: {err}"); } public static void SetWebSocketMinimumDebugLevel(LogEventLevel level) @@ -470,6 +497,18 @@ public static void ShowDebugLog(string s) CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine); } + public static void LogMessage(LogEventLevel level, string message, params object[] args) + { + _logger.Write(level, message, args); + } + + public static void LogMessage(LogEventLevel level, IKeyed keyed, string message, params object[] args) + { + var log = _logger.ForContext("Key", keyed.Key); + + log.Write(level, message, args); + } + private static void LogMessage(uint level, string format, params object[] items) { @@ -477,7 +516,7 @@ private static void LogMessage(uint level, string format, params object[] items) var logLevel = _logLevels[level]; - _logger.Write(logLevel, format, items); + LogMessage(logLevel, format, items ); } private static void LogMessage(uint level, IKeyed keyed, string format, params object[] items) @@ -485,9 +524,8 @@ private static void LogMessage(uint level, IKeyed keyed, string format, params o if (!_logLevels.ContainsKey(level)) return; var logLevel = _logLevels[level]; - - var logger = _logger.ForContext("Key", keyed.Key); - logger.Write(logLevel, format, items); + + LogMessage(logLevel, keyed, format, items); } From a7f9799370f53c5b62a03e61a15aec9c6fe943d8 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 20 Mar 2024 15:56:00 -0500 Subject: [PATCH 4/6] feat: update appdebug command `appdebug` command now takes levels as either integers 0-5 or Serilg `LogEventLevel` strings, `Information` etc. --- src/Pepperdash Core/Logging/Debug.cs | 84 ++++++++++++---------- src/Pepperdash Core/PepperDash_Core.csproj | 7 +- 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index ae63c25..015d82b 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.RegularExpressions; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Crestron.SimplSharp.CrestronLogger; using Crestron.SimplSharp.CrestronIO; using Newtonsoft.Json; @@ -21,8 +21,9 @@ namespace PepperDash.Core /// public static class Debug { - private static string LevelStoreKey = "ConsoleDebugLevel"; - private static Dictionary _logLevels = new Dictionary() + private static readonly string LevelStoreKey = "ConsoleDebugLevel"; + + private static readonly Dictionary _logLevels = new Dictionary() { {0, LogEventLevel.Information }, {3, LogEventLevel.Warning }, @@ -32,18 +33,18 @@ public static class Debug {2, LogEventLevel.Verbose }, }; - private static Logger _logger; + private static readonly Logger _logger; - private static LoggingLevelSwitch _consoleLoggingLevelSwitch; + private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch; - private static LoggingLevelSwitch _websocketLoggingLevelSwitch; + private static readonly LoggingLevelSwitch _websocketLoggingLevelSwitch; public static LogEventLevel WebsocketMinimumLogLevel { get { return _websocketLoggingLevelSwitch.MinimumLevel; } } - private static DebugWebsocketSink _websocketSink; + private static readonly DebugWebsocketSink _websocketSink; public static DebugWebsocketSink WebsocketSink { @@ -102,13 +103,14 @@ public static DebugWebsocketSink WebsocketSink static Debug() { + CrestronDataStoreStatic.InitCrestronDataStore(); + var defaultConsoleLevel = GetStoredLogEventLevel(); - _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel); - _consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) => - { - Console(0, "Console debug level set to {0}", _consoleLoggingLevelSwitch.MinimumLevel); - }; + _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Information); + + _consoleLoggingLevelSwitch.MinimumLevel = defaultConsoleLevel; + _websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: LogEventLevel.Verbose); _websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true)); @@ -125,15 +127,11 @@ static Debug() // Get the assembly version and print it to console and the log GetVersion(); - string msg = ""; + string msg = $"[App {InitialParametersClass.ApplicationNumber}] Using PepperDash_Core v{PepperDashCoreVersion}"; - if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) - { - msg = string.Format("[App {0}] Using PepperDash_Core v{1}", InitialParametersClass.ApplicationNumber, PepperDashCoreVersion); - } - else if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) + if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) { - msg = string.Format("[Room {0}] Using PepperDash_Core v{1}", InitialParametersClass.RoomId, PepperDashCoreVersion); + msg = $"[Room {InitialParametersClass.RoomId}] Using PepperDash_Core v{PepperDashCoreVersion}"; } CrestronConsole.PrintLine(msg); @@ -141,8 +139,7 @@ static Debug() LogError(ErrorLogLevel.Notice, msg); IncludedExcludedKeys = new Dictionary(); - - //CrestronDataStoreStatic.InitCrestronDataStore(); + if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro) { // Add command to console @@ -188,22 +185,35 @@ static Debug() 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() { try { - var result = CrestronDataStoreStatic.GetLocalUintValue(LevelStoreKey, out uint logLevel); + var result = CrestronDataStoreStatic.GetLocalIntValue(LevelStoreKey, out int logLevel); - if(result != CrestronDataStore.CDS_ERROR.CDS_SUCCESS || logLevel > 5 || logLevel < 0) + 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"); return LogEventLevel.Information; } - return _logLevels[logLevel]; - } catch + if(logLevel < 0 || logLevel > 5) + { + CrestronConsole.PrintLine($"Stored Log level not valid: {logLevel}. Setting level to {LogEventLevel.Information}"); + return LogEventLevel.Information; + } + + return (LogEventLevel)logLevel; + } catch (Exception ex) { + CrestronConsole.PrintLine($"Exception retrieving log level: {ex.Message}"); return LogEventLevel.Information; } } @@ -217,9 +227,7 @@ private static void GetVersion() if (ver != null && ver.Length > 0) { - var verAttribute = ver[0] as AssemblyInformationalVersionAttribute; - - if (verAttribute != null) + if (ver[0] is AssemblyInformationalVersionAttribute verAttribute) { PepperDashCoreVersion = verAttribute.InformationalVersion; } @@ -227,8 +235,7 @@ private static void GetVersion() else { var version = assembly.GetName().Version; - PepperDashCoreVersion = string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, - version.Revision); + PepperDashCoreVersion = version.ToString(); } } @@ -287,7 +294,7 @@ public static void SetDebugFromConsole(string levelString) CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5"); return; } - SetDebugLevel((LogEventLevel)levelInt); + SetDebugLevel((uint) levelInt); return; } @@ -315,7 +322,7 @@ public static void SetDebugLevel(uint level) { logLevel = LogEventLevel.Information; - CrestronConsole.PrintLine($"{level} not valid. Setting level to {logLevel}"); + CrestronConsole.ConsoleCommandResponse($"{level} not valid. Setting level to {logLevel}"); SetDebugLevel(logLevel); } @@ -327,10 +334,15 @@ public static void SetDebugLevel(LogEventLevel level) { _consoleLoggingLevelSwitch.MinimumLevel = level; - CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}", + CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}\r\n", InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel); - var err = CrestronDataStoreStatic.SetLocalUintValue("ConsoleDebugLevel", (uint) level); + CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int) level}"); + + var err = CrestronDataStoreStatic.SetLocalIntValue(LevelStoreKey, (int) level); + + CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}"); + if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) CrestronConsole.PrintLine($"Error saving console debug level setting: {err}"); } @@ -361,7 +373,7 @@ public static void SetDoNotLoadOnNextBootFromConsole(string stateString) return; } - SetDoNotLoadConfigOnNextBoot(Boolean.Parse(stateString)); + SetDoNotLoadConfigOnNextBoot(bool.Parse(stateString)); } catch { @@ -734,7 +746,7 @@ static string GetMemoryFileName() { if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) { - CheckForMigration(); + // CheckForMigration(); return string.Format(@"\user\debugSettings\program{0}", InitialParametersClass.ApplicationNumber); } diff --git a/src/Pepperdash Core/PepperDash_Core.csproj b/src/Pepperdash Core/PepperDash_Core.csproj index 782dae7..d6880a4 100644 --- a/src/Pepperdash Core/PepperDash_Core.csproj +++ b/src/Pepperdash Core/PepperDash_Core.csproj @@ -3,7 +3,7 @@ PepperDash.Core PepperDashCore net472;net6 - false + true en bin\$(Configuration)\ False @@ -13,9 +13,10 @@ git https://github.com/PepperDash/PepperDashCore crestron;4series; - $(Version) + 2.0.0-local $(Version) ../../package + true full @@ -28,7 +29,7 @@ - + D From 244aa26c42d7906952cd765beb0f5a37a7094519 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 21 Mar 2024 09:45:49 -0500 Subject: [PATCH 5/6] feat: add CrestronLogger Serilog Sink --- src/Pepperdash Core/Logging/Debug.cs | 113 +++++++++++------- .../Logging/DebugConsoleSink.cs | 2 +- .../Logging/DebugCrestronLoggerSink.cs | 29 +++++ src/Pepperdash Core/PepperDash_Core.csproj | 2 +- 4 files changed, 104 insertions(+), 42 deletions(-) create mode 100644 src/Pepperdash Core/Logging/DebugCrestronLoggerSink.cs 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.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 @@ public static class Debug {2, LogEventLevel.Verbose }, }; - private static readonly Logger _logger; + private static Logger _logger; private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch; @@ -101,29 +102,61 @@ public static DebugWebsocketSink WebsocketSink 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 @@ static Debug() 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 @@ public static void SetDebugLevel(LogEventLevel level) 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 @@ public static void Console(uint level, ErrorLogLevel errorLogLevel, /// 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 @@ public static void ConsoleWithLog(uint level, string format, params object[] ite /// 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 @@ 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 + From 8403265c2641194ce53ea47d0838fc84d6ce2b35 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 21 Mar 2024 10:17:20 -0500 Subject: [PATCH 6/6] feat: update file sink format to include key if available --- src/Pepperdash Core/Logging/Debug.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index 4b08430..5d46dde 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -133,10 +133,11 @@ static Debug() .WriteTo.Sink(new DebugConsoleSink(new JsonFormatter(renderMessage: true)), levelSwitch: _consoleLoggingLevelSwitch) .WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch) .WriteTo.File(logFilePath, + outputTemplate: "[{Timestamp}][{Level}][{Properties.Key}]{Message}{NewLine}", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug, retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60 - ); + ); ; try {