Skip to content

Commit d7fc2f5

Browse files
authored
[System.Diagnostics.DiagnosticSource] Support listening to meters out-of-proc using a wildcard (#105581)
* Support listening to meters out-of-proc using a wildcard. * Support prefix in addition to wildcard. * Code review.
1 parent 8839704 commit d7fc2f5

File tree

3 files changed

+95
-3
lines changed

3 files changed

+95
-3
lines changed

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,23 @@ public AggregationManager(
8888

8989
public void Include(string meterName)
9090
{
91-
Include(i => i.Meter.Name == meterName);
91+
Include(i => i.Meter.Name.Equals(meterName, StringComparison.OrdinalIgnoreCase));
92+
}
93+
94+
public void IncludeAll()
95+
{
96+
Include(i => true);
97+
}
98+
99+
public void IncludePrefix(string meterNamePrefix)
100+
{
101+
Include(i => i.Meter.Name.StartsWith(meterNamePrefix, StringComparison.OrdinalIgnoreCase));
92102
}
93103

94104
public void Include(string meterName, string instrumentName)
95105
{
96-
Include(i => i.Meter.Name == meterName && i.Name == instrumentName);
106+
Include(i => i.Meter.Name.Equals(meterName, StringComparison.OrdinalIgnoreCase)
107+
&& i.Name.Equals(instrumentName, StringComparison.OrdinalIgnoreCase));
97108
}
98109

99110
private void Include(Predicate<Instrument> instrumentFilter)

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,19 @@ private void ParseSpecs(string? metricsSpecs)
653653
{
654654
_aggregationManager!.Include(spec.MeterName, spec.InstrumentName);
655655
}
656+
else if (spec.MeterName.Length > 0
657+
&& spec.MeterName[spec.MeterName.Length - 1] == '*')
658+
{
659+
if (spec.MeterName.Length == 1)
660+
{
661+
_aggregationManager!.IncludeAll();
662+
}
663+
else
664+
{
665+
_aggregationManager!.IncludePrefix(
666+
spec.MeterName.Substring(0, spec.MeterName.Length - 1));
667+
}
668+
}
656669
else
657670
{
658671
_aggregationManager!.Include(spec.MeterName);

src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,74 @@ public void MultipleListeners_ThreeCounters()
215215
AssertCollectStartStopEventsPresent(events3, IntervalSecs, 2);
216216
}
217217

218+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
219+
[OuterLoop("Slow and has lots of console spew")]
220+
public void SingleListener_Wildcard()
221+
{
222+
using Meter meter = new Meter("Test.TestMeter1");
223+
Counter<int> c = meter.CreateCounter<int>("counter1");
224+
225+
using Meter meter2 = new Meter("Test.TestMeter2", null, new TagList() { { "Mk1", "Mv1" } }, new object());
226+
Counter<int> c2 = meter2.CreateCounter<int>("counter2");
227+
228+
using Meter meter3 = new Meter("Test.TestMeter3", null, new TagList() { { "MMk1", null }, { "MMk2", null } }, new object());
229+
Counter<int> c3 = meter3.CreateCounter<int>("counter3");
230+
231+
EventWrittenEventArgs[] events;
232+
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, isShared: true, IntervalSecs, "*"))
233+
{
234+
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
235+
c.Add(5);
236+
c2.Add(10);
237+
c3.Add(20);
238+
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
239+
events = listener.Events.ToArray();
240+
}
241+
242+
// Note: Need to exclude System.Runtime metrics any anything else in platform
243+
events = events.Where(e => e.EventName != "BeginInstrumentReporting"
244+
|| (e.Payload[1] as string)?.StartsWith("Test.") == true)
245+
.ToArray();
246+
247+
AssertBeginInstrumentReportingEventsPresent(events, c, c2, c3);
248+
AssertInitialEnumerationCompleteEventPresent(events);
249+
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", ("5", "5"));
250+
AssertCounterEventsPresent(events, meter2.Name, c2.Name, "", "", ("10", "10"));
251+
AssertCounterEventsPresent(events, meter3.Name, c3.Name, "", "", ("20", "20"));
252+
AssertCollectStartStopEventsPresent(events, IntervalSecs, 2);
253+
}
254+
255+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
256+
[OuterLoop("Slow and has lots of console spew")]
257+
public void SingleListener_Prefix()
258+
{
259+
using Meter meter = new Meter("Company1.TestMeter1");
260+
Counter<int> c = meter.CreateCounter<int>("counter1");
261+
262+
using Meter meter2 = new Meter("Company1.TestMeter2", null, new TagList() { { "Mk1", "Mv1" } }, new object());
263+
Counter<int> c2 = meter2.CreateCounter<int>("counter2");
264+
265+
using Meter meter3 = new Meter("Company2.TestMeter3", null, new TagList() { { "MMk1", null }, { "MMk2", null } }, new object());
266+
Counter<int> c3 = meter3.CreateCounter<int>("counter3");
267+
268+
EventWrittenEventArgs[] events;
269+
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, isShared: true, IntervalSecs, "Company1*"))
270+
{
271+
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
272+
c.Add(5);
273+
c2.Add(10);
274+
c3.Add(20);
275+
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
276+
events = listener.Events.ToArray();
277+
}
278+
279+
AssertBeginInstrumentReportingEventsPresent(events, c, c2);
280+
AssertInitialEnumerationCompleteEventPresent(events);
281+
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", ("5", "5"));
282+
AssertCounterEventsPresent(events, meter2.Name, c2.Name, "", "", ("10", "10"));
283+
AssertCollectStartStopEventsPresent(events, IntervalSecs, 2);
284+
}
285+
218286
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
219287
[OuterLoop("Slow and has lots of console spew")]
220288
public void MultipleListeners_OverlappingListeners()
@@ -1727,7 +1795,7 @@ private static void AssertGenericCounterEventsPresent(string eventName, EventWri
17271795
Tags = e.Payload[5].ToString(),
17281796
Rate = e.Payload[6].ToString(),
17291797
Value = e.Payload[7].ToString(),
1730-
InstrumentId = (int)(e.Payload[7]),
1798+
InstrumentId = (int)(e.Payload[8]),
17311799
}).ToArray();
17321800
var filteredEvents = counterEvents.Where(e => e.MeterName == meterName && e.InstrumentName == instrumentName && e.Tags == tags).ToArray();
17331801
Assert.True(filteredEvents.Length >= expected.Length);

0 commit comments

Comments
 (0)