Skip to content

Commit 4a1e5f4

Browse files
github-actions[bot]stephentoubericstj
authored
[release/8.0-staging] Fix FormatQuantiles formatting in MetricsEventSource (#99045)
* Fix FormatQuantiles formatting in MetricsEventSource These doubles need to be formatted with the invariant culture to meet consumer expectations around parsing them. * Enable DiagnosticSource for servicing --------- Co-authored-by: Stephen Toub <stoub@microsoft.com> Co-authored-by: Eric StJohn <ericstj@microsoft.com>
1 parent d66d790 commit 4a1e5f4

File tree

3 files changed

+73
-54
lines changed

3 files changed

+73
-54
lines changed

src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
<NoWarn>$(NoWarn);SA1205</NoWarn>
77
<EnableTrimAnalyzer Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETFramework'">false</EnableTrimAnalyzer>
88
<IsPackable>true</IsPackable>
9+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
10+
<ServicingVersion>1</ServicingVersion>
911
<PackageDescription>Provides Classes that allow you to decouple code logging rich (unserializable) diagnostics/telemetry (e.g. framework) from code that consumes it (e.g. tools)
1012

1113
Commonly Used Types:

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,11 @@ private static string FormatQuantiles(QuantileValue[] quantiles)
737737
StringBuilder sb = new StringBuilder();
738738
for (int i = 0; i < quantiles.Length; i++)
739739
{
740-
sb.Append(quantiles[i].Quantile).Append('=').Append(quantiles[i].Value);
740+
#if NETCOREAPP
741+
sb.Append(CultureInfo.InvariantCulture, $"{quantiles[i].Quantile}={quantiles[i].Value}");
742+
#else
743+
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", quantiles[i].Quantile, quantiles[i].Value);
744+
#endif
741745
if (i != quantiles.Length - 1)
742746
{
743747
sb.Append(';');

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

+66-53
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System;
54
using System.Collections.Generic;
65
using System.Diagnostics.Tracing;
76
using System.Globalization;
87
using System.Linq;
98
using System.Runtime.CompilerServices;
109
using System.Text;
1110
using System.Threading;
12-
using System.Threading.Tasks;
11+
using Microsoft.DotNet.RemoteExecutor;
1312
using Xunit;
1413
using Xunit.Abstractions;
1514

@@ -658,45 +657,59 @@ public void MultipleListeners_PublishingInstruments()
658657
AssertInitialEnumerationCompleteEventPresent(events2);
659658
}
660659

661-
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
660+
public static bool IsNotBrowserAndRemoteExecuteSupported => PlatformDetection.IsNotBrowser && RemoteExecutor.IsSupported;
661+
662+
[ConditionalFact(typeof(MetricEventSourceTests), nameof(IsNotBrowserAndRemoteExecuteSupported))]
662663
[OuterLoop("Slow and has lots of console spew")]
663664
public void EventSourcePublishesTimeSeriesWithEmptyMetadata()
664665
{
665-
using Meter meter = new Meter("TestMeter1", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object());
666-
Counter<int> c = meter.CreateCounter<int>("counter1");
667-
int counterState = 3;
668-
ObservableCounter<int> oc = meter.CreateObservableCounter<int>("observableCounter1", () => { counterState += 7; return counterState; });
669-
int gaugeState = 0;
670-
ObservableGauge<int> og = meter.CreateObservableGauge<int>("observableGauge1", () => { gaugeState += 9; return gaugeState; });
671-
Histogram<int> h = meter.CreateHistogram<int>("histogram1");
672-
UpDownCounter<int> udc = meter.CreateUpDownCounter<int>("upDownCounter1");
673-
int upDownCounterState = 0;
674-
ObservableUpDownCounter<int> oudc = meter.CreateObservableUpDownCounter<int>("observableUpDownCounter1", () => { upDownCounterState -= 11; return upDownCounterState; });
675-
676-
EventWrittenEventArgs[] events;
677-
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter1"))
666+
RemoteExecutor.Invoke(static () =>
678667
{
679-
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
680-
c.Add(5);
681-
h.Record(19);
682-
udc.Add(-33);
683-
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
684-
c.Add(12);
685-
h.Record(26);
686-
udc.Add(-40);
687-
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
688-
events = listener.Events.ToArray();
689-
}
668+
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("fi-FI");
690669

691-
AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
692-
AssertInitialEnumerationCompleteEventPresent(events);
693-
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", ("5", "5"), ("12", "17"));
694-
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", ("", "10"), ("7", "17"));
695-
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "9", "18");
696-
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", ("0.5=19;0.95=19;0.99=19", "1", "19"), ("0.5=26;0.95=26;0.99=26", "1", "26"));
697-
AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", ("-33", "-33"), ("-40", "-73"));
698-
AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", ("", "-11"), ("-11", "-22"));
699-
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
670+
using Meter meter = new Meter("TestMeter1", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object());
671+
Counter<int> c = meter.CreateCounter<int>("counter1");
672+
int counterState = 3;
673+
ObservableCounter<int> oc = meter.CreateObservableCounter<int>("observableCounter1", () => { counterState += 7; return counterState; });
674+
int gaugeState = 0;
675+
ObservableGauge<int> og = meter.CreateObservableGauge<int>("observableGauge1", () => { gaugeState += 9; return gaugeState; });
676+
Histogram<int> h = meter.CreateHistogram<int>("histogram1");
677+
UpDownCounter<int> udc = meter.CreateUpDownCounter<int>("upDownCounter1");
678+
int upDownCounterState = 0;
679+
ObservableUpDownCounter<int> oudc = meter.CreateObservableUpDownCounter<int>("observableUpDownCounter1", () => { upDownCounterState -= 11; return upDownCounterState; });
680+
681+
EventWrittenEventArgs[] events;
682+
using (MetricsEventListener listener = new MetricsEventListener(NullTestOutputHelper.Instance, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter1"))
683+
{
684+
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
685+
c.Add(5);
686+
h.Record(19);
687+
udc.Add(-33);
688+
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
689+
c.Add(12);
690+
h.Record(26);
691+
udc.Add(-40);
692+
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
693+
events = listener.Events.ToArray();
694+
}
695+
696+
AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
697+
AssertInitialEnumerationCompleteEventPresent(events);
698+
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", ("5", "5"), ("12", "17"));
699+
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", ("", "10"), ("7", "17"));
700+
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "9", "18");
701+
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", ("0.5=19;0.95=19;0.99=19", "1", "19"), ("0.5=26;0.95=26;0.99=26", "1", "26"));
702+
AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", ("-33", "-33"), ("-40", "-73"));
703+
AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", ("", "-11"), ("-11", "-22"));
704+
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
705+
}).Dispose();
706+
}
707+
708+
private sealed class NullTestOutputHelper : ITestOutputHelper
709+
{
710+
public static NullTestOutputHelper Instance { get; } = new();
711+
public void WriteLine(string message) { }
712+
public void WriteLine(string format, params object[] args) { }
700713
}
701714

702715
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
@@ -1470,7 +1483,7 @@ private static string FormatTags(IEnumerable<KeyValuePair<string, object?>>? tag
14701483
return sb.ToString();
14711484
}
14721485

1473-
private void AssertBeginInstrumentReportingEventsPresent(EventWrittenEventArgs[] events, params Instrument[] expectedInstruments)
1486+
private static void AssertBeginInstrumentReportingEventsPresent(EventWrittenEventArgs[] events, params Instrument[] expectedInstruments)
14741487
{
14751488
var beginReportEvents = events.Where(e => e.EventName == "BeginInstrumentReporting").Select(e =>
14761489
new
@@ -1502,7 +1515,7 @@ private void AssertBeginInstrumentReportingEventsPresent(EventWrittenEventArgs[]
15021515
Assert.Equal(expectedInstruments.Length, beginReportEvents.Length);
15031516
}
15041517

1505-
private void AssertEndInstrumentReportingEventsPresent(EventWrittenEventArgs[] events, params Instrument[] expectedInstruments)
1518+
private static void AssertEndInstrumentReportingEventsPresent(EventWrittenEventArgs[] events, params Instrument[] expectedInstruments)
15061519
{
15071520
var beginReportEvents = events.Where(e => e.EventName == "EndInstrumentReporting").Select(e =>
15081521
new
@@ -1534,27 +1547,27 @@ private void AssertEndInstrumentReportingEventsPresent(EventWrittenEventArgs[] e
15341547
Assert.Equal(expectedInstruments.Length, beginReportEvents.Length);
15351548
}
15361549

1537-
private void AssertInitialEnumerationCompleteEventPresent(EventWrittenEventArgs[] events, int eventsCount = 1)
1550+
private static void AssertInitialEnumerationCompleteEventPresent(EventWrittenEventArgs[] events, int eventsCount = 1)
15381551
{
15391552
Assert.Equal(eventsCount, events.Where(e => e.EventName == "InitialInstrumentEnumerationComplete").Count());
15401553
}
15411554

1542-
private void AssertTimeSeriesLimitPresent(EventWrittenEventArgs[] events)
1555+
private static void AssertTimeSeriesLimitPresent(EventWrittenEventArgs[] events)
15431556
{
15441557
Assert.Equal(1, events.Where(e => e.EventName == "TimeSeriesLimitReached").Count());
15451558
}
15461559

1547-
private void AssertTimeSeriesLimitNotPresent(EventWrittenEventArgs[] events)
1560+
private static void AssertTimeSeriesLimitNotPresent(EventWrittenEventArgs[] events)
15481561
{
15491562
Assert.Equal(0, events.Where(e => e.EventName == "TimeSeriesLimitReached").Count());
15501563
}
15511564

1552-
private void AssertHistogramLimitPresent(EventWrittenEventArgs[] events)
1565+
private static void AssertHistogramLimitPresent(EventWrittenEventArgs[] events)
15531566
{
15541567
Assert.Equal(1, events.Where(e => e.EventName == "HistogramLimitReached").Count());
15551568
}
15561569

1557-
private void AssertInstrumentPublishingEventsPresent(EventWrittenEventArgs[] events, params Instrument[] expectedInstruments)
1570+
private static void AssertInstrumentPublishingEventsPresent(EventWrittenEventArgs[] events, params Instrument[] expectedInstruments)
15581571
{
15591572
var publishEvents = events.Where(e => e.EventName == "InstrumentPublished").Select(e =>
15601573
new
@@ -1586,19 +1599,19 @@ private void AssertInstrumentPublishingEventsPresent(EventWrittenEventArgs[] eve
15861599
Assert.Equal(expectedInstruments.Length, publishEvents.Length);
15871600
}
15881601

1589-
private void AssertCounterEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
1602+
private static void AssertCounterEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
15901603
string expectedUnit, params (string, string)[] expected)
15911604
{
15921605
AssertGenericCounterEventsPresent("CounterRateValuePublished", events, meterName, instrumentName, tags, expectedUnit, expected);
15931606
}
15941607

1595-
private void AssertUpDownCounterEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
1608+
private static void AssertUpDownCounterEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
15961609
string expectedUnit, params (string, string)[] expected)
15971610
{
15981611
AssertGenericCounterEventsPresent("UpDownCounterRateValuePublished", events, meterName, instrumentName, tags, expectedUnit, expected);
15991612
}
16001613

1601-
private void AssertGenericCounterEventsPresent(string eventName, EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
1614+
private static void AssertGenericCounterEventsPresent(string eventName, EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
16021615
string expectedUnit, params (string, string)[] expected)
16031616
{
16041617
var counterEvents = events.Where(e => e.EventName == eventName).Select(e =>
@@ -1622,7 +1635,7 @@ private void AssertGenericCounterEventsPresent(string eventName, EventWrittenEve
16221635
}
16231636
}
16241637

1625-
private void AssertCounterEventsNotPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags)
1638+
private static void AssertCounterEventsNotPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags)
16261639
{
16271640
var counterEvents = events.Where(e => e.EventName == "CounterRateValuePublished").Select(e =>
16281641
new
@@ -1636,7 +1649,7 @@ private void AssertCounterEventsNotPresent(EventWrittenEventArgs[] events, strin
16361649
Assert.Equal(0, filteredEvents.Length);
16371650
}
16381651

1639-
private void AssertGaugeEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
1652+
private static void AssertGaugeEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
16401653
string expectedUnit, params string[] expectedValues)
16411654
{
16421655
var counterEvents = events.Where(e => e.EventName == "GaugeValuePublished").Select(e =>
@@ -1658,7 +1671,7 @@ private void AssertGaugeEventsPresent(EventWrittenEventArgs[] events, string met
16581671
}
16591672
}
16601673

1661-
private void AssertHistogramEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
1674+
private static void AssertHistogramEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
16621675
string expectedUnit, params (string, string, string)[] expected)
16631676
{
16641677
var counterEvents = events.Where(e => e.EventName == "HistogramValuePublished").Select(e =>
@@ -1684,7 +1697,7 @@ private void AssertHistogramEventsPresent(EventWrittenEventArgs[] events, string
16841697
}
16851698
}
16861699

1687-
private void AssertHistogramEventsNotPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags)
1700+
private static void AssertHistogramEventsNotPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags)
16881701
{
16891702
var counterEvents = events.Where(e => e.EventName == "HistogramValuePublished").Select(e =>
16901703
new
@@ -1697,7 +1710,7 @@ private void AssertHistogramEventsNotPresent(EventWrittenEventArgs[] events, str
16971710
var filteredEvents = counterEvents.Where(e => e.MeterName == meterName && e.InstrumentName == instrumentName && e.Tags == tags).ToArray();
16981711
Assert.Equal(0, filteredEvents.Length);
16991712
}
1700-
private void AssertCollectStartStopEventsPresent(EventWrittenEventArgs[] events, double expectedIntervalSecs, int expectedPairs)
1713+
private static void AssertCollectStartStopEventsPresent(EventWrittenEventArgs[] events, double expectedIntervalSecs, int expectedPairs)
17011714
{
17021715
int startEventsSeen = 0;
17031716
int stopEventsSeen = 0;
@@ -1726,7 +1739,7 @@ private void AssertCollectStartStopEventsPresent(EventWrittenEventArgs[] events,
17261739
Assert.Equal(expectedPairs, stopEventsSeen);
17271740
}
17281741

1729-
private void AssertObservableCallbackErrorPresent(EventWrittenEventArgs[] events)
1742+
private static void AssertObservableCallbackErrorPresent(EventWrittenEventArgs[] events)
17301743
{
17311744
var errorEvents = events.Where(e => e.EventName == "ObservableInstrumentCallbackError").Select(e =>
17321745
new
@@ -1737,7 +1750,7 @@ private void AssertObservableCallbackErrorPresent(EventWrittenEventArgs[] events
17371750
Assert.Contains("Example user exception", errorEvents[0].ErrorText);
17381751
}
17391752

1740-
private void AssertMultipleSessionsConfiguredIncorrectlyErrorEventsPresent(EventWrittenEventArgs[] events,
1753+
private static void AssertMultipleSessionsConfiguredIncorrectlyErrorEventsPresent(EventWrittenEventArgs[] events,
17411754
string expectedMaxHistograms, string actualMaxHistograms, string expectedMaxTimeSeries, string actualMaxTimeSeries,
17421755
string expectedRefreshInterval, string actualRefreshInterval)
17431756
{

0 commit comments

Comments
 (0)