diff --git a/src/Pepperdash Core/Comm/ControlPropertiesConfig.cs b/src/Pepperdash Core/Comm/ControlPropertiesConfig.cs index f342f25..ff869f7 100644 --- a/src/Pepperdash Core/Comm/ControlPropertiesConfig.cs +++ b/src/Pepperdash Core/Comm/ControlPropertiesConfig.cs @@ -1,6 +1,7 @@ using System; using Crestron.SimplSharp; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace PepperDash.Core { @@ -12,38 +13,44 @@ namespace PepperDash.Core /// /// The method of control /// + [JsonProperty("method")] + [JsonConverter(typeof(StringEnumConverter))] public eControlMethod Method { get; set; } /// /// The key of the device that contains the control port /// + [JsonProperty("controlPortDevKey", NullValueHandling = NullValueHandling.Ignore)] public string ControlPortDevKey { get; set; } /// /// The number of the control port on the device specified by ControlPortDevKey /// - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value - public uint ControlPortNumber { get; set; } + [JsonProperty("controlPortNumber", NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value + public uint? ControlPortNumber { get; set; } /// /// The name of the control port on the device specified by ControlPortDevKey /// - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value + [JsonProperty("controlPortName", NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value public string ControlPortName { get; set; } /// /// Properties for ethernet based communications /// + [JsonProperty("tcpSshProperties", NullValueHandling = NullValueHandling.Ignore)] public TcpSshPropertiesConfig TcpSshProperties { get; set; } /// /// The filename and path for the IR file /// + [JsonProperty("irFile", NullValueHandling = NullValueHandling.Ignore)] public string IrFile { get; set; } /// /// The IpId of a Crestron device /// + [JsonProperty("ipId", NullValueHandling = NullValueHandling.Ignore)] public string IpId { get; set; } /// @@ -55,29 +62,32 @@ namespace PepperDash.Core /// /// Char indicating end of line /// + [JsonProperty("endOfLineChar", NullValueHandling = NullValueHandling.Ignore)] public char EndOfLineChar { get; set; } /// /// Defaults to Environment.NewLine; /// + [JsonProperty("endOfLineString", NullValueHandling = NullValueHandling.Ignore)] public string EndOfLineString { get; set; } /// /// Indicates /// + [JsonProperty("deviceReadyResponsePattern", NullValueHandling = NullValueHandling.Ignore)] public string DeviceReadyResponsePattern { get; set; } /// /// Used when communcating to programs running in VC-4 /// + [JsonProperty("roomId", NullValueHandling = NullValueHandling.Ignore)] public string RoomId { get; set; } /// /// Constructor /// public ControlPropertiesConfig() - { - EndOfLineString = CrestronEnvironment.NewLine; + { } } } \ No newline at end of file diff --git a/src/Pepperdash Core/Logging/CrestronEnricher.cs b/src/Pepperdash Core/Logging/CrestronEnricher.cs new file mode 100644 index 0000000..902ce8d --- /dev/null +++ b/src/Pepperdash Core/Logging/CrestronEnricher.cs @@ -0,0 +1,37 @@ +using Crestron.SimplSharp; +using Serilog.Core; +using Serilog.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Core.Logging +{ + public class CrestronEnricher : ILogEventEnricher + { + static readonly string _appName; + + static CrestronEnricher() + { + switch (CrestronEnvironment.DevicePlatform) + { + case eDevicePlatform.Appliance: + _appName = $"App {InitialParametersClass.ApplicationNumber}"; + break; + case eDevicePlatform.Server: + _appName = $"{InitialParametersClass.RoomId}"; + break; + } + } + + + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + var property = propertyFactory.CreateProperty("App", _appName); + + logEvent.AddOrUpdateProperty(property); + } + } +} diff --git a/src/Pepperdash Core/Logging/Debug.cs b/src/Pepperdash Core/Logging/Debug.cs index 1cf916a..4e79a60 100644 --- a/src/Pepperdash Core/Logging/Debug.cs +++ b/src/Pepperdash Core/Logging/Debug.cs @@ -10,6 +10,7 @@ using Serilog.Core; using Serilog.Events; using Serilog.Formatting.Compact; using Serilog.Formatting.Json; +using Serilog.Templates; using System; using System.Collections.Generic; using System.Reflection; @@ -143,12 +144,17 @@ namespace PepperDash.Core CrestronConsole.PrintLine($"Saving log files to {logFilePath}"); + var errorLogTemplate = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance + ? "{@t:fff}ms [{@l:u4}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}" + : "[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}"; + _defaultLoggerConfiguration = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() - .WriteTo.Sink(new DebugConsoleSink(new JsonFormatter(renderMessage: true)), levelSwitch: _consoleLoggingLevelSwitch) + .Enrich.With(new CrestronEnricher()) + .WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLoggingLevelSwitch) .WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch) - .WriteTo.Sink(new DebugErrorLogSink(), levelSwitch: _errorLogLevelSwitch) + .WriteTo.Sink(new DebugErrorLogSink(new ExpressionTemplate(errorLogTemplate)), levelSwitch: _errorLogLevelSwitch) .WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath, rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug, @@ -187,7 +193,7 @@ namespace PepperDash.Core CrestronConsole.PrintLine(msg); - LogError(ErrorLogLevel.Notice, msg); + LogMessage(LogEventLevel.Information,msg); IncludedExcludedKeys = new Dictionary(); @@ -591,7 +597,7 @@ namespace PepperDash.Core /// Args to put into message template public static void LogMessage(Exception ex, string message, IKeyed device = null, params object[] args) { - using (LogContext.PushProperty("Key", device?.Key ?? string.Empty)) + using (LogContext.PushProperty("Key", device?.Key)) { _logger.Error(ex, message, args); } @@ -606,7 +612,7 @@ namespace PepperDash.Core /// Args to put into message template public static void LogMessage(LogEventLevel level, string message, IKeyed device=null, params object[] args) { - using (LogContext.PushProperty("Key", device?.Key ?? string.Empty)) + using (LogContext.PushProperty("Key", device?.Key)) { _logger.Write(level, message, args); } @@ -655,14 +661,6 @@ namespace PepperDash.Core LogMessage(level, format, items); - if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) - { - var logString = string.Format("[level {0}] {1}", level, string.Format(format, items)); - - LogError(ErrorLogLevel.Notice, logString); - return; - } - //if (IsRunningOnAppliance) //{ // CrestronConsole.PrintLine("[{0}]App {1} Lvl {2}:{3}", DateTime.Now.ToString("HH:mm:ss.fff"), @@ -691,25 +689,8 @@ namespace PepperDash.Core [Obsolete("Use LogMessage methods")] public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel, string format, params object[] items) - { - - var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items)); - if (errorLogLevel != ErrorLogLevel.None) - { - LogError(errorLogLevel, str); - } - + { LogMessage(level, dev, format, items); - - //var log = _logger.ForContext("Key", dev.Key); - //var message = string.Format(format, items); - - //log.Write((LogEventLevel)level, message); - - //if (Level >= level) - //{ - // Console(level, str); - //} } /// @@ -719,17 +700,7 @@ namespace PepperDash.Core public static void Console(uint level, ErrorLogLevel errorLogLevel, string format, params object[] items) { - var str = string.Format(format, items); - if (errorLogLevel != ErrorLogLevel.None) - { - LogError(errorLogLevel, str); - } - LogMessage(level, format, items); - //if (Level >= level) - //{ - // Console(level, str); - //} } /// @@ -770,18 +741,16 @@ namespace PepperDash.Core [Obsolete("Use LogMessage methods")] public static void LogError(ErrorLogLevel errorLogLevel, string str) { - - var msg = IsRunningOnAppliance ? string.Format("App {0}:{1}", InitialParametersClass.ApplicationNumber, str) : string.Format("Room {0}:{1}", InitialParametersClass.RoomId, str); switch (errorLogLevel) { case ErrorLogLevel.Error: - ErrorLog.Error(msg); + LogMessage(LogEventLevel.Error, str); break; case ErrorLogLevel.Warning: - ErrorLog.Warn(msg); + LogMessage(LogEventLevel.Warning, str); break; case ErrorLogLevel.Notice: - ErrorLog.Notice(msg); + LogMessage(LogEventLevel.Information, str); break; } } diff --git a/src/Pepperdash Core/Logging/DebugConsoleSink.cs b/src/Pepperdash Core/Logging/DebugConsoleSink.cs index 990d47b..a6c7f89 100644 --- a/src/Pepperdash Core/Logging/DebugConsoleSink.cs +++ b/src/Pepperdash Core/Logging/DebugConsoleSink.cs @@ -5,6 +5,8 @@ using Serilog.Core; using Serilog.Events; using Serilog.Formatting; using Serilog.Formatting.Json; +using System.IO; +using System.Text; namespace PepperDash.Core @@ -17,12 +19,18 @@ namespace PepperDash.Core { if (!Debug.IsRunningOnAppliance) return; - string message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}]{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,3}]: {logEvent.RenderMessage()}"; - } + }*/ + + var buffer = new StringWriter(new StringBuilder(256)); + + _textFormatter.Format(logEvent, buffer); + + var message = buffer.ToString(); CrestronConsole.PrintLine(message); } diff --git a/src/Pepperdash Core/Logging/DebugErrorLogSink.cs b/src/Pepperdash Core/Logging/DebugErrorLogSink.cs index b5bbb09..3885982 100644 --- a/src/Pepperdash Core/Logging/DebugErrorLogSink.cs +++ b/src/Pepperdash Core/Logging/DebugErrorLogSink.cs @@ -1,8 +1,10 @@ using Crestron.SimplSharp; using Serilog.Core; using Serilog.Events; +using Serilog.Formatting; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -11,6 +13,8 @@ namespace PepperDash.Core.Logging { public class DebugErrorLogSink : ILogEventSink { + private ITextFormatter _formatter; + private Dictionary> _errorLogMap = new Dictionary> { { LogEventLevel.Verbose, (msg) => ErrorLog.Notice(msg) }, @@ -22,15 +26,27 @@ namespace PepperDash.Core.Logging }; public void Emit(LogEvent logEvent) { - var programId = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance - ? $"App {InitialParametersClass.ApplicationNumber}" - : $"Room {InitialParametersClass.RoomId}"; + string message; - string message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}]{logEvent.RenderMessage()}"; - - if (logEvent.Properties.TryGetValue("Key", out var value) && value is ScalarValue sv && sv.Value is string rawValue) + if (_formatter == null) { - message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}][{rawValue}]: {logEvent.RenderMessage()}"; + var programId = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance + ? $"App {InitialParametersClass.ApplicationNumber}" + : $"Room {InitialParametersClass.RoomId}"; + + message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}]{logEvent.RenderMessage()}"; + + if (logEvent.Properties.TryGetValue("Key", out var value) && value is ScalarValue sv && sv.Value is string rawValue) + { + message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}][{rawValue}]: {logEvent.RenderMessage()}"; + } + } else + { + var buffer = new StringWriter(new StringBuilder(256)); + + _formatter.Format(logEvent, buffer); + + message = buffer.ToString(); } if(!_errorLogMap.TryGetValue(logEvent.Level, out var handler)) @@ -40,5 +56,10 @@ namespace PepperDash.Core.Logging handler(message); } + + public DebugErrorLogSink(ITextFormatter formatter = null) + { + _formatter = formatter; + } } } diff --git a/src/Pepperdash Core/Logging/DebugExtensions.cs b/src/Pepperdash Core/Logging/DebugExtensions.cs new file mode 100644 index 0000000..e37e6d9 --- /dev/null +++ b/src/Pepperdash Core/Logging/DebugExtensions.cs @@ -0,0 +1,39 @@ +using Serilog; +using Serilog.Events; +using Log = PepperDash.Core.Debug; + +namespace PepperDash.Core.Logging +{ + public static class DebugExtensions + { + public static void LogVerbose(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Verbose, device, message, args); + } + + public static void LogDebug(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Debug, device, message, args); + } + + public static void LogInformation(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Information, device, message, args); + } + + public static void LogWarning(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Warning, device, message, args); + } + + public static void LogError(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Error, device, message, args); + } + + public static void LogFatal(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Fatal, device, message, args); + } + } +} diff --git a/src/Pepperdash Core/PepperDash_Core.csproj b/src/Pepperdash Core/PepperDash_Core.csproj index 0a9b74a..f00b2e3 100644 --- a/src/Pepperdash Core/PepperDash_Core.csproj +++ b/src/Pepperdash Core/PepperDash_Core.csproj @@ -42,10 +42,11 @@ - + + - +