Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 711e612

Browse files
author
John Salem
authored
[release/3.1] Handle Counter Polling Interval of 0 (#28180)
* Backport dotnet/runtime#53836 * Fix test build * update test
1 parent 53cff17 commit 711e612

File tree

3 files changed

+143
-4
lines changed

3 files changed

+143
-4
lines changed

src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,9 @@ private void OnTimer()
240240
lock (s_counterGroupLock)
241241
{
242242
_timeStampSinceCollectionStarted = now;
243-
do
244-
{
245-
_nextPollingTimeStamp += new TimeSpan(0, 0, 0, 0, _pollingIntervalInMilliseconds);
246-
} while (_nextPollingTimeStamp <= now);
243+
TimeSpan delta = now - _nextPollingTimeStamp;
244+
if (delta > TimeSpan.Zero && _pollingIntervalInMilliseconds > 0)
245+
_nextPollingTimeStamp += TimeSpan.FromMilliseconds(_pollingIntervalInMilliseconds * Math.Ceiling(delta.TotalMilliseconds / _pollingIntervalInMilliseconds));
247246
}
248247
}
249248
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#if USE_MDT_EVENTSOURCE
5+
using Microsoft.Diagnostics.Tracing;
6+
#else
7+
using System.Diagnostics.Tracing;
8+
#endif
9+
using System;
10+
using System.Collections.Generic;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
using System.Diagnostics;
14+
15+
namespace gh53564Tests
16+
{
17+
public class RuntimeCounterListener : EventListener
18+
{
19+
public RuntimeCounterListener(){}
20+
21+
private DateTime? setToZeroTimestamp = null;
22+
private DateTime? mostRecentTimestamp = null;
23+
private ManualResetEvent setToZero = new ManualResetEvent(initialState: false);
24+
public ManualResetEvent ReadyToVerify { get; } = new ManualResetEvent(initialState: false);
25+
26+
protected override void OnEventSourceCreated(EventSource source)
27+
{
28+
if (source.Name.Equals("System.Runtime"))
29+
{
30+
Dictionary<string, string> refreshInterval = new Dictionary<string, string>();
31+
32+
Console.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}] OnEventSourceCreated :: Setting interval to 1");
33+
// first set interval to 1 seconds
34+
refreshInterval["EventCounterIntervalSec"] = "1";
35+
EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval);
36+
37+
// wait a moment to get some events
38+
Thread.Sleep(TimeSpan.FromSeconds(3));
39+
40+
// then set interval to 0
41+
Console.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}] OnEventSourceCreated :: Setting interval to 0");
42+
refreshInterval["EventCounterIntervalSec"] = "0";
43+
EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval);
44+
setToZeroTimestamp = DateTime.UtcNow + TimeSpan.FromSeconds(1); // Stash timestamp 1 second after setting to 0
45+
setToZero.Set();
46+
47+
// then attempt to set interval back to 1
48+
Thread.Sleep(TimeSpan.FromSeconds(3));
49+
Console.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}] OnEventSourceCreated :: Setting interval to 1");
50+
refreshInterval["EventCounterIntervalSec"] = "1";
51+
EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval);
52+
}
53+
}
54+
55+
protected override void OnEventWritten(EventWrittenEventArgs eventData)
56+
{
57+
if (!ReadyToVerify.WaitOne(0))
58+
{
59+
mostRecentTimestamp = eventData.TimeStamp;
60+
if (setToZero.WaitOne(0) && mostRecentTimestamp > setToZeroTimestamp)
61+
{
62+
Console.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}] OnEventWritten :: Setting ReadyToVerify");
63+
ReadyToVerify.Set();
64+
}
65+
}
66+
}
67+
68+
public bool Verify()
69+
{
70+
if (!ReadyToVerify.WaitOne(0))
71+
return false;
72+
73+
Console.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}] Verify :: Verifying");
74+
Console.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}] setToZeroTimestamp = {setToZeroTimestamp?.ToString("hh:mm:ss.fff") ?? "NULL"}");
75+
Console.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}] mostRecentTimestamp = {mostRecentTimestamp?.ToString("hh:mm:ss.fff") ?? "NULL"}");
76+
77+
return (setToZeroTimestamp is null || mostRecentTimestamp is null) ? false : setToZeroTimestamp < mostRecentTimestamp;
78+
}
79+
}
80+
81+
public partial class TestRuntimeEventCounter
82+
{
83+
public static int Main(string[] args)
84+
{
85+
// Create an EventListener.
86+
using (RuntimeCounterListener myListener = new RuntimeCounterListener())
87+
{
88+
if (myListener.ReadyToVerify.WaitOne(TimeSpan.FromSeconds(30)))
89+
{
90+
if (myListener.Verify())
91+
{
92+
Console.WriteLine("Test passed");
93+
return 100;
94+
}
95+
else
96+
{
97+
Console.WriteLine($"Test Failed - did not see one or more of the expected runtime counters.");
98+
return 1;
99+
}
100+
}
101+
else
102+
{
103+
Console.WriteLine("Test Failed - timed out waiting for reset");
104+
return 1;
105+
}
106+
}
107+
}
108+
}
109+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<SchemaVersion>2.0</SchemaVersion>
8+
<ProjectGuid>{8E3244CB-407F-4142-BAAB-E7A55901A5FA}</ProjectGuid>
9+
<OutputType>Exe</OutputType>
10+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
11+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
12+
<CLRTestKind>BuildAndRun</CLRTestKind>
13+
<DefineConstants>$(DefineConstants);STATIC</DefineConstants>
14+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
15+
<CLRTestPriority>0</CLRTestPriority>
16+
<GCStressIncompatible>true</GCStressIncompatible>
17+
<!-- This test has a secondary thread with an infinite loop -->
18+
<UnloadabilityIncompatible>true</UnloadabilityIncompatible>
19+
</PropertyGroup>
20+
<!-- Default configurations to help VS understand the configurations -->
21+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
22+
</PropertyGroup>
23+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
24+
</PropertyGroup>
25+
<ItemGroup>
26+
<Compile Include="gh53564.cs" />
27+
<ProjectReference Include="../common/common.csproj" />
28+
</ItemGroup>
29+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
30+
</Project>
31+

0 commit comments

Comments
 (0)