Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Debug Logging #173

Merged
merged 3 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/Pepperdash Core/Device.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Serilog;
using Serilog.Core;
using Serilog.Sinks.SystemConsole;
using Serilog.Events;

namespace PepperDash.Core
{
Expand Down Expand Up @@ -53,7 +50,7 @@ public class Device : IKeyName
public Device(string key)
{
Key = key;
if (key.Contains('.')) Debug.Console(0, this, "WARNING: Device name's should not include '.'");
if (key.Contains(".")) Debug.LogMessage(LogEventLevel.Information, "WARNING: Device key should not include '.'", this);
Name = "";
}

Expand Down
108 changes: 88 additions & 20 deletions src/Pepperdash Core/Logging/Debug.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using System.Reflection;
using Crestron.SimplSharp.CrestronLogger;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.CrestronLogger;
using Newtonsoft.Json;
using PepperDash.Core.DebugThings;
using PepperDash.Core.Logging;
using Serilog;
using Serilog.Context;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Json;
using Crestron.SimplSharp.CrestronDataStore;
using PepperDash.Core.Logging;
using Serilog.Formatting.Compact;
using Serilog.Formatting.Json;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;

namespace PepperDash.Core
{
Expand All @@ -24,6 +24,8 @@ public static class Debug
{
private static readonly string LevelStoreKey = "ConsoleDebugLevel";
private static readonly string WebSocketLevelStoreKey = "WebsocketDebugLevel";
private static readonly string ErrorLogLevelStoreKey = "ErrorLogDebugLevel";
private static readonly string FileLevelStoreKey = "FileDebugLevel";

private static readonly Dictionary<uint, LogEventLevel> _logLevels = new Dictionary<uint, LogEventLevel>()
{
Expand All @@ -35,12 +37,16 @@ public static class Debug
{2, LogEventLevel.Verbose },
};

private static Logger _logger;
private static ILogger _logger;

private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch;

private static readonly LoggingLevelSwitch _websocketLoggingLevelSwitch;

private static readonly LoggingLevelSwitch _errorLogLevelSwitch;

private static readonly LoggingLevelSwitch _fileLevelSwitch;

public static LogEventLevel WebsocketMinimumLogLevel
{
get { return _websocketLoggingLevelSwitch.MinimumLevel; }
Expand Down Expand Up @@ -117,10 +123,18 @@ static Debug()

var defaultWebsocketLevel = GetStoredLogEventLevel(WebSocketLevelStoreKey);

var defaultErrorLogLevel = GetStoredLogEventLevel(ErrorLogLevelStoreKey);

var defaultFileLogLevel = GetStoredLogEventLevel(FileLevelStoreKey);

_consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel);

_websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel);

_errorLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultErrorLogLevel);

_fileLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultFileLogLevel);

_websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true));

var logFilePath = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ?
Expand All @@ -131,13 +145,15 @@ static Debug()

_defaultLoggerConfiguration = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.WriteTo.Sink(new DebugConsoleSink(new JsonFormatter(renderMessage: true)), levelSwitch: _consoleLoggingLevelSwitch)
.WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch)
.WriteTo.Sink(new DebugErrorLogSink(), LogEventLevel.Information)
.WriteTo.Sink(new DebugErrorLogSink(), levelSwitch: _errorLogLevelSwitch)
.WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath,
rollingInterval: RollingInterval.Day,
restrictedToMinimumLevel: LogEventLevel.Debug,
retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60
retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60,
levelSwitch: _fileLevelSwitch
);

try
Expand Down Expand Up @@ -387,9 +403,33 @@ public static void SetWebSocketMinimumDebugLevel(LogEventLevel level)
var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint) level);

if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
Console(0, "Error saving websocket debug level setting: {0}", err);
LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err);

Console(0, "Websocket debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
}

public static void SetErrorLogMinimumDebugLevel(LogEventLevel level)
{
_errorLogLevelSwitch.MinimumLevel = level;

var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level);

if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
LogMessage(LogEventLevel.Information, "Error saving Error Log debug level setting: {error}", err);

LogMessage(LogEventLevel.Information, "Error log debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
}

public static void SetFileMinimumDebugLevel(LogEventLevel level)
{
_errorLogLevelSwitch.MinimumLevel = level;

var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level);

if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
LogMessage(LogEventLevel.Information, "Error saving File debug level setting: {error}", err);

LogMessage(LogEventLevel.Information, "File debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
}

/// <summary>
Expand Down Expand Up @@ -542,16 +582,44 @@ public static void ShowDebugLog(string s)
CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine);
}

/// <summary>
/// Log an Exception using Serilog's default Exception logging mechanism
/// </summary>
/// <param name="ex">Exception to log</param>
/// <param name="message">Message template</param>
/// <param name="device">Optional IKeyed device. If provided, the Key of the device will be added to the log message</param>
/// <param name="args">Args to put into message template</param>
public static void LogMessage(Exception ex, string message, IKeyed device = null, params object[] args)
{
using (LogContext.PushProperty("Key", device?.Key ?? string.Empty))
{
_logger.Error(ex, message, args);
}
}

/// <summary>
/// Log a message
/// </summary>
/// <param name="level">Level to log at</param>
/// <param name="message">Message template</param>
/// <param name="device">Optional IKeyed device. If provided, the Key of the device will be added to the log message</param>
/// <param name="args">Args to put into message template</param>
public static void LogMessage(LogEventLevel level, string message, IKeyed device=null, params object[] args)
{
using (LogContext.PushProperty("Key", device?.Key ?? string.Empty))
{
_logger.Write(level, message, args);
}
}

public static void LogMessage(LogEventLevel level, string message, params object[] args)
{
_logger.Write(level, message, args);
LogMessage(level, message, null, 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);
LogMessage(level, message, keyed, args);
}


Expand All @@ -561,7 +629,7 @@ private static void LogMessage(uint level, string format, params object[] items)

var logLevel = _logLevels[level];

LogMessage(logLevel, format, items );
LogMessage(logLevel, format, items);
}

private static void LogMessage(uint level, IKeyed keyed, string format, params object[] items)
Expand Down
9 changes: 2 additions & 7 deletions src/Pepperdash Core/Logging/DebugConsoleSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Formatting.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;


namespace PepperDash.Core
{
Expand All @@ -26,7 +21,7 @@ public void Emit(LogEvent logEvent)

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()}";
message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}][{rawValue,3}]: {logEvent.RenderMessage()}";
}

CrestronConsole.PrintLine(message);
Expand Down
2 changes: 1 addition & 1 deletion src/Pepperdash Core/Logging/DebugMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Crestron.SimplSharp;
using Newtonsoft.Json;

namespace PepperDash.Core.DebugThings
namespace PepperDash.Core.Logging
{
/// <summary>
/// Class to persist current Debug settings across program restarts
Expand Down
Loading