From 2f1180512c18e31962b8434bf13e4ca2067737fd Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 30 Oct 2023 17:24:47 -0600 Subject: [PATCH] feat: Initial implementation of DebugWebsocketSink --- src/Pepperdash Core/CoreInterfaces.cs | 20 ++++-- src/Pepperdash Core/Device.cs | 12 +++- src/Pepperdash Core/Logging/Debug.cs | 70 ++++++++++++++++++- .../Logging/DebugWebsocketSink.cs | 42 +++++++++++ src/Pepperdash Core/PepperDash_Core.csproj | 4 ++ 5 files changed, 141 insertions(+), 7 deletions(-) create mode 100644 src/Pepperdash Core/Logging/DebugWebsocketSink.cs diff --git a/src/Pepperdash Core/CoreInterfaces.cs b/src/Pepperdash Core/CoreInterfaces.cs index 3a5df42..84d2486 100644 --- a/src/Pepperdash Core/CoreInterfaces.cs +++ b/src/Pepperdash Core/CoreInterfaces.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; +using Serilog; namespace PepperDash.Core { @@ -15,16 +16,27 @@ namespace PepperDash.Core /// Unique Key /// string Key { get; } - } + } /// - /// Named Keyed device interface. Forces the devie to have a Unique Key and a name. + /// Named Keyed device interface. Forces the device to have a Unique Key and a name. /// public interface IKeyName : IKeyed - { + { /// /// Isn't it obvious :) /// string Name { get; } - } + } + + /// + /// Logging interface for IKeyName + /// + public interface IKeyNameWithLogging : IKeyName + { + /// + /// Logger for the device + /// + ILogger Logger { get; } + } } \ No newline at end of file diff --git a/src/Pepperdash Core/Device.cs b/src/Pepperdash Core/Device.cs index 55d4c15..2ce3b10 100644 --- a/src/Pepperdash Core/Device.cs +++ b/src/Pepperdash Core/Device.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using Serilog; +using Serilog.Core; +using Serilog.Sinks.SystemConsole; namespace PepperDash.Core { @@ -8,8 +11,12 @@ namespace PepperDash.Core /// /// The core event and status-bearing class that most if not all device and connectors can derive from. /// - public class Device : IKeyName + public class Device : IKeyNameWithLogging { + public ILogger Logger { get; private set; } + + private static LoggingLevelSwitch _loggingLevelSwitch; + /// /// Unique Key /// @@ -52,6 +59,9 @@ namespace PepperDash.Core if (key.Contains('.')) Debug.Console(0, this, "WARNING: Device name's should not include '.'"); Name = ""; + _loggingLevelSwitch = new LoggingLevelSwitch(); + + Logger = Serilog.Log.ForContext("Key", Key); } /// diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index a0af198..09dd7b3 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -8,15 +8,47 @@ using Crestron.SimplSharp.CrestronLogger; using Crestron.SimplSharp.CrestronIO; using Full.Newtonsoft.Json; using PepperDash.Core.DebugThings; - +using Serilog; +using Serilog.Core; +using Serilog.Events; +using Serilog.Formatting.Display; +using System.Runtime.Serialization; namespace PepperDash.Core { + public enum eDebugLevel + { + Information = 0, + Warning = 1, + Error = 2, + Fatal = 3, + Debug = 4, + Verbose = 5, + } + /// /// Contains debug commands for use in various situations /// public static class Debug { + private static Dictionary> _logActions = new Dictionary>() + { + {0, (s) => _logger.Information(s) }, + {1, (s) => _logger.Warning(s) }, + {2, (s) => _logger.Error(s) }, + {3, (s) => _logger.Fatal(s) }, + {4, (s) => _logger.Debug(s) }, + {5, (s) => _logger.Verbose(s) }, + }; + + private static Logger _logger; + + private static LoggingLevelSwitch _consoleLoggingLevelSwitch; + + private static LoggingLevelSwitch _websocketLoggingLevelSwitch; + + private static DebugWebsocketSink _websocketSink; + /// /// Describes the folder location where a given program stores it's debug level memory. By default, the /// file written will be named appNdebug where N is 1-10. @@ -67,6 +99,19 @@ namespace PepperDash.Core static Debug() { + _consoleLoggingLevelSwitch = new LoggingLevelSwitch(); + _websocketLoggingLevelSwitch = new LoggingLevelSwitch(); + + // Instantiate the root logger + _logger = new LoggerConfiguration() + .WriteTo.Logger(lc => lc + .WriteTo.Console(levelSwitch: _consoleLoggingLevelSwitch)) + .WriteTo.Sink(new DebugWebsocketSink(), levelSwitch: _websocketLoggingLevelSwitch) + .WriteTo.File(@"\user\debug\global-log-{Date}.txt" + , rollingInterval: RollingInterval.Day + , restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Debug) + .CreateLogger(); + // Get the assembly version and print it to console and the log GetVersion(); @@ -165,6 +210,7 @@ namespace PepperDash.Core /// static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) { + if (programEventType == eProgramStatusEventType.Stopping) { if (_saveTimer != null) @@ -199,6 +245,16 @@ namespace PepperDash.Core } } + public static void SetConsoleDebugLevel(LogEventLevel level) + { + _consoleLoggingLevelSwitch.MinimumLevel = level; + } + + public static void SetWebSocketDebugLevel(LogEventLevel level) + { + + } + /// /// Callback for console command /// @@ -233,7 +289,7 @@ namespace PepperDash.Core CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " + "+all: at beginning puts filter into 'default include' mode\r" + " All keys that follow will be excluded from output.\r" + - "-all: at beginning puts filter into 'default excluse all' mode.\r" + + "-all: at beginning puts filter into 'default exclude all' mode.\r" + " All keys that follow will be the only keys that are shown\r" + "+nokey: Enables messages with no key (default)\r" + "-nokey: Disables messages with no key.\r" + @@ -368,6 +424,12 @@ namespace PepperDash.Core CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine); } + + private static void Log(uint level, string format, params object[] items) + { + + } + /// /// Prints message to console if current debug level is equal to or higher than the level of this message. /// Uses CrestronConsole.PrintLine. @@ -410,6 +472,10 @@ namespace PepperDash.Core public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel, string format, params object[] items) { + var logDevice = dev as IKeyNameWithLogging; + + + var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items)); if (errorLogLevel != ErrorLogLevel.None) { diff --git a/src/Pepperdash Core/Logging/DebugWebsocketSink.cs b/src/Pepperdash Core/Logging/DebugWebsocketSink.cs new file mode 100644 index 0000000..c335759 --- /dev/null +++ b/src/Pepperdash Core/Logging/DebugWebsocketSink.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Serilog; +using Serilog.Core; +using Serilog.Events; +using Serilog.Configuration; +using WebSocketSharp.Server; + +namespace PepperDash.Core +{ + public class DebugWebsocketSink : ILogEventSink + { + public WebSocketServer WSSV { get; private set; } + + private readonly IFormatProvider _formatProvider; + + public DebugWebsocketSink() + { + WSSV = new WebSocketServer(); + + } + + public void Emit(LogEvent logEvent) + { + var message = logEvent.RenderMessage(_formatProvider); + WSSV.WebSocketServices.Broadcast(message); + } + } + + public static class DebugWebsocketSinkExtensions + { + public static LoggerConfiguration DebugWebsocketSink( + this LoggerSinkConfiguration loggerConfiguration, + IFormatProvider formatProvider = null) + { + return loggerConfiguration.Sink(new DebugWebsocketSink()); + } + } +} diff --git a/src/Pepperdash Core/PepperDash_Core.csproj b/src/Pepperdash Core/PepperDash_Core.csproj index 845577b..3100767 100644 --- a/src/Pepperdash Core/PepperDash_Core.csproj +++ b/src/Pepperdash Core/PepperDash_Core.csproj @@ -34,6 +34,10 @@ Full + + + +