From f70c68356b0a2dc8446c3a2b3d6e44aefc7a61ff Mon Sep 17 00:00:00 2001 From: Tomasz Masternak Date: Tue, 19 Sep 2017 14:28:07 +0200 Subject: [PATCH 1/6] Performance counter creation script deletes category only when necessary (#37) * exptected script content * cs script generator * ps1 script writer --- src/ScriptBuilder/CSharpCounterWriter.cs | 31 +++++++++++++------ src/ScriptBuilder/PowerShellCounterWriter.cs | 29 ++++++++++++----- ...pCodeGenerationTests.Generates.approved.cs | 31 +++++++++++++------ ...CodeGenerationTests.Generates.approved.ps1 | 26 +++++++++++++--- .../PowershellCodeGenerationTests.cs | 3 ++ 5 files changed, 90 insertions(+), 30 deletions(-) diff --git a/src/ScriptBuilder/CSharpCounterWriter.cs b/src/ScriptBuilder/CSharpCounterWriter.cs index 39b0466..bc84923 100644 --- a/src/ScriptBuilder/CSharpCounterWriter.cs +++ b/src/ScriptBuilder/CSharpCounterWriter.cs @@ -41,26 +41,39 @@ public static void WriteCode(string scriptPath, IEnumerable tim using System.Runtime.CompilerServices; [CompilerGenerated] -public static class CounterCreator +public static class CounterCreator {{ - public static void Create() + public static void Create() {{ var counterCreationCollection = new CounterCreationDataCollection(Counters); try {{ var categoryName = ""NServiceBus""; + if (PerformanceCounterCategory.Exists(categoryName)) {{ - PerformanceCounterCategory.Delete(categoryName); + foreach (CounterCreationData counter in counterCreationCollection) + {{ + if (!PerformanceCounterCategory.CounterExists(counter.CounterName, categoryName)) + {{ + PerformanceCounterCategory.Delete(categoryName); + break; + }} + }} + }} + + if (PerformanceCounterCategory.Exists(categoryName) == false) + {{ + PerformanceCounterCategory.Create( + categoryName: categoryName, + categoryHelp: ""NServiceBus statistics"", + categoryType: PerformanceCounterCategoryType.MultiInstance, + counterData: counterCreationCollection); }} - PerformanceCounterCategory.Create( - categoryName: categoryName, - categoryHelp: ""NServiceBus statistics"", - categoryType: PerformanceCounterCategoryType.MultiInstance, - counterData: counterCreationCollection); PerformanceCounter.CloseSharedResources(); - }} catch(Exception ex) when(ex is SecurityException || ex is UnauthorizedAccessException) + }} + catch (Exception ex) when (ex is SecurityException || ex is UnauthorizedAccessException) {{ throw new Exception(""Execution requires elevated permissions"", ex); }} diff --git a/src/ScriptBuilder/PowerShellCounterWriter.cs b/src/ScriptBuilder/PowerShellCounterWriter.cs index c67a8ef..7821f1a 100644 --- a/src/ScriptBuilder/PowerShellCounterWriter.cs +++ b/src/ScriptBuilder/PowerShellCounterWriter.cs @@ -35,22 +35,37 @@ public static void WriteScript(string scriptPath, IEnumerable t } } - const string Template = @" -#requires -RunAsAdministrator + const string Template = @"#requires -RunAsAdministrator Function InstallNSBPerfCounters {{ - + $category = @{{Name=""NServiceBus""; Description=""NServiceBus statistics""}} $counters = New-Object System.Diagnostics.CounterCreationDataCollection $counters.AddRange(@( {0} )) + if ([System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) {{ - [System.Diagnostics.PerformanceCounterCategory]::Delete($category.Name) + foreach($counter in $counters){{ + $exists = [System.Diagnostics.PerformanceCounterCategory]::CounterExists($counter.CounterName, $category.Name) + if (!$exists){{ + Write-Host ""One or more counters are missing.The performance counter category will be recreated"" + [System.Diagnostics.PerformanceCounterCategory]::Delete($category.Name) + + break + }} + }} }} - [void] [System.Diagnostics.PerformanceCounterCategory]::Create($category.Name, $category.Description, [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance, $counters) + + if (![System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) {{ + Write-Host ""Creating the performance counter category"" + [void] [System.Diagnostics.PerformanceCounterCategory]::Create($category.Name, $category.Description, [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance, $counters) + }} + else {{ + Write-Host ""No performance counters have to be created"" + }} + [System.Diagnostics.PerformanceCounter]::CloseSharedResources() }} -InstallNSBPerfCounters -"; +InstallNSBPerfCounters"; } } \ No newline at end of file diff --git a/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs b/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs index e7032c7..63382af 100644 --- a/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs +++ b/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs @@ -4,26 +4,39 @@ using System.Runtime.CompilerServices; [CompilerGenerated] -public static class CounterCreator +public static class CounterCreator { - public static void Create() + public static void Create() { var counterCreationCollection = new CounterCreationDataCollection(Counters); try { var categoryName = "NServiceBus"; + if (PerformanceCounterCategory.Exists(categoryName)) { - PerformanceCounterCategory.Delete(categoryName); + foreach (CounterCreationData counter in counterCreationCollection) + { + if (!PerformanceCounterCategory.CounterExists(counter.CounterName, categoryName)) + { + PerformanceCounterCategory.Delete(categoryName); + break; + } + } + } + + if (PerformanceCounterCategory.Exists(categoryName) == false) + { + PerformanceCounterCategory.Create( + categoryName: categoryName, + categoryHelp: "NServiceBus statistics", + categoryType: PerformanceCounterCategoryType.MultiInstance, + counterData: counterCreationCollection); } - PerformanceCounterCategory.Create( - categoryName: categoryName, - categoryHelp: "NServiceBus statistics", - categoryType: PerformanceCounterCategoryType.MultiInstance, - counterData: counterCreationCollection); PerformanceCounter.CloseSharedResources(); - } catch(Exception ex) when(ex is SecurityException || ex is UnauthorizedAccessException) + } + catch (Exception ex) when (ex is SecurityException || ex is UnauthorizedAccessException) { throw new Exception("Execution requires elevated permissions", ex); } diff --git a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 index 5f8f754..8040fa7 100644 --- a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 +++ b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 @@ -1,7 +1,6 @@ - #requires -RunAsAdministrator Function InstallNSBPerfCounters { - + $category = @{Name="NServiceBus"; Description="NServiceBus statistics"} $counters = New-Object System.Diagnostics.CounterCreationDataCollection $counters.AddRange(@( @@ -13,10 +12,27 @@ Function InstallNSBPerfCounters { New-Object System.Diagnostics.CounterCreationData "# of msgs successfully processed / sec", "The current number of messages processed successfully by the transport per second.", RateOfCountsPerSecond32 )) + if ([System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) { - [System.Diagnostics.PerformanceCounterCategory]::Delete($category.Name) + foreach($counter in $counters){ + $exists = [System.Diagnostics.PerformanceCounterCategory]::CounterExists($counter.CounterName, $category.Name) + if (!$exists){ + Write-Host "One or more counters are missing.The performance counter category will be recreated" + [System.Diagnostics.PerformanceCounterCategory]::Delete($category.Name) + + break + } + } } - [void] [System.Diagnostics.PerformanceCounterCategory]::Create($category.Name, $category.Description, [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance, $counters) + + if (![System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) { + Write-Host "Creating the performance counter category" + [void] [System.Diagnostics.PerformanceCounterCategory]::Create($category.Name, $category.Description, [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance, $counters) + } + else { + Write-Host "No performance counters have to be created" + } + [System.Diagnostics.PerformanceCounter]::CloseSharedResources() } -InstallNSBPerfCounters +InstallNSBPerfCounters \ No newline at end of file diff --git a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs index 811fe5c..c4832f1 100644 --- a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs +++ b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Runtime.CompilerServices; using ApprovalTests; + using ApprovalTests.Reporters; using NServiceBus.Metrics.PerformanceCounters; using NUnit.Framework; @@ -36,6 +37,8 @@ public void Generates() { task.Execute(); + GenericDiffReporter.RegisterTextFileTypes(".ps1"); + var powershell = Directory.EnumerateFiles(tempPath, "*.ps1", SearchOption.AllDirectories).Single(); Approvals.VerifyFile(powershell); } From 8becad9f10ba74969130434c8e495deb379adda9 Mon Sep 17 00:00:00 2001 From: Szymon Kulec Date: Thu, 5 Oct 2017 15:53:16 +0200 Subject: [PATCH 2/6] Timers are reset after not receiving pipeline completion for 2 seconds --- .../PerformanceCounterUpdaterTests.cs | 43 ++++++++++++++++++- .../PerformanceCounterUpdater.cs | 31 +++++++++++-- .../PerformanceCountersFeature.cs | 6 +++ 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs index 2798dae..ccc79cc 100644 --- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs +++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs @@ -1,6 +1,8 @@ namespace Tests { + using System; using System.Collections.Generic; + using System.Threading; using NUnit.Framework; [TestFixture] @@ -130,7 +132,7 @@ public void Timers_within_payload_should_be_converted_into_performance_counters( var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", "Sender@af016c07")); var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", "Sender@af016c07")); - + Assert.AreEqual(11, performanceCounterOne.RawValue); Assert.AreEqual(22, performanceCounterTwo.RawValue); } @@ -196,6 +198,45 @@ public void Timers_within_payload_should_be_converted_into_performance_counters( } ] }"; + [Test] + public void Timers_within_payload_should_be_reported_as_zeros_after_specific_period_from_last_observed_pipeline_completion() + { + var resetTimersAfter = TimeSpan.FromMilliseconds(100); + + var cache = new MockPerformanceCountersCache(); + var sut = new PerformanceCounterUpdater(cache, new Dictionary(), resetTimersAfter); + + Thread.Sleep(TimeSpan.FromTicks(resetTimersAfter.Ticks * 2)); + + sut.Update(PayloadWithRandomTimers); + + var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", "Sender@af016c07")); + var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", "Sender@af016c07")); + + Assert.AreEqual(0, performanceCounterOne.RawValue); + Assert.AreEqual(0, performanceCounterTwo.RawValue); + } + + [Test] + public void Timers_within_payload_should_be_reported_properly_after_observed_pipeline_completion() + { + var resetTimersAfter = TimeSpan.FromMilliseconds(100); + + var cache = new MockPerformanceCountersCache(); + var sut = new PerformanceCounterUpdater(cache, new Dictionary(), resetTimersAfter); + + Thread.Sleep(TimeSpan.FromTicks(resetTimersAfter.Ticks * 2)); + + sut.OnReceivePipelineCompleted(); + + sut.Update(PayloadWithRandomTimers); + + var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", "Sender@af016c07")); + var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", "Sender@af016c07")); + + Assert.AreEqual(11, performanceCounterOne.RawValue); + Assert.AreEqual(22, performanceCounterTwo.RawValue); + } } class MockPerformanceCountersCache : PerformanceCountersCache diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs index 3ee8061..77ed25f 100644 --- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs +++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs @@ -1,12 +1,18 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Threading; using Newtonsoft.Json.Linq; class PerformanceCounterUpdater { - public PerformanceCounterUpdater(PerformanceCountersCache cache, Dictionary legacyInstanceNameMap) + public PerformanceCounterUpdater(PerformanceCountersCache cache, Dictionary legacyInstanceNameMap, TimeSpan? resetTimersAfter = null) { + resetAfterTicks = (resetTimersAfter ?? TimeSpan.FromSeconds(2)).Ticks; this.legacyInstanceNameMap = legacyInstanceNameMap; this.cache = cache; + + // initialize to an armed state + OnReceivePipelineCompleted(); } public void Update(string payload) @@ -28,11 +34,28 @@ public void Update(string payload) foreach (var timer in timers) { var performanceCounterInstance = cache.Get(new CounterInstanceName(timer.Name, context)); - - performanceCounterInstance.RawValue = timer.Histogram.LastValue / 1000; + + var idleFor = NowTicks - Volatile.Read(ref lastCompleted); + if (idleFor > resetAfterTicks) + { + performanceCounterInstance.RawValue = 0; + } + else + { + performanceCounterInstance.RawValue = timer.Histogram.LastValue / 1000; + } } } readonly PerformanceCountersCache cache; readonly Dictionary legacyInstanceNameMap; + long lastCompleted; + + public void OnReceivePipelineCompleted() + { + Volatile.Write(ref lastCompleted, NowTicks); + } + + static long NowTicks => DateTime.UtcNow.Ticks; + readonly long resetAfterTicks; } \ No newline at end of file diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs index a4eded0..cbc69e9 100644 --- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs +++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs @@ -31,6 +31,12 @@ protected override void Setup(FeatureConfigurationContext context) context.RegisterStartupTask(new Cleanup(this)); + context.Pipeline.OnReceivePipelineCompleted(_=> + { + updater.OnReceivePipelineCompleted(); + return TaskExtensions.CompletedTask; + }); + options.EnableCustomReport(payload => { updater?.Update(payload); From 07430634b006c9f9233fb7537412d1e05e63e48b Mon Sep 17 00:00:00 2001 From: Szymon Kulec Date: Wed, 8 Nov 2017 17:28:03 +0100 Subject: [PATCH 3/6] Approved fixed --- .../CSharpCodeGenerationTests.Generates.approved.cs | 4 ++-- .../PowershellCodeGenerationTests.Generates.approved.ps1 | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs b/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs index 785f2f6..e22dc50 100644 --- a/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs +++ b/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs @@ -4,9 +4,9 @@ using System.Runtime.CompilerServices; [CompilerGenerated] -public static class CounterCreator +public static class CounterCreator { - public static void Create() + public static void Create() { var counterCreationCollection = new CounterCreationDataCollection(Counters); try diff --git a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 index b1b26f5..53d1d67 100644 --- a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 +++ b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 @@ -1,3 +1,4 @@ + #requires -RunAsAdministrator Function InstallNSBPerfCounters { From 8d524659052551cd97bce06fa2d1aa5e64205a2b Mon Sep 17 00:00:00 2001 From: Szymon Kulec Date: Wed, 8 Nov 2017 17:34:18 +0100 Subject: [PATCH 4/6] Integration test cleaned up. CriticalTime and Processing Time assertions temporarily disabled --- .../IntegrationTests.cs | 20 ++++++++++--------- .../ScriptBuilderTask.Tests.csproj | 6 ++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs index 3500649..ed26368 100644 --- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs +++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs @@ -8,6 +8,7 @@ [TestFixture] public class IntegrationTests { + const string EndpointName = "PerfCountersIntegrationTests"; static ManualResetEvent ManualResetEvent = new ManualResetEvent(false); [Test] @@ -15,8 +16,7 @@ public async Task Ensure_counters_are_written() { string message = null; - var endpointName = "PerfCountersIntegrationTests"; - var endpointConfiguration = EndpointConfigBuilder.BuildEndpoint(endpointName); + var endpointConfiguration = EndpointConfigBuilder.BuildEndpoint(EndpointName); endpointConfiguration.DefineCriticalErrorAction( context => { @@ -40,13 +40,13 @@ await Task.Delay(1500) await endpoint.Stop() .ConfigureAwait(false); - var criticalTimePerfCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.CriticalTimeCounterName, endpointName, true); - //var processingTimePerfCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.ProcessingTimeCounterName, endpointName, true); - var slaPerCounter = new PerformanceCounter("NServiceBus", SLAMonitoringFeature.CounterName, endpointName, true); - var messagesFailuresPerSecondCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.MessagesFailuresPerSecondCounterName, endpointName, true); - var messagesProcessedPerSecondCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.MessagesProcessedPerSecondCounterName, endpointName, true); - var messagesPulledPerSecondCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.MessagesPulledPerSecondCounterName, endpointName, true); - Assert.AreNotEqual(0, criticalTimePerfCounter.RawValue); + var criticalTimePerfCounter = GetCounter(PerformanceCountersFeature.CriticalTimeCounterName); + var processingTimePerfCounter = GetCounter(PerformanceCountersFeature.ProcessingTimeCounterName); + var slaPerCounter = GetCounter(SLAMonitoringFeature.CounterName); + var messagesFailuresPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesFailuresPerSecondCounterName); + var messagesProcessedPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesProcessedPerSecondCounterName); + var messagesPulledPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesPulledPerSecondCounterName); + //Assert.AreNotEqual(0, criticalTimePerfCounter.RawValue); //Assert.AreNotEqual(0, processingTimePerfCounter.RawValue); Assert.AreNotEqual(0, slaPerCounter.RawValue); Assert.AreEqual(0, messagesFailuresPerSecondCounter.RawValue); @@ -56,6 +56,8 @@ await endpoint.Stop() Assert.IsNull(message); } + static PerformanceCounter GetCounter(string counterName) => new PerformanceCounter("NServiceBus", counterName, EndpointName, true); + public class MyHandler : IHandleMessages { public Task Handle(MyMessage message, IMessageHandlerContext context) diff --git a/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj b/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj index 4211a74..e498e15 100644 --- a/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj +++ b/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj @@ -7,6 +7,12 @@ full True + + + + + + From ea5c03d19672729cecd60ccca4284fe81cd86b95 Mon Sep 17 00:00:00 2001 From: Szymon Kulec Date: Wed, 8 Nov 2017 17:42:44 +0100 Subject: [PATCH 5/6] Integration test fix --- .../IntegrationTests.cs | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs index ed26368..a06d254 100644 --- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs +++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs @@ -31,6 +31,17 @@ public async Task Ensure_counters_are_written() var endpoint = await Endpoint.Start(endpointConfiguration) .ConfigureAwait(false); + var criticalTime = GetCounter(PerformanceCountersFeature.CriticalTimeCounterName); + var processingTime = GetCounter(PerformanceCountersFeature.ProcessingTimeCounterName); + + Assert.AreEqual(0, criticalTime.RawValue); + Assert.AreEqual(0, processingTime.RawValue); + + var cancellation = new CancellationTokenSource(); + + var criticalTimeReading = ReadNonZero(criticalTime, cancellation); + var processingTimeReading = ReadNonZero(processingTime, cancellation); + await endpoint.SendLocal(new MyMessage()) .ConfigureAwait(false); @@ -40,14 +51,13 @@ await Task.Delay(1500) await endpoint.Stop() .ConfigureAwait(false); - var criticalTimePerfCounter = GetCounter(PerformanceCountersFeature.CriticalTimeCounterName); - var processingTimePerfCounter = GetCounter(PerformanceCountersFeature.ProcessingTimeCounterName); + cancellation.Cancel(); var slaPerCounter = GetCounter(SLAMonitoringFeature.CounterName); var messagesFailuresPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesFailuresPerSecondCounterName); var messagesProcessedPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesProcessedPerSecondCounterName); var messagesPulledPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesPulledPerSecondCounterName); - //Assert.AreNotEqual(0, criticalTimePerfCounter.RawValue); - //Assert.AreNotEqual(0, processingTimePerfCounter.RawValue); + Assert.True(await criticalTimeReading); + Assert.True(await processingTimeReading); Assert.AreNotEqual(0, slaPerCounter.RawValue); Assert.AreEqual(0, messagesFailuresPerSecondCounter.RawValue); Assert.AreNotEqual(0, messagesProcessedPerSecondCounter.RawValue); @@ -56,6 +66,21 @@ await endpoint.Stop() Assert.IsNull(message); } + static async Task ReadNonZero(PerformanceCounter counter, CancellationTokenSource cancellation) + { + while (counter.RawValue == 0) + { + if (cancellation.IsCancellationRequested) + { + return false; + } + + await Task.Delay(TimeSpan.FromMilliseconds(10)); + } + + return true; + } + static PerformanceCounter GetCounter(string counterName) => new PerformanceCounter("NServiceBus", counterName, EndpointName, true); public class MyHandler : IHandleMessages From 67560a71e379f6007b9972cc8db5829f26dd72ab Mon Sep 17 00:00:00 2001 From: Szymon Kulec Date: Mon, 13 Nov 2017 09:31:36 +0100 Subject: [PATCH 6/6] A minor renaming --- .../PerformanceCounterUpdater.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs index baab0c3..21dc58c 100644 --- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs +++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs @@ -48,7 +48,7 @@ public void Observe(ProbeContext context) { var key = new CounterInstanceName(durationProbe.Name, endpointName); var performanceCounterInstance = cache.Get(key); - expirable[key] = performanceCounterInstance; + resettable[key] = performanceCounterInstance; durationProbe.Register((ref DurationEvent d) => performanceCounterInstance.RawValue = (long) d.Duration.TotalSeconds); } @@ -66,7 +66,7 @@ public void Observe(ProbeContext context) readonly PerformanceCountersCache cache; readonly Dictionary legacyInstanceNameMap; - readonly ConcurrentDictionary expirable = new ConcurrentDictionary(); + readonly ConcurrentDictionary resettable = new ConcurrentDictionary(); long lastCompleted; public void OnReceivePipelineCompleted() @@ -83,7 +83,7 @@ async Task Cleanup() var idleFor = NowTicks - Volatile.Read(ref lastCompleted); if (idleFor > resetEvery.Ticks) { - foreach (var performanceCounter in expirable) + foreach (var performanceCounter in resettable) { performanceCounter.Value.RawValue = 0; }