feat: Initial implementation of DebugWebsocketSink

This commit is contained in:
Neil Dorin
2023-10-30 17:24:47 -06:00
parent 6174400b7e
commit 2f1180512c
5 changed files with 141 additions and 7 deletions

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Serilog;
namespace PepperDash.Core namespace PepperDash.Core
{ {
@@ -15,16 +16,27 @@ namespace PepperDash.Core
/// Unique Key /// Unique Key
/// </summary> /// </summary>
string Key { get; } string Key { get; }
} }
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
public interface IKeyName : IKeyed public interface IKeyName : IKeyed
{ {
/// <summary> /// <summary>
/// Isn't it obvious :) /// Isn't it obvious :)
/// </summary> /// </summary>
string Name { get; } string Name { get; }
} }
/// <summary>
/// Logging interface for IKeyName
/// </summary>
public interface IKeyNameWithLogging : IKeyName
{
/// <summary>
/// Logger for the device
/// </summary>
ILogger Logger { get; }
}
} }

View File

@@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Serilog;
using Serilog.Core;
using Serilog.Sinks.SystemConsole;
namespace PepperDash.Core namespace PepperDash.Core
{ {
@@ -8,8 +11,12 @@ namespace PepperDash.Core
/// <summary> /// <summary>
/// The core event and status-bearing class that most if not all device and connectors can derive from. /// The core event and status-bearing class that most if not all device and connectors can derive from.
/// </summary> /// </summary>
public class Device : IKeyName public class Device : IKeyNameWithLogging
{ {
public ILogger Logger { get; private set; }
private static LoggingLevelSwitch _loggingLevelSwitch;
/// <summary> /// <summary>
/// Unique Key /// Unique Key
/// </summary> /// </summary>
@@ -52,6 +59,9 @@ namespace PepperDash.Core
if (key.Contains('.')) Debug.Console(0, this, "WARNING: Device name's should not include '.'"); if (key.Contains('.')) Debug.Console(0, this, "WARNING: Device name's should not include '.'");
Name = ""; Name = "";
_loggingLevelSwitch = new LoggingLevelSwitch();
Logger = Serilog.Log.ForContext("Key", Key);
} }
/// <summary> /// <summary>

View File

@@ -8,15 +8,47 @@ using Crestron.SimplSharp.CrestronLogger;
using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronIO;
using Full.Newtonsoft.Json; using Full.Newtonsoft.Json;
using PepperDash.Core.DebugThings; using PepperDash.Core.DebugThings;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Display;
using System.Runtime.Serialization;
namespace PepperDash.Core namespace PepperDash.Core
{ {
public enum eDebugLevel
{
Information = 0,
Warning = 1,
Error = 2,
Fatal = 3,
Debug = 4,
Verbose = 5,
}
/// <summary> /// <summary>
/// Contains debug commands for use in various situations /// Contains debug commands for use in various situations
/// </summary> /// </summary>
public static class Debug public static class Debug
{ {
private static Dictionary<int, Action<string>> _logActions = new Dictionary<int, Action<string>>()
{
{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;
/// <summary> /// <summary>
/// Describes the folder location where a given program stores it's debug level memory. By default, the /// 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. /// file written will be named appNdebug where N is 1-10.
@@ -67,6 +99,19 @@ namespace PepperDash.Core
static Debug() 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 // Get the assembly version and print it to console and the log
GetVersion(); GetVersion();
@@ -165,6 +210,7 @@ namespace PepperDash.Core
/// <param name="programEventType"></param> /// <param name="programEventType"></param>
static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
{ {
if (programEventType == eProgramStatusEventType.Stopping) if (programEventType == eProgramStatusEventType.Stopping)
{ {
if (_saveTimer != null) 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)
{
}
/// <summary> /// <summary>
/// Callback for console command /// Callback for console command
/// </summary> /// </summary>
@@ -233,7 +289,7 @@ namespace PepperDash.Core
CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " + CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " +
"+all: at beginning puts filter into 'default include' mode\r" + "+all: at beginning puts filter into 'default include' mode\r" +
" All keys that follow will be excluded from output.\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" + " All keys that follow will be the only keys that are shown\r" +
"+nokey: Enables messages with no key (default)\r" + "+nokey: Enables messages with no key (default)\r" +
"-nokey: Disables messages with no key.\r" + "-nokey: Disables messages with no key.\r" +
@@ -368,6 +424,12 @@ namespace PepperDash.Core
CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine); CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine);
} }
private static void Log(uint level, string format, params object[] items)
{
}
/// <summary> /// <summary>
/// Prints message to console if current debug level is equal to or higher than the level of this message. /// Prints message to console if current debug level is equal to or higher than the level of this message.
/// Uses CrestronConsole.PrintLine. /// Uses CrestronConsole.PrintLine.
@@ -410,6 +472,10 @@ namespace PepperDash.Core
public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel, public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel,
string format, params object[] items) string format, params object[] items)
{ {
var logDevice = dev as IKeyNameWithLogging;
var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items)); var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items));
if (errorLogLevel != ErrorLogLevel.None) if (errorLogLevel != ErrorLogLevel.None)
{ {

View File

@@ -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());
}
}
}

View File

@@ -34,6 +34,10 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.2"> <PackageReference Include="Newtonsoft.Json" Version="13.0.2">
<Aliases>Full</Aliases> <Aliases>Full</Aliases>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="WebSocketSharp" Version="1.0.3-rc11" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Comm\._GenericSshClient.cs" /> <Compile Remove="Comm\._GenericSshClient.cs" />