Skip to content

Commit 800c51a

Browse files
committed
PR feedback and additional tests
1 parent f4d2567 commit 800c51a

File tree

3 files changed

+220
-43
lines changed

3 files changed

+220
-43
lines changed

src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MeterListener.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public sealed class MeterListener : IDisposable
3535

3636
static MeterListener()
3737
{
38+
// This ensures that the static Meter gets created before any listeners exist.
3839
_ = RuntimeMetrics.IsEnabled();
3940
}
4041

src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/RuntimeMetrics.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,34 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Generic;
5-
using System.Runtime.CompilerServices;
6-
#if !NETFRAMEWORK && !NETSTANDARD
5+
#if NET
76
using System.Threading;
87
#endif
98

109
namespace System.Diagnostics.Metrics
1110
{
1211
internal static class RuntimeMetrics
1312
{
13+
[ThreadStatic] private static bool t_handlingFirstChanceException;
14+
1415
private const string MeterName = "System.Runtime";
1516

1617
private static readonly Meter s_meter = new(MeterName);
1718

1819
// These MUST align to the possible attribute values defined in the semantic conventions (TODO: link to the spec)
1920
private static readonly string[] s_genNames = ["gen0", "gen1", "gen2", "loh", "poh"];
20-
#if !NETFRAMEWORK && !NETSTANDARD
21+
#if NET
2122
private static readonly int s_maxGenerations = Math.Min(GC.GetGCMemoryInfo().GenerationInfo.Length, s_genNames.Length);
2223
#endif
2324

2425
static RuntimeMetrics()
2526
{
2627
AppDomain.CurrentDomain.FirstChanceException += (source, e) =>
2728
{
29+
if (t_handlingFirstChanceException) return;
30+
t_handlingFirstChanceException = true;
2831
s_exceptionCount.Add(1, new KeyValuePair<string, object?>("error.type", e.Exception.GetType().Name));
32+
t_handlingFirstChanceException = false;
2933
};
3034
}
3135

@@ -43,15 +47,15 @@ static RuntimeMetrics()
4347
unit: "By",
4448
description: "The number of bytes currently allocated on the managed GC heap. Fragmentation and other GC committed memory pools are excluded.");
4549

46-
#if !NETFRAMEWORK && !NETSTANDARD
50+
#if NET
4751
private static readonly ObservableCounter<long> s_gcMemoryTotalAllocated = s_meter.CreateObservableCounter(
4852
"dotnet.gc.memory.total_allocated",
4953
() => GC.GetTotalAllocatedBytes(),
5054
unit: "By",
5155
description: "The approximate number of bytes allocated on the managed GC heap since the process has started. The returned value does not include any native allocations.");
5256

5357
private static readonly ObservableUpDownCounter<long> s_gcMemoryCommited = s_meter.CreateObservableUpDownCounter(
54-
"dotnet.gc.memory.commited",
58+
"dotnet.gc.memory.committed",
5559
() =>
5660
{
5761
GCMemoryInfo gcInfo = GC.GetGCMemoryInfo();
@@ -61,7 +65,7 @@ static RuntimeMetrics()
6165
: [new(gcInfo.TotalCommittedBytes)];
6266
},
6367
unit: "By",
64-
description: "The amount of committed virtual memory for the managed GC heap, as observed during the latest garbage collection.");
68+
description: "The amount of committed virtual memory in use by the .NET GC, as observed during the latest garbage collection.");
6569

6670
private static readonly ObservableUpDownCounter<long> s_gcHeapSize = s_meter.CreateObservableUpDownCounter(
6771
"dotnet.gc.heap.size",
@@ -106,7 +110,7 @@ static RuntimeMetrics()
106110
private static readonly ObservableCounter<long> s_monitorLockContention = s_meter.CreateObservableCounter(
107111
"dotnet.monitor.lock_contention.count",
108112
() => Monitor.LockContentionCount,
109-
unit: "s",
113+
unit: "{contention}",
110114
description: "The number of times there was contention when trying to acquire a monitor lock since the process has started.");
111115

112116
// Thread Pool Metrics
@@ -161,13 +165,13 @@ static RuntimeMetrics()
161165
"dotnet.cpu.time",
162166
GetCpuTime,
163167
unit: "s",
164-
description: "The number of work items that are currently queued to be processed by the thread pool.");
168+
description: "CPU time used by the process as reported by the CLR.");
165169

166170
public static bool IsEnabled()
167171
{
168172
return s_gcCollectionsCounter.Enabled
169173
|| s_gcObjectsSize.Enabled
170-
#if !NETFRAMEWORK && !NETSTANDARD
174+
#if NET
171175
|| s_gcMemoryTotalAllocated.Enabled
172176
|| s_gcMemoryCommited.Enabled
173177
|| s_gcHeapSize.Enabled
@@ -202,7 +206,7 @@ private static IEnumerable<Measurement<long>> GetGarbageCollectionCounts()
202206

203207
private static IEnumerable<Measurement<double>> GetCpuTime()
204208
{
205-
#if !NETFRAMEWORK && !NETSTANDARD
209+
#if NET
206210
if (OperatingSystem.IsBrowser() || OperatingSystem.IsTvOS() || OperatingSystem.IsIOS())
207211
yield break;
208212
#endif
@@ -213,7 +217,7 @@ private static IEnumerable<Measurement<double>> GetCpuTime()
213217
yield return new(process.PrivilegedProcessorTime.TotalSeconds, [new KeyValuePair<string, object?>("cpu.mode", "system")]);
214218
}
215219

216-
#if !NETFRAMEWORK && !NETSTANDARD
220+
#if NET
217221
private static IEnumerable<Measurement<long>> GetHeapSizes()
218222
{
219223
GCMemoryInfo gcInfo = GC.GetGCMemoryInfo();

0 commit comments

Comments
 (0)