diff --git a/src/Diagnostics.cs b/src/Diagnostics.cs new file mode 100644 index 0000000..b0e5a82 --- /dev/null +++ b/src/Diagnostics.cs @@ -0,0 +1,112 @@ + +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace OpcPublisher +{ + using static OpcPublisher.Workarounds.TraceWorkaround; + using static IotHubMessaging; + using static PublisherNodeConfiguration; + + /// + /// Class to enable output to the console. + /// + public static class Diagnostics + { + + public static uint DiagnosticsInterval + { + get => _diagnosticsInterval; + set => _diagnosticsInterval = value; + } + private static uint _diagnosticsInterval = 0; + + public static int IotHubMessagingMessagesSentCount + { + get => _messagesSentCount; + } + private static int _messagesSentCount = 0; + + private static CancellationTokenSource _shutdownTokenSource; + private static Task _showDiagnosticsInfoTask; + + public static void Init() + { + // init data + _showDiagnosticsInfoTask = null; + _shutdownTokenSource = new CancellationTokenSource(); + + // kick off the task to show diagnostic info + if (_diagnosticsInterval > 0) + { + _showDiagnosticsInfoTask = Task.Run(async () => await ShowDiagnosticsInfoAsync(_shutdownTokenSource.Token)); + } + + + } + public async static Task Shutdown() + { + // wait for diagnostic task completion if it is enabled + if (_showDiagnosticsInfoTask != null) + { + _shutdownTokenSource.Cancel(); + await _showDiagnosticsInfoTask; + } + + } + + /// + /// Kicks of the task to show diagnostic information each 30 seconds. + /// + public static async Task ShowDiagnosticsInfoAsync(CancellationToken cancellationtoken) + { + while (true) + { + try + { + + if (cancellationtoken.IsCancellationRequested) + { + return; + } + await Task.Delay((int)_diagnosticsInterval * 1000); + + Trace("======================================================================"); + Trace($"OpcPublisher status @ {System.DateTime.UtcNow}"); + Trace("---------------------------------"); + Trace($"OPC sessions: {NumberOfOpcSessions}"); + Trace($"connected OPC sessions: {NumberOfConnectedOpcSessions}"); + Trace($"connected OPC subscriptions: {NumberOfConnectedOpcSubscriptions}"); + Trace($"OPC monitored items: {NumberOfMonitoredItems}"); + Trace("---------------------------------"); + Trace($"monitored items queue bounded capacity: {MonitoredItemsQueueCapacity}"); + Trace($"monitored items queue current items: {MonitoredItemsQueueCount}"); + Trace($"monitored item notifications enqueued: {EnqueueCount}"); + Trace($"monitored item notifications enqueue failure: {EnqueueFailureCount}"); + Trace($"monitored item notifications dequeued: {DequeueCount}"); + Trace("---------------------------------"); + Trace($"messages sent to IoTHub: {SentMessages}"); + Trace($"bytes sent to IoTHub: {SentBytes}"); + Trace($"avg msg size: {SentBytes / (SentMessages == 0 ? 1 : SentMessages)}"); + Trace($"time in ms for sent msgs: {SentTime}"); + Trace($"min time in ms for msg: {MinSentTime}"); + Trace($"max time in ms for msg: {MaxSentTime}"); + Trace($"avg time in ms for msg: {SentTime / (SentMessages == 0 ? 1 : SentMessages)}"); + Trace($"msg send failures: {FailedMessages}"); + Trace($"time in ms for failed msgs: {FailedTime}"); + Trace($"avg time in ms for failed msg: {FailedTime / (FailedMessages == 0 ? 1 : FailedMessages)}"); + Trace($"messages too large to sent to IoTHub: {TooLargeCount}"); + Trace($"times we missed send interval: {MissedSendIntervalCount}"); + Trace("---------------------------------"); + Trace($"current working set in MB: {Process.GetCurrentProcess().WorkingSet64 / (1024 * 1024)}"); + Trace("======================================================================"); + } + catch + { + } + } + } + + } +}