diff --git a/libraries/MTConnect.NET-Common/Adapters/MTConnectAdapter.cs b/libraries/MTConnect.NET-Common/Adapters/MTConnectAdapter.cs index 986c850e..f4c3857d 100644 --- a/libraries/MTConnect.NET-Common/Adapters/MTConnectAdapter.cs +++ b/libraries/MTConnect.NET-Common/Adapters/MTConnectAdapter.cs @@ -4,10 +4,11 @@ using MTConnect.Input; using System; using System.Collections.Generic; -using System.Data; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using MTConnect.Logging; namespace MTConnect.Adapters { @@ -20,6 +21,7 @@ public class MTConnectAdapter : IMTConnectAdapter private readonly object _lock = new object(); private readonly int? _interval; private readonly bool _bufferEnabled; + private readonly ILogger _logger; private readonly Dictionary _currentDevices = new Dictionary(); private readonly Dictionary _lastDevices = new Dictionary(); @@ -80,10 +82,14 @@ public class MTConnectAdapter : IMTConnectAdapter public event EventHandler> SendError; - public MTConnectAdapter(int? interval = null, bool bufferEnabled = false) + public MTConnectAdapter( + int? interval = null, + bool bufferEnabled = false, + ILogger logger = null) { _interval = interval; _bufferEnabled = bufferEnabled; + _logger = logger; FilterDuplicates = true; OutputTimestamps = true; @@ -304,6 +310,14 @@ public void AddObservation(IObservationInput observation) _observationsBuffer.Add(CreateUniqueId(newObservation), newObservation); + if (_logger?.IsEnabled(LogLevel.Trace) == true) + { + var values = string.Join(",", observation.Values.Select(v => $"{v.Key}/{v.Value}")); + _logger?.LogTrace( + $"{nameof(MTConnectAdapter)}:{DateTime.Now.ToString("hh:mm:ss.ffffff")} Data item added in adapter {newObservation.DataItemKey}:{values}."); + + } + // Call Overridable Method OnObservationAdd(newObservation); } @@ -446,6 +460,8 @@ protected bool WriteChangedObservations() if (!dataItems.IsNullOrEmpty()) { + LogReporter.Report($"Sending {dataItems.Count} changed items...", _logger); + var success = Write(dataItems); if (success) { @@ -505,6 +521,8 @@ public bool WriteBufferObservations(int count = 1000) sendObservations.Add(sendObservation); } + LogReporter.Report($"Sending {sendObservations.Count} buffered items...", _logger); + var success = Write(sendObservations); if (success) { diff --git a/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs b/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs index 6f637215..eeb35586 100644 --- a/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs +++ b/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs @@ -1,6 +1,7 @@ // Copyright (c) 2024 TrakHound Inc., All Rights Reserved. // TrakHound Inc. licenses this file to you under the MIT license. +using Microsoft.Extensions.Logging; using MTConnect.Agents.Metrics; using MTConnect.Assets; using MTConnect.Configurations; @@ -14,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using MTConnect.Logging; namespace MTConnect.Agents { @@ -54,7 +56,7 @@ public class MTConnectAgent : IMTConnectAgent, IDisposable private string _sender; private System.Timers.Timer _informationUpdateTimer; private bool _updateInformation; - + protected readonly ILogger _logger; #region "Properties" @@ -200,7 +202,8 @@ public MTConnectAgent( string uuid = null, ulong instanceId = 0, long deviceModelChangeTime = 0, - bool initializeAgentDevice = true + bool initializeAgentDevice = true, + ILogger logger = null ) { _uuid = !string.IsNullOrEmpty(uuid) ? uuid : Guid.NewGuid().ToString(); @@ -208,6 +211,7 @@ public MTConnectAgent( _configuration = new AgentConfiguration(); _information = new MTConnectAgentInformation(_uuid, _instanceId, _deviceModelChangeTime); _deviceModelChangeTime = deviceModelChangeTime; + _logger = logger; _mtconnectVersion = MTConnectVersions.Max; _version = GetAgentVersion(); InitializeAgentDevice(initializeAgentDevice); @@ -218,7 +222,8 @@ public MTConnectAgent( string uuid = null, ulong instanceId = 0, long deviceModelChangeTime = 0, - bool initializeAgentDevice = true + bool initializeAgentDevice = true, + ILogger logger = null ) { _uuid = !string.IsNullOrEmpty(uuid) ? uuid : Guid.NewGuid().ToString(); @@ -226,6 +231,7 @@ public MTConnectAgent( _configuration = configuration != null ? configuration : new AgentConfiguration(); _information = new MTConnectAgentInformation(_uuid, _instanceId, _deviceModelChangeTime); _deviceModelChangeTime = deviceModelChangeTime; + _logger = logger; _mtconnectVersion = _configuration != null && _configuration.DefaultVersion != null ? _configuration.DefaultVersion : MTConnectVersions.Max; _version = GetAgentVersion(); InitializeAgentDevice(initializeAgentDevice); @@ -814,6 +820,15 @@ protected bool CheckCurrentObservation(string deviceUuid, IDataItem dataItem, IO // Check Filters var update = FilterPeriod(dataItem, timestamp, existingTimestamp); + if (!update) + { + if (_logger?.IsEnabled(LogLevel.Trace) == true) + { + _logger?.LogTrace( + $"FilterPeriod {dataItem.Id}: {observation.Timestamp.ToDateTime():o} & {existingTimestamp.ToDateTime():o} ."); + } + } + if (update) update = FilterDelta(dataItem, observation, existingObservationInput); // Update if Filters are passed or if the DataItem is set to Discrete @@ -1648,7 +1663,11 @@ private string Remove3dSuffix(string s) /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(IDataItem dataItem, object value, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + IDataItem dataItem, + object value, + bool? convertUnits = null, + bool? ignoreCase = null) { if (dataItem != null && dataItem.Device != null && !string.IsNullOrEmpty(dataItem.Device.Uuid) && !string.IsNullOrEmpty(dataItem.Id)) { @@ -1675,7 +1694,12 @@ public bool AddObservation(IDataItem dataItem, object value, bool? convertUnits /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(string deviceKey, string dataItemKey, object value, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + string deviceKey, + string dataItemKey, + object value, + bool? convertUnits = null, + bool? ignoreCase = null) { var input = new ObservationInput { @@ -1697,7 +1721,12 @@ public bool AddObservation(string deviceKey, string dataItemKey, object value, b /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(IDataItem dataItem, object value, long timestamp, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + IDataItem dataItem, + object value, + long timestamp, + bool? convertUnits = null, + bool? ignoreCase = null) { if (dataItem != null && dataItem.Device != null && !string.IsNullOrEmpty(dataItem.Device.Uuid) && !string.IsNullOrEmpty(dataItem.Id)) { @@ -1725,7 +1754,13 @@ public bool AddObservation(IDataItem dataItem, object value, long timestamp, boo /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(string deviceKey, string dataItemKey, object value, long timestamp, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + string deviceKey, + string dataItemKey, + object value, + long timestamp, + bool? convertUnits = null, + bool? ignoreCase = null) { return AddObservation(new ObservationInput { @@ -1745,7 +1780,12 @@ public bool AddObservation(string deviceKey, string dataItemKey, object value, l /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(IDataItem dataItem, object value, DateTime timestamp, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + IDataItem dataItem, + object value, + DateTime timestamp, + bool? convertUnits = null, + bool? ignoreCase = null) { if (dataItem != null && dataItem.Device != null && !string.IsNullOrEmpty(dataItem.Device.Uuid) && !string.IsNullOrEmpty(dataItem.Id)) { @@ -1773,7 +1813,13 @@ public bool AddObservation(IDataItem dataItem, object value, DateTime timestamp, /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(string deviceKey, string dataItemKey, object value, DateTime timestamp, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + string deviceKey, + string dataItemKey, + object value, + DateTime timestamp, + bool? convertUnits = null, + bool? ignoreCase = null) { return AddObservation(new ObservationInput { @@ -1794,7 +1840,13 @@ public bool AddObservation(string deviceKey, string dataItemKey, object value, D /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(string deviceKey, string dataItemKey, string valueKey, object value, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + string deviceKey, + string dataItemKey, + string valueKey, + object value, + bool? convertUnits = null, + bool? ignoreCase = null) { return AddObservation(new ObservationInput { @@ -1816,7 +1868,14 @@ public bool AddObservation(string deviceKey, string dataItemKey, string valueKey /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(string deviceKey, string dataItemKey, string valueKey, object value, long timestamp, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + string deviceKey, + string dataItemKey, + string valueKey, + object value, + long timestamp, + bool? convertUnits = null, + bool? ignoreCase = null) { return AddObservation(new ObservationInput { @@ -1838,7 +1897,14 @@ public bool AddObservation(string deviceKey, string dataItemKey, string valueKey /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(string deviceKey, string dataItemKey, string valueKey, object value, DateTime timestamp, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + string deviceKey, + string dataItemKey, + string valueKey, + object value, + DateTime timestamp, + bool? convertUnits = null, + bool? ignoreCase = null) { return AddObservation(new ObservationInput { @@ -1857,7 +1923,11 @@ public bool AddObservation(string deviceKey, string dataItemKey, string valueKey /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(IObservationInput observationInput, bool? ignoreTimestamp = null, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + IObservationInput observationInput, + bool? ignoreTimestamp = null, + bool? convertUnits = null, + bool? ignoreCase = null) { if (observationInput != null && !string.IsNullOrEmpty(observationInput.DeviceKey)) { @@ -1876,7 +1946,12 @@ public bool AddObservation(IObservationInput observationInput, bool? ignoreTimes /// Used to override the default configuration for the Agent to ConvertUnits /// Used to override the default configuration for the Agent to IgnoreCase of the Value /// True if the Observation was added successfully - public bool AddObservation(string deviceKey, IObservationInput observationInput, bool? ignoreTimestamp = null, bool? convertUnits = null, bool? ignoreCase = null) + public bool AddObservation( + string deviceKey, + IObservationInput observationInput, + bool? ignoreTimestamp = null, + bool? convertUnits = null, + bool? ignoreCase = null) { if (observationInput != null) { @@ -1984,9 +2059,22 @@ public bool AddObservation(string deviceKey, IObservationInput observationInput, OnObservationAdded(observation); success = true; + + if (_logger?.IsEnabled(LogLevel.Trace) == true) + { + var values = string.Join(",", observation.Values.Select(v => $"{v.Key}/{v.Value}")); + _logger?.LogTrace( + $"{nameof(MTConnectAgent)}:{DateTime.Now.ToString("hh:mm:ss.ffffff")} Data item added async in agent {observation.DataItemId}:{values} with success."); + } } + + LogReporter.Report($"Added data item {dataItem.Id} to buffer with {success}.", _logger); + } + else + { + LogReporter.Report($"Skipped adding data item {dataItem.Id}.", _logger); + success = true; // Return true if no update needed } - else success = true; // Return true if no update needed } if (!validationResult.IsValid && InvalidObservationAdded != null) @@ -2005,7 +2093,6 @@ public bool AddObservation(string deviceKey, IObservationInput observationInput, return false; } - /// /// Add new Observations for DataItems to the Agent /// diff --git a/libraries/MTConnect.NET-Common/Agents/MTConnectAgentBroker.cs b/libraries/MTConnect.NET-Common/Agents/MTConnectAgentBroker.cs index 66bea397..1be25cc2 100644 --- a/libraries/MTConnect.NET-Common/Agents/MTConnectAgentBroker.cs +++ b/libraries/MTConnect.NET-Common/Agents/MTConnectAgentBroker.cs @@ -15,6 +15,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Logging; namespace MTConnect.Agents { @@ -147,8 +148,9 @@ public MTConnectAgentBroker( string uuid = null, ulong instanceId = 0, long deviceModelChangeTime = 0, - bool initializeAgentDevice = true - ) : base(uuid, instanceId, deviceModelChangeTime, false) + bool initializeAgentDevice = true, + ILogger logger = null + ) : base(uuid, instanceId, deviceModelChangeTime, false, logger) { var config = new AgentConfiguration(); //_deviceBuffer = new MTConnectDeviceBuffer(); @@ -163,8 +165,9 @@ public MTConnectAgentBroker( string uuid = null, ulong instanceId = 0, long deviceModelChangeTime = 0, - bool initializeAgentDevice = true - ) : base(configuration, uuid, instanceId, deviceModelChangeTime, false) + bool initializeAgentDevice = true, + ILogger logger = null + ) : base(configuration, uuid, instanceId, deviceModelChangeTime, false, logger) { var config = configuration != null ? configuration : new AgentConfiguration(); //_deviceBuffer = new MTConnectDeviceBuffer(); @@ -180,8 +183,9 @@ public MTConnectAgentBroker( string uuid = null, ulong instanceId = 0, long deviceModelChangeTime = 0, - bool initializeAgentDevice = true - ) : base(uuid, instanceId, deviceModelChangeTime, false) + bool initializeAgentDevice = true, + ILogger logger = null + ) : base(uuid, instanceId, deviceModelChangeTime, false, logger) { var config = new AgentConfiguration(); _observationBuffer = observationBuffer != null ? observationBuffer : new MTConnectObservationBuffer(config); @@ -197,8 +201,9 @@ public MTConnectAgentBroker( string uuid = null, ulong instanceId = 0, long deviceModelChangeTime = 0, - bool initializeAgentDevice = true - ) : base(configuration, uuid, instanceId, deviceModelChangeTime, false) + bool initializeAgentDevice = true, + ILogger logger = null + ) : base(configuration, uuid, instanceId, deviceModelChangeTime, false, logger) { var config = configuration != null ? configuration : new AgentConfiguration(); _observationBuffer = observationBuffer != null ? observationBuffer : new MTConnectObservationBuffer(config); diff --git a/libraries/MTConnect.NET-Common/Logging/LogReporter.cs b/libraries/MTConnect.NET-Common/Logging/LogReporter.cs new file mode 100644 index 00000000..561977b4 --- /dev/null +++ b/libraries/MTConnect.NET-Common/Logging/LogReporter.cs @@ -0,0 +1,80 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace MTConnect.Logging +{ + public static class LogReporter + { + #region Private Methods + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static string GetPlacement( + string sourceFilePath, + int sourceLineNumber) + { + return $"[{Path.GetFileNameWithoutExtension(sourceFilePath)}, {sourceLineNumber}]"; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static string Now() + { + return DateTime.Now.ToString("hh:mm:ss.ffffff"); + } + + #endregion + + public static async Task MeasureAndReport( + Func> operation, + string operationName, + ILogger logger, + [CallerFilePath] string sourceFilePath = "", + [CallerLineNumber] int sourceLineNumber = 0) + { + var stopwatch = Stopwatch.StartNew(); + var result = await operation(); + stopwatch.Stop(); + + if (logger?.IsEnabled(LogLevel.Trace) == true) + { + logger?.LogTrace( + $"{GetPlacement(sourceFilePath, sourceLineNumber)} {Now()} {operationName} in {stopwatch.ElapsedMilliseconds} ms."); + } + + return result; + } + + public static void MeasureAndReport( + Action operation, + string operationName, + ILogger logger, + [CallerFilePath] string sourceFilePath = "", + [CallerLineNumber] int sourceLineNumber = 0) + { + var stopwatch = Stopwatch.StartNew(); + operation(); + stopwatch.Stop(); + + if (logger?.IsEnabled(LogLevel.Trace) == true) + { + logger?.LogTrace($"{GetPlacement(sourceFilePath, sourceLineNumber)} {Now()} {operationName} in {stopwatch.ElapsedMilliseconds} ms."); + } + } + + public static void Report( + string report, + ILogger logger, + [CallerFilePath] string sourceFilePath = "", + [CallerLineNumber] int sourceLineNumber = 0) + { + if (logger?.IsEnabled(LogLevel.Trace) == true) + { + logger?.LogTrace($"{GetPlacement(sourceFilePath, sourceLineNumber)} {Now()} {report}"); + } + } + + } +} diff --git a/libraries/MTConnect.NET-Common/MTConnect.NET-Common.csproj b/libraries/MTConnect.NET-Common/MTConnect.NET-Common.csproj index 6acf7074..b7ee85f1 100644 --- a/libraries/MTConnect.NET-Common/MTConnect.NET-Common.csproj +++ b/libraries/MTConnect.NET-Common/MTConnect.NET-Common.csproj @@ -112,6 +112,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClient.cs b/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClient.cs index a6332839..954d3ec0 100644 --- a/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClient.cs +++ b/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClient.cs @@ -1,19 +1,21 @@ // Copyright (c) 2024 TrakHound Inc., All Rights Reserved. // TrakHound Inc. licenses this file to you under the MIT license. +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using MTConnect.Assets; using MTConnect.Devices; using MTConnect.Errors; using MTConnect.Formatters; using MTConnect.Headers; using MTConnect.Http; +using MTConnect.Logging; using MTConnect.Observations; using MTConnect.Streams; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; namespace MTConnect.Clients { @@ -34,7 +36,7 @@ public class MTConnectHttpClient : IMTConnectClient, IMTConnectEntityClient private long _lastResponse; private bool _initializeFromBuffer; private string _streamPath; - + private ILogger _logger; /// /// Initializes a new instance of the MTConnectClient class that is used to perform @@ -50,13 +52,19 @@ public class MTConnectHttpClient : IMTConnectClient, IMTConnectEntityClient /// If not present, Metadata for all pieces of equipment associated with the Agent will be published. /// /// Gets or Sets the Document Format to return - public MTConnectHttpClient(string authority, string device = null, string documentFormat = MTConnect.DocumentFormat.XML) + /// instance. + public MTConnectHttpClient( + string authority, + string device = null, + string documentFormat = MTConnect.DocumentFormat.XML, + ILogger logger = null) { Id = Guid.NewGuid().ToString(); Init(); Authority = authority; Device = device; DocumentFormat = documentFormat; + _logger = logger; } /// @@ -74,13 +82,20 @@ public MTConnectHttpClient(string authority, string device = null, string docume /// If not present, Metadata for all pieces of equipment associated with the Agent will be published. /// /// Gets or Sets the Document Format to return - public MTConnectHttpClient(string hostname, int port, string device = null, string documentFormat = MTConnect.DocumentFormat.XML) + /// instance. + public MTConnectHttpClient( + string hostname, + int port, + string device = null, + string documentFormat = MTConnect.DocumentFormat.XML, + ILogger logger = null) { Id = Guid.NewGuid().ToString(); Init(); Authority = CreateUrl(hostname, port); Device = device; DocumentFormat = documentFormat; + _logger = logger; } private void Init() @@ -97,7 +112,7 @@ private void Init() /// - /// A unique Identifier used to indentify this instance of the MTConnectClient class + /// A unique Identifier used to identify this instance of the MTConnectClient class /// public string Id { get; set; } @@ -649,13 +664,20 @@ private async Task Worker() try { // Run Probe Request - var probe = await GetProbeAsync(_stop.Token); + var probe = await LogReporter.MeasureAndReport( + () => GetProbeAsync(_stop.Token), + $"got probe", + _logger); + if (probe != null) { _lastResponse = UnixDateTime.Now; - ResponseReceived?.Invoke(this, new EventArgs()); + ResponseReceived?.Invoke(this, new EventArgs()); - ProcessProbeDocument(probe); + LogReporter.MeasureAndReport( + () => ProcessProbeDocument(probe), + $"probe processed", + _logger); // Get All Assets if (probe.Header.AssetCount > 0) @@ -673,14 +695,21 @@ private async Task Worker() if (UseStreaming) { // Run Current Request - var current = await GetCurrentAsync(_stop.Token, path: _streamPath); + var current = await LogReporter.MeasureAndReport( + () => GetCurrentAsync(_stop.Token, path: _streamPath), + $"got current", + _logger); + if (current != null) { _lastResponse = UnixDateTime.Now; ResponseReceived?.Invoke(this, new EventArgs()); - // Raise CurrentReceived Event - ProcessCurrentDocument(current, _stop.Token); + // Raise CurrentReceived Event; + LogReporter.MeasureAndReport( + () => ProcessCurrentDocument(current, _stop.Token), + $"current processed", + _logger); // Check Assets if (!current.Streams.IsNullOrEmpty()) @@ -705,7 +734,7 @@ private async Task Worker() // Read & Save the Instance ID of the MTConnect Agent _lastInstanceId = current.Header.InstanceId; - // If the LastSequence is not within the current sequence range then reset Sequeunce to 0 + // If the LastSequence is not within the current sequence range then reset Sequence to 0 if (current.Header.FirstSequence > _lastSequence || current.Header.NextSequence < _lastSequence) { @@ -717,7 +746,7 @@ private async Task Worker() if (CurrentOnly) url = CreateCurrentUrl(Authority, Device, Interval, _streamPath); // Create and Start the Stream - using (_stream = new MTConnectHttpClientStream(url, DocumentFormat)) + using (_stream = new MTConnectHttpClientStream(url, DocumentFormat, _logger)) { _stream.Timeout = Heartbeat * 3; _stream.ContentEncodings = ContentEncodings; @@ -945,7 +974,10 @@ private void ProcessSampleDocument(IStreamsResponseDocument document, Cancellati } } - SampleReceived?.Invoke(this, response); + LogReporter.MeasureAndReport( + () => SampleReceived?.Invoke(this, response), + $"handling samples", + _logger); foreach (var observation in receivedObservations) { diff --git a/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClientStream.cs b/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClientStream.cs index d41a3002..3eb51d66 100644 --- a/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClientStream.cs +++ b/libraries/MTConnect.NET-HTTP/Clients/MTConnectHttpClientStream.cs @@ -12,6 +12,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using MTConnect.Logging; namespace MTConnect.Clients { @@ -26,12 +28,16 @@ public class MTConnectHttpClientStream : IDisposable private const byte Dash = 45; private static readonly byte[] _trimBytes = new byte[] { LineFeed, CarriageReturn }; private readonly HttpClient _httpClient; + private ILogger _logger; private CancellationTokenSource _stop; private string _documentFormat = DocumentFormat.XML; - public MTConnectHttpClientStream(string url, string documentFormat = DocumentFormat.XML) + public MTConnectHttpClientStream( + string url, + string documentFormat = DocumentFormat.XML, + ILogger logger = null) { Id = Guid.NewGuid().ToString(); Url = url; @@ -39,6 +45,7 @@ public MTConnectHttpClientStream(string url, string documentFormat = DocumentFor _documentFormat = documentFormat; ContentEncodings = HttpContentEncodings.DefaultAccept; ContentType = MimeTypes.Get(documentFormat); + _logger = logger; _httpClient = new HttpClient(); _httpClient.Timeout = TimeSpan.FromMilliseconds(DefaultTimeout); @@ -155,6 +162,7 @@ public async Task Run(CancellationToken cancellationToken) } } + LogReporter.Report("Creating stream async.", _logger); var httpRequest = new HttpRequestMessage(); httpRequest.RequestUri = new Uri(Url); @@ -168,6 +176,8 @@ public async Task Run(CancellationToken cancellationToken) using (var stream = await response.Content.ReadAsStreamAsync()) #endif { + LogReporter.Report("Created stream async.", _logger); + var header = new List(); var headerActive = false; var cr = false; @@ -180,6 +190,7 @@ public async Task Run(CancellationToken cancellationToken) string contentEncoding = null; string lineStr = null; + LogReporter.Report("Starting bytes...", _logger); var readBuffer = new byte[1]; var read = await stream.ReadAsync(readBuffer, 0, readBuffer.Length, stop.Token); @@ -237,7 +248,10 @@ public async Task Run(CancellationToken cancellationToken) if (bodyBytes != null) { // Call overridable method to process the bytes contained in the body of the response - ProcessResponseBody(bodyBytes, contentEncoding); + LogReporter.MeasureAndReport( + () => ProcessResponseBody(bodyBytes, contentEncoding), + "processing stream body", + _logger); } contentLength = 0; @@ -264,6 +278,8 @@ public async Task Run(CancellationToken cancellationToken) responseTimer.Start(); } } + + LogReporter.Report("Finished bytes successfully.", _logger); } } catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetResponseHandler.cs index 6a2792e8..7da5a64f 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetResponseHandler.cs @@ -10,12 +10,20 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers { class MTConnectAssetResponseHandler : MTConnectHttpResponseHandler { - public MTConnectAssetResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectAssetResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) + : base( + serverConfiguration, + mtconnectAgent, + logger) { } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetsResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetsResponseHandler.cs index e86cb205..a2ba9acd 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetsResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectAssetsResponseHandler.cs @@ -10,12 +10,20 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers { class MTConnectAssetsResponseHandler : MTConnectHttpResponseHandler { - public MTConnectAssetsResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectAssetsResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) + : base( + serverConfiguration, + mtconnectAgent, + logger) { } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectCurrentResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectCurrentResponseHandler.cs index 88fd40b3..a7ae2186 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectCurrentResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectCurrentResponseHandler.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers.Http { @@ -18,7 +19,14 @@ class MTConnectCurrentResponseHandler : MTConnectHttpResponseHandler private const int _defaultHeartbeat = 10000; // 10 Seconds - public MTConnectCurrentResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectCurrentResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) + : base( + serverConfiguration, + mtconnectAgent, + logger) { } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) @@ -104,7 +112,8 @@ protected async override Task OnRequestReceived(IHttpCont heartbeat, documentFormat, acceptEncodings, - formatOptions + formatOptions, + _logger ); try diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpResponseHandler.cs index 4653f272..969a2334 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpResponseHandler.cs @@ -14,6 +14,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers.Http { @@ -21,6 +22,7 @@ internal abstract class MTConnectHttpResponseHandler : IHttpModule { protected readonly IMTConnectAgentBroker _mtconnectAgent; protected readonly IHttpServerConfiguration _serverConfiguration; + protected readonly ILogger _logger; /// @@ -46,10 +48,14 @@ internal abstract class MTConnectHttpResponseHandler : IHttpModule public Func>> CreateFormatOptionsFunction { get; set; } - public MTConnectHttpResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) + public MTConnectHttpResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger) { _mtconnectAgent = mtconnectAgent; _serverConfiguration = serverConfiguration; + _logger = logger; } diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServer.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServer.cs index 23c4b37b..a1e142a4 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServer.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServer.cs @@ -15,6 +15,9 @@ using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using MTConnect.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers.Http { @@ -26,7 +29,7 @@ public class MTConnectHttpServer : IDisposable protected readonly IMTConnectAgentBroker _mtconnectAgent; protected readonly IHttpServerConfiguration _configuration; private CancellationTokenSource _stop; - + protected ILogger _logger; /// /// Event for when an error occurs with a MTConnectHttpResponse is written to the HTTP Client @@ -72,10 +75,14 @@ public class MTConnectHttpServer : IDisposable public event EventHandler ClientException; - public MTConnectHttpServer(IHttpServerConfiguration configuration, IMTConnectAgentBroker mtconnectAgent) + public MTConnectHttpServer( + IHttpServerConfiguration configuration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) { _mtconnectAgent = mtconnectAgent; _configuration = configuration; + _logger = logger; } @@ -114,12 +121,18 @@ public void Start() if (_configuration != null) { _ = Task.Run(() => StartServer(_configuration, _stop.Token)); + + LogReporter.Report($"Started server at {_configuration.Port}", _logger); } } public void Stop() { - if (_stop != null) _stop.Cancel(); + if (_stop != null) + { + _stop.Cancel(); + LogReporter.Report($"Stopping server at {_configuration.Port}...", _logger); + } } public void Dispose() { Stop(); } @@ -216,7 +229,7 @@ private ServerConfig CreateServerConfig(IHttpServerConfiguration serverConfigura serverConfig.MaxProcessingTimeSeconds = 60; // Setup the Probe Request Handler - var probeHandler = new MTConnectProbeResponseHandler(serverConfiguration, _mtconnectAgent); + var probeHandler = new MTConnectProbeResponseHandler(serverConfiguration, _mtconnectAgent, _logger); probeHandler.ResponseSent += ResponseSent; probeHandler.ClientConnected += ClientConnected; probeHandler.ClientDisconnected += ClientDisconnected; @@ -224,7 +237,7 @@ private ServerConfig CreateServerConfig(IHttpServerConfiguration serverConfigura probeHandler.CreateFormatOptionsFunction = OnCreateFormatOptions; // Setup the Current Request Handler - var currentHandler = new MTConnectCurrentResponseHandler(serverConfiguration, _mtconnectAgent); + var currentHandler = new MTConnectCurrentResponseHandler(serverConfiguration, _mtconnectAgent, _logger); currentHandler.ResponseSent += ResponseSent; currentHandler.ClientConnected += ClientConnected; currentHandler.ClientDisconnected += ClientDisconnected; @@ -232,7 +245,7 @@ private ServerConfig CreateServerConfig(IHttpServerConfiguration serverConfigura currentHandler.CreateFormatOptionsFunction = OnCreateFormatOptions; // Setup the Sample Request Handler - var sampleHandler = new MTConnectSampleResponseHandler(serverConfiguration, _mtconnectAgent); + var sampleHandler = new MTConnectSampleResponseHandler(serverConfiguration, _mtconnectAgent, _logger); sampleHandler.ResponseSent += ResponseSent; sampleHandler.ClientConnected += ClientConnected; sampleHandler.ClientDisconnected += ClientDisconnected; @@ -307,6 +320,12 @@ private ServerConfig CreateServerConfig(IHttpServerConfiguration serverConfigura serverConfig.AddRoute("/asset/*", assetHandler); serverConfig.AddRoute(staticHandler); + if (_logger != null) + { + serverConfig.DebugLogHandler += (string message, string logtaskid, object data) + => _logger.LogDebug($"[{logtaskid}] message: {message}, data: {data}"); + } + return serverConfig; } diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServerStream.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServerStream.cs index 16b8d504..4eed6dbf 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServerStream.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectHttpServerStream.cs @@ -12,6 +12,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using MTConnect.Logging; namespace MTConnect.Servers.Http { @@ -33,6 +35,7 @@ public class MTConnectHttpServerStream private readonly string _documentFormat; private readonly IEnumerable _acceptEncodings; private readonly IEnumerable> _formatOptions; + private readonly ILogger _logger; private CancellationTokenSource _stop; private bool _isConnected; @@ -72,7 +75,8 @@ public MTConnectHttpServerStream( int heartbeat = 10000, string documentFormat = DocumentFormat.XML, IEnumerable acceptEncodings = null, - IEnumerable> formatOptions = null + IEnumerable> formatOptions = null, + ILogger logger = null ) { _configuration = configuration; @@ -86,6 +90,7 @@ public MTConnectHttpServerStream( _documentFormat = documentFormat; _acceptEncodings = acceptEncodings; _formatOptions = formatOptions; + _logger = logger; } @@ -99,6 +104,8 @@ public void StartSample(CancellationToken cancellationToken) _= Task.Run(Worker, _stop.Token); _isConnected = true; + + LogReporter.Report("Started server sample stream", _logger); } public void StartCurrent(CancellationToken cancellationToken) @@ -110,12 +117,19 @@ public void StartCurrent(CancellationToken cancellationToken) _ = Task.Run(Worker, _stop.Token); + LogReporter.Report("Started server current stream", _logger); + _isConnected = true; } public void Stop() { - if (_stop != null) _stop.Cancel(); + if (_stop != null) + { + _stop.Cancel(); + var type = _currentOnly ? "current" : "sample"; + LogReporter.Report($"Stopped server {type} stream", _logger); + } _isConnected = false; } @@ -125,8 +139,12 @@ public void RunSample(CancellationToken cancellationToken) cancellationToken.Register(() => { Stop(); }); _currentOnly = false; + LogReporter.Report("Running server sample stream...", _logger); + Worker(); + LogReporter.Report("Finished server sample stream", _logger); + _isConnected = true; } @@ -135,8 +153,12 @@ public void RunCurrent() _stop = new CancellationTokenSource(); _currentOnly = true; + LogReporter.Report("Running server current stream", _logger); + Worker(); + LogReporter.Report("Finished server current stream", _logger); + _isConnected = true; } diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectPostResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectPostResponseHandler.cs index 9ed4c9e0..44a93adc 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectPostResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectPostResponseHandler.cs @@ -10,6 +10,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers { @@ -18,7 +19,14 @@ class MTConnectPostResponseHandler : MTConnectHttpResponseHandler public Func ProcessFunction { get; set; } - public MTConnectPostResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectPostResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) + : base( + serverConfiguration, + mtconnectAgent, + logger) { } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectProbeResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectProbeResponseHandler.cs index e62bcd41..b123d6fb 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectProbeResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectProbeResponseHandler.cs @@ -9,12 +9,20 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers.Http { class MTConnectProbeResponseHandler : MTConnectHttpResponseHandler { - public MTConnectProbeResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectProbeResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) + : base( + serverConfiguration, + mtconnectAgent, + logger) { } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectPutResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectPutResponseHandler.cs index e67a88c7..9a97087b 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectPutResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectPutResponseHandler.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers { @@ -19,7 +20,16 @@ class MTConnectPutResponseHandler : MTConnectHttpResponseHandler public Func ProcessFunction { get; set; } - public MTConnectPutResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectPutResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) + : base( + serverConfiguration, + mtconnectAgent, + logger) + { + } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectSampleResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectSampleResponseHandler.cs index 130c21b3..68dd177c 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectSampleResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectSampleResponseHandler.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers { @@ -19,7 +20,14 @@ class MTConnectSampleResponseHandler : MTConnectHttpResponseHandler private const int _defaultHeartbeat = 10000; // 10 Seconds - public MTConnectSampleResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectSampleResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) + : base( + serverConfiguration, + mtconnectAgent, + logger) { } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) @@ -112,7 +120,8 @@ protected async override Task OnRequestReceived(IHttpCont heartbeat, documentFormat, acceptEncodings, - formatOptions + formatOptions, + _logger ); try diff --git a/libraries/MTConnect.NET-HTTP/Servers/MTConnectStaticResponseHandler.cs b/libraries/MTConnect.NET-HTTP/Servers/MTConnectStaticResponseHandler.cs index c7e59b03..6e358c11 100644 --- a/libraries/MTConnect.NET-HTTP/Servers/MTConnectStaticResponseHandler.cs +++ b/libraries/MTConnect.NET-HTTP/Servers/MTConnectStaticResponseHandler.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace MTConnect.Servers { @@ -19,7 +20,13 @@ class MTConnectStaticResponseHandler : MTConnectHttpResponseHandler public Func ProcessFunction { get; set; } - public MTConnectStaticResponseHandler(IHttpServerConfiguration serverConfiguration, IMTConnectAgentBroker mtconnectAgent) : base(serverConfiguration, mtconnectAgent) { } + public MTConnectStaticResponseHandler( + IHttpServerConfiguration serverConfiguration, + IMTConnectAgentBroker mtconnectAgent, + ILogger logger = null) : base( + serverConfiguration, + mtconnectAgent, + logger) { } protected async override Task OnRequestReceived(IHttpContext context, CancellationToken cancellationToken) diff --git a/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapter.cs b/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapter.cs index da4e54a4..9ab0a63b 100644 --- a/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapter.cs +++ b/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapter.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 TrakHound Inc., All Rights Reserved. // TrakHound Inc. licenses this file to you under the MIT license. +using Microsoft.Extensions.Logging; using MTConnect.Assets; using MTConnect.Configurations; using MTConnect.Devices; @@ -13,6 +14,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using MTConnect.Logging; namespace MTConnect.Adapters { @@ -27,7 +29,7 @@ public class ShdrAdapter private readonly AgentClientConnectionListener _connectionListener; private readonly Dictionary _clients = new Dictionary(); private readonly object _lock = new object(); - + private ILogger _logger; private CancellationTokenSource _stop; protected CancellationTokenSource StopToken => _stop; @@ -129,15 +131,19 @@ public class ShdrAdapter public event EventHandler> ConnectionError; - public ShdrAdapter(int port = 7878, int heartbeat = 10000) + public ShdrAdapter( + int port = 7878, + int heartbeat = 10000, + ILogger logger = null) { FilterDuplicates = true; OutputTimestamps = true; Port = port; Heartbeat = heartbeat; Timeout = 5000; + _logger = logger; - var adapter = new MTConnectAdapter(null, false); + var adapter = new MTConnectAdapter(null, false, logger); adapter.OutputTimestamps = OutputTimestamps; adapter.WriteObservationsFunction = WriteObservations; adapter.WriteAssetsFunction = WriteAssets; @@ -152,7 +158,11 @@ public ShdrAdapter(int port = 7878, int heartbeat = 10000) _connectionListener.ConnectionErrorReceived += ClientConnectionError; } - public ShdrAdapter(string deviceKey, int port = 7878, int heartbeat = 10000) + public ShdrAdapter( + string deviceKey, + int port = 7878, + int heartbeat = 10000, + ILogger logger = null) { FilterDuplicates = true; OutputTimestamps = true; @@ -160,8 +170,9 @@ public ShdrAdapter(string deviceKey, int port = 7878, int heartbeat = 10000) Port = port; Heartbeat = heartbeat; Timeout = 5000; + _logger = logger; - var adapter = new MTConnectAdapter(null, false); + var adapter = new MTConnectAdapter(null, false, logger); adapter.OutputTimestamps = OutputTimestamps; adapter.WriteObservationsFunction = WriteObservations; adapter.WriteAssetsFunction = WriteAssets; @@ -176,10 +187,13 @@ public ShdrAdapter(string deviceKey, int port = 7878, int heartbeat = 10000) _connectionListener.ConnectionErrorReceived += ClientConnectionError; } - public ShdrAdapter(ShdrAdapterClientConfiguration configuration) + public ShdrAdapter( + ShdrAdapterClientConfiguration configuration, + ILogger logger = null) { FilterDuplicates = true; OutputTimestamps = true; + _logger = logger; if (configuration != null) { @@ -188,7 +202,7 @@ public ShdrAdapter(ShdrAdapterClientConfiguration configuration) Heartbeat = configuration.Heartbeat; Timeout = 5000; - var adapter = new MTConnectAdapter(null, false); + var adapter = new MTConnectAdapter(null, false, logger); adapter.IgnoreTimestamps = configuration.IgnoreTimestamps; adapter.OutputTimestamps = OutputTimestamps; adapter.WriteObservationsFunction = WriteObservations; @@ -205,15 +219,21 @@ public ShdrAdapter(ShdrAdapterClientConfiguration configuration) } } - protected ShdrAdapter(int port = 7878, int heartbeat = 10000, int? interval = null, bool bufferEnabled = false) + protected ShdrAdapter( + int port = 7878, + int heartbeat = 10000, + int? interval = null, + bool bufferEnabled = false, + ILogger logger = null) { FilterDuplicates = true; OutputTimestamps = true; Port = port; Heartbeat = heartbeat; Timeout = 5000; + _logger = logger; - var adapter = new MTConnectAdapter(interval, bufferEnabled); + var adapter = new MTConnectAdapter(interval, bufferEnabled, logger); adapter.OutputTimestamps = OutputTimestamps; adapter.WriteObservationsFunction = WriteObservations; adapter.WriteAssetsFunction = WriteAssets; @@ -228,7 +248,13 @@ protected ShdrAdapter(int port = 7878, int heartbeat = 10000, int? interval = nu _connectionListener.ConnectionErrorReceived += ClientConnectionError; } - protected ShdrAdapter(string deviceKey, int port = 7878, int heartbeat = 10000, int? interval = null, bool bufferEnabled = false) + protected ShdrAdapter( + string deviceKey, + int port = 7878, + int heartbeat = 10000, + int? interval = null, + bool bufferEnabled = false, + ILogger logger = null) { FilterDuplicates = true; OutputTimestamps = true; @@ -236,8 +262,9 @@ protected ShdrAdapter(string deviceKey, int port = 7878, int heartbeat = 10000, Port = port; Heartbeat = heartbeat; Timeout = 5000; + _logger = logger; - var adapter = new MTConnectAdapter(interval, bufferEnabled); + var adapter = new MTConnectAdapter(interval, bufferEnabled, logger); adapter.OutputTimestamps = OutputTimestamps; adapter.WriteObservationsFunction = WriteObservations; adapter.WriteAssetsFunction = WriteAssets; @@ -252,10 +279,15 @@ protected ShdrAdapter(string deviceKey, int port = 7878, int heartbeat = 10000, _connectionListener.ConnectionErrorReceived += ClientConnectionError; } - protected ShdrAdapter(ShdrAdapterClientConfiguration configuration, int? interval = null, bool bufferEnabled = false) + protected ShdrAdapter( + ShdrAdapterClientConfiguration configuration, + int? interval = null, + bool bufferEnabled = false, + ILogger logger = null) { FilterDuplicates = true; OutputTimestamps = true; + _logger = logger; if (configuration != null) { @@ -264,7 +296,7 @@ protected ShdrAdapter(ShdrAdapterClientConfiguration configuration, int? interva Heartbeat = configuration.Heartbeat; Timeout = 5000; - var adapter = new MTConnectAdapter(interval, bufferEnabled); + var adapter = new MTConnectAdapter(interval, bufferEnabled, logger); adapter.IgnoreTimestamps = configuration.IgnoreTimestamps; adapter.WriteObservationsFunction = WriteObservations; adapter.WriteAssetsFunction = WriteAssets; @@ -542,6 +574,8 @@ protected bool WriteLine(string line) { try { + LogReporter.Report(line, _logger); + // Write Line to each client in stored client list var clients = GetAgentClients(); if (!clients.IsNullOrEmpty()) diff --git a/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapterClient.cs b/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapterClient.cs index 3fc88bdb..830951b8 100644 --- a/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapterClient.cs +++ b/libraries/MTConnect.NET-SHDR/Adapters/ShdrAdapterClient.cs @@ -1,6 +1,7 @@ // Copyright (c) 2024 TrakHound Inc., All Rights Reserved. // TrakHound Inc. licenses this file to you under the MIT license. +using Microsoft.Extensions.Logging; using MTConnect.Agents; using MTConnect.Assets; using MTConnect.Configurations; @@ -20,8 +21,7 @@ public class ShdrAdapterClient : ShdrClient private readonly IShdrAdapterClientConfiguration _configuration; private readonly IMTConnectAgent _agent; private IDevice _device; - - + public IDevice Device => _device; @@ -29,7 +29,8 @@ public ShdrAdapterClient( IShdrAdapterClientConfiguration configuration, IMTConnectAgent agent, IDevice device, - string idSuffix = null + string idSuffix = null, + ILogger logger = null ) { _configuration = configuration; @@ -37,6 +38,7 @@ public ShdrAdapterClient( if (!string.IsNullOrEmpty(idSuffix)) Id = Id != null ? $"{Id}_{idSuffix}" : idSuffix; _agent = agent; _device = device; + _logger = logger; if (_configuration != null) { @@ -51,7 +53,8 @@ public ShdrAdapterClient( IMTConnectAgent agent, IDevice device, string hostname, - int port + int port, + ILogger logger = null ) { _configuration = configuration; @@ -59,6 +62,7 @@ int port _device = device; Hostname = hostname; Port = port; + _logger = logger; if (_configuration != null) { diff --git a/libraries/MTConnect.NET-SHDR/Adapters/ShdrIntervalAdapter.cs b/libraries/MTConnect.NET-SHDR/Adapters/ShdrIntervalAdapter.cs index dd9c6f6d..a92a678d 100644 --- a/libraries/MTConnect.NET-SHDR/Adapters/ShdrIntervalAdapter.cs +++ b/libraries/MTConnect.NET-SHDR/Adapters/ShdrIntervalAdapter.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 TrakHound Inc., All Rights Reserved. // TrakHound Inc. licenses this file to you under the MIT license. +using Microsoft.Extensions.Logging; using MTConnect.Configurations; namespace MTConnect.Adapters @@ -15,10 +16,37 @@ public class ShdrIntervalAdapter : ShdrAdapter private const int _defaultInterval = 100; - public ShdrIntervalAdapter(int port = 7878, int heartbeat = 10000, int interval = _defaultInterval) : base(port, heartbeat, interval) { } + public ShdrIntervalAdapter( + int port = 7878, + int heartbeat = 10000, + int interval = _defaultInterval, + ILogger logger = null) + : base( + port, + heartbeat, + interval, + logger: logger) { } - public ShdrIntervalAdapter(string deviceKey, int port = 7878, int heartbeat = 10000, int interval = _defaultInterval) : base(deviceKey, port, heartbeat, interval) { } + public ShdrIntervalAdapter( + string deviceKey, + int port = 7878, + int heartbeat = 10000, + int interval = _defaultInterval, + ILogger logger = null) + : base( + deviceKey, + port, + heartbeat, + interval, + logger: logger) { } - public ShdrIntervalAdapter(ShdrAdapterClientConfiguration configuration, int interval = _defaultInterval) : base(configuration, interval) { } + public ShdrIntervalAdapter( + ShdrAdapterClientConfiguration configuration, + int interval = _defaultInterval, + ILogger logger = null) + : base( + configuration, + interval, + logger: logger) { } } } \ No newline at end of file diff --git a/libraries/MTConnect.NET-SHDR/Shdr/ShdrClient.cs b/libraries/MTConnect.NET-SHDR/Shdr/ShdrClient.cs index 7f6ef713..11801372 100644 --- a/libraries/MTConnect.NET-SHDR/Shdr/ShdrClient.cs +++ b/libraries/MTConnect.NET-SHDR/Shdr/ShdrClient.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 TrakHound Inc., All Rights Reserved. // TrakHound Inc. licenses this file to you under the MIT license. +using Microsoft.Extensions.Logging; using MTConnect.Assets; using MTConnect.Assets.Xml; using MTConnect.Configurations; @@ -13,6 +14,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using MTConnect.Logging; namespace MTConnect.Shdr { @@ -31,6 +33,7 @@ public class ShdrClient private long _lastHeartbeat = 0; private CancellationTokenSource _stop; private int _heartbeat = DefaultPongHeartbeat; + protected ILogger _logger; /// @@ -113,13 +116,19 @@ public class ShdrClient public event EventHandler CommandReceived; - public ShdrClient() + public ShdrClient(ILogger logger = null) { Id = StringFunctions.RandomString(10); IgnoreHeartbeatOnChange = true; + _logger = logger; } - public ShdrClient(string hostname, int port, int connectionTimeout = DefaultConnectionTimeout, int reconnectInterval = DefaultReconnectInterval) + public ShdrClient( + string hostname, + int port, + int connectionTimeout = DefaultConnectionTimeout, + int reconnectInterval = DefaultReconnectInterval, + ILogger logger = null) { Id = StringFunctions.RandomString(10); Hostname = hostname; @@ -127,9 +136,16 @@ public ShdrClient(string hostname, int port, int connectionTimeout = DefaultConn ConnectionTimeout = connectionTimeout; ReconnectInterval = reconnectInterval; IgnoreHeartbeatOnChange = true; + _logger = logger; } - public ShdrClient(string hostname, int port, string deviceKey, int connectionTimeout = DefaultConnectionTimeout, int reconnectInterval = DefaultReconnectInterval) + public ShdrClient( + string hostname, + int port, + string deviceKey, + int connectionTimeout = DefaultConnectionTimeout, + int reconnectInterval = DefaultReconnectInterval, + ILogger logger = null) { Id = StringFunctions.RandomString(10); Hostname = hostname; @@ -138,12 +154,16 @@ public ShdrClient(string hostname, int port, string deviceKey, int connectionTim ConnectionTimeout = connectionTimeout; ReconnectInterval = reconnectInterval; IgnoreHeartbeatOnChange = true; + _logger = logger; } - public ShdrClient(ShdrClientConfiguration configuration) + public ShdrClient( + ShdrClientConfiguration configuration, + ILogger logger = null) { Id = StringFunctions.RandomString(10); IgnoreHeartbeatOnChange = true; + _logger = logger; if (configuration != null) { @@ -540,6 +560,8 @@ private bool ProcessResponse(ref char[] chars, int length) } else { + LogReporter.Report(line, _logger); + ProcessProtocol(line); // Raise ProtocolReceived Event passing the Line that was read as a parameter