diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 8a769b932817ee..ac81d88b5d9788 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -26,12 +26,12 @@ public string? Id } public bool HasRemoteParent { get { throw null; } } - public bool IsAllDataRequested { get { throw null; } set { throw null; } } + public bool IsAllDataRequested { get { throw null; } set { } } public bool IsStopped { get { throw null; } } public System.Diagnostics.ActivityIdFormat IdFormat { get { throw null; } } public System.Diagnostics.ActivityKind Kind { get { throw null; } } public string OperationName { get { throw null; } } - public string DisplayName { get { throw null; } set { throw null; } } + public string DisplayName { get { throw null; } set { } } public System.Diagnostics.ActivitySource Source { get { throw null; } } public System.Diagnostics.Activity? Parent { get { throw null; } } public string? ParentId { get { throw null; } } @@ -59,7 +59,7 @@ public string? Id public string? GetBaggageItem(string key) { throw null; } public object? GetTagItem(string key) { throw null; } public System.Diagnostics.Activity SetEndTime(System.DateTime endTimeUtc) { throw null; } - public static Func? TraceIdGenerator { get { throw null; } set { throw null; } } + public static Func? TraceIdGenerator { get { throw null; } set { } } public System.Diagnostics.Activity SetIdFormat(System.Diagnostics.ActivityIdFormat format) { throw null; } public System.Diagnostics.Activity SetParentId(System.Diagnostics.ActivityTraceId traceId, System.Diagnostics.ActivitySpanId spanId, System.Diagnostics.ActivityTraceFlags activityTraceFlags = System.Diagnostics.ActivityTraceFlags.None) { throw null; } public System.Diagnostics.Activity SetParentId(string parentId) { throw null; } @@ -155,8 +155,10 @@ public sealed class ActivitySource : IDisposable [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] public ActivitySource(string name, string? version = "") { throw null; } public ActivitySource(string name, string? version = "", System.Collections.Generic.IEnumerable>? tags = default) { throw null; } + public ActivitySource(ActivitySourceOptions options) { throw null; } public string Name { get { throw null; } } public string? Version { get { throw null; } } + public string? TelemetrySchemaUrl { get; } public System.Collections.Generic.IEnumerable>? Tags { get { throw null; } } public bool HasListeners() { throw null; } public System.Diagnostics.Activity? CreateActivity(string name, System.Diagnostics.ActivityKind kind) { throw null; } @@ -169,6 +171,14 @@ public sealed class ActivitySource : IDisposable public static void AddActivityListener(System.Diagnostics.ActivityListener listener) { throw null; } public void Dispose() { throw null; } } + public class ActivitySourceOptions + { + public ActivitySourceOptions(string name) { throw null; } + public string Name { get { throw null; } set { } } + public string? Version { get { throw null; } set { } } + public System.Collections.Generic.IEnumerable>? Tags { get { throw null; } set { } } + public string? TelemetrySchemaUrl { get { throw null; } set { } } + } [System.FlagsAttribute] public enum ActivityTraceFlags { @@ -281,12 +291,12 @@ public readonly struct ActivityCreationOptions public sealed class ActivityListener : IDisposable { public ActivityListener() { throw null; } - public System.Action? ActivityStarted { get { throw null; } set { throw null; } } - public System.Action? ActivityStopped { get { throw null; } set { throw null; } } - public System.Diagnostics.ExceptionRecorder? ExceptionRecorder { get { throw null; } set { throw null; } } - public System.Func? ShouldListenTo { get { throw null; } set { throw null; } } - public System.Diagnostics.SampleActivity? SampleUsingParentId { get { throw null; } set { throw null; } } - public System.Diagnostics.SampleActivity? Sample { get { throw null; } set { throw null; } } + public System.Action? ActivityStarted { get { throw null; } set { } } + public System.Action? ActivityStopped { get { throw null; } set { } } + public System.Diagnostics.ExceptionRecorder? ExceptionRecorder { get { throw null; } set { } } + public System.Func? ShouldListenTo { get { throw null; } set { } } + public System.Diagnostics.SampleActivity? SampleUsingParentId { get { throw null; } set { } } + public System.Diagnostics.SampleActivity? Sample { get { throw null; } set { } } public void Dispose() { throw null; } } public abstract class DistributedContextPropagator @@ -565,6 +575,7 @@ public ObservableGauge CreateObservableGauge( public string? Version { get { throw null; } } public System.Collections.Generic.IEnumerable>? Tags { get { throw null; } } public object? Scope { get { throw null; } } + public string? TelemetrySchemaUrl { get { throw null; } } } public static class MeterFactoryExtensions { @@ -575,8 +586,8 @@ public sealed class MeterListener : IDisposable public object? DisableMeasurementEvents(Instrument instrument) { throw null; } public void Dispose() { throw null; } public void EnableMeasurementEvents(Instrument instrument, object? state = null) { throw null; } - public Action? InstrumentPublished { get { throw null; } set { throw null; } } - public Action? MeasurementsCompleted { get { throw null; } set { throw null; } } + public Action? InstrumentPublished { get { throw null; } set { } } + public Action? MeasurementsCompleted { get { throw null; } set { } } public MeterListener() { throw null; } public void RecordObservableInstruments() { throw null; } public void SetMeasurementEventCallback(MeasurementCallback? measurementCallback) where T : struct { throw null; } @@ -584,10 +595,11 @@ public sealed class MeterListener : IDisposable } public class MeterOptions { - public string Name { get { throw null;} set { throw null;} } - public string? Version { get { throw null;} set { throw null;} } - public System.Collections.Generic.IEnumerable>? Tags { get { throw null;} set { throw null;} } - public object? Scope { get { throw null;} set { throw null;} } + public string Name { get { throw null;} set { } } + public string? Version { get { throw null;} set { } } + public System.Collections.Generic.IEnumerable>? Tags { get { throw null;} set { } } + public object? Scope { get { throw null;} set { } } + public string? TelemetrySchemaUrl { get { throw null;} set { } } public MeterOptions(string name) { throw null;} } public sealed class ObservableCounter : ObservableInstrument where T : struct diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index 90f92146a21ad6..8be83c2ccbd180 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -40,6 +40,7 @@ System.Diagnostics.DiagnosticSource + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs index f82e54e65d5b5e..8b3cdebadc1ead 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs @@ -18,7 +18,7 @@ public sealed class ActivitySource : IDisposable /// Construct an ActivitySource object with the input name /// /// The name of the ActivitySource object - public ActivitySource(string name) : this(name, version: "", tags: null) {} + public ActivitySource(string name) : this(name, version: "", tags: null, telemetrySchemaUrl: null) {} /// /// Construct an ActivitySource object with the input name @@ -26,7 +26,7 @@ public ActivitySource(string name) : this(name, version: "", tags: null) {} /// The name of the ActivitySource object /// The version of the component publishing the tracing info. [EditorBrowsable(EditorBrowsableState.Never)] - public ActivitySource(string name, string? version = "") : this(name, version, tags: null) {} + public ActivitySource(string name, string? version = "") : this(name, version, tags: null, telemetrySchemaUrl: null) {} /// /// Construct an ActivitySource object with the input name @@ -34,10 +34,19 @@ public ActivitySource(string name, string? version = "") : this(name, version, t /// The name of the ActivitySource object /// The version of the component publishing the tracing info. /// The optional ActivitySource tags. - public ActivitySource(string name, string? version = "", IEnumerable>? tags = default) + public ActivitySource(string name, string? version = "", IEnumerable>? tags = default) : this(name, version, tags, telemetrySchemaUrl: null) {} + + /// + /// Initialize a new instance of the ActivitySource object using the . + /// + /// The object to use for initializing the ActivitySource object. + public ActivitySource(ActivitySourceOptions options) : this((options ?? throw new ArgumentNullException(nameof(options))).Name, options.Version, options.Tags, options.TelemetrySchemaUrl) {} + + private ActivitySource(string name, string? version, IEnumerable>? tags, string? telemetrySchemaUrl) { Name = name ?? throw new ArgumentNullException(nameof(name)); Version = version; + TelemetrySchemaUrl = telemetrySchemaUrl; // Sorting the tags to make sure the tags are always in the same order. // Sorting can help in comparing the tags used for any scenario. @@ -84,6 +93,11 @@ public ActivitySource(string name, string? version = "", IEnumerable public IEnumerable>? Tags { get; } + /// + /// Returns the telemetry schema URL associated with the ActivitySource. + /// + public string? TelemetrySchemaUrl { get; } + /// /// Check if there is any listeners for this ActivitySource. /// This property can be helpful to tell if there is no listener, then no need to create Activity object diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySourceOptions.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySourceOptions.cs new file mode 100644 index 00000000000000..28b49259ecf346 --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySourceOptions.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +namespace System.Diagnostics +{ + /// + /// Options for creating a . + /// + public class ActivitySourceOptions + { + private string _name; + + /// + /// Constructs a new instance of . + /// + /// The name of the object + public ActivitySourceOptions(string name) + { + _name = name ?? throw new ArgumentNullException(nameof(name)); + } + + /// + /// Get or set the object name. Cannot be null. + /// + public string Name + { + get => _name; + set => _name = value ?? throw new ArgumentNullException(nameof(value)); + } + + /// + /// The optional version. Defaulted to empty string. + /// + public string? Version { get; set; } = string.Empty; + + /// + /// The optional list of key-value pair tags associated with the . + /// + public IEnumerable>? Tags { get; set; } + + /// + /// The optional schema URL specifies a location of a Schema File that + /// can be retrieved using HTTP or HTTPS protocol. + /// + public string? TelemetrySchemaUrl { get; set; } + } +} diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs index 7afc120baebe21..762d90f425ebfb 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs @@ -39,7 +39,7 @@ public Meter(MeterOptions options) Debug.Assert(options.Name is not null); - Initialize(options.Name, options.Version, options.Tags, options.Scope); + Initialize(options.Name, options.Version, options.Tags, options.Scope, options.TelemetrySchemaUrl); Debug.Assert(Name is not null); } @@ -71,11 +71,11 @@ public Meter(string name, string? version) : this(name, version, null, null) { } /// public Meter(string name, string? version, IEnumerable>? tags, object? scope = null) { - Initialize(name, version, tags, scope); + Initialize(name, version, tags, scope, telemetrySchemaUrl: null); Debug.Assert(Name is not null); } - private void Initialize(string name, string? version, IEnumerable>? tags, object? scope = null) + private void Initialize(string name, string? version, IEnumerable>? tags, object? scope = null, string? telemetrySchemaUrl = null) { Name = name ?? throw new ArgumentNullException(nameof(name)); Version = version; @@ -86,6 +86,7 @@ private void Initialize(string name, string? version, IEnumerable public object? Scope { get; private set; } + /// + /// The optional schema URL specifies a location of a Schema File that + /// can be retrieved using HTTP or HTTPS protocol. + /// + public string? TelemetrySchemaUrl { get; private set; } + /// /// Create a metrics Counter object. /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MeterOptions.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MeterOptions.cs index 9697c4edda35bc..6e3ce8f43c1c96 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MeterOptions.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MeterOptions.cs @@ -18,15 +18,7 @@ public class MeterOptions public string Name { get => _name; - set - { - if (value is null) - { - throw new ArgumentNullException(nameof(value)); - } - - _name = value; - } + set => _name = value ?? throw new ArgumentNullException(nameof(value)); } /// @@ -44,6 +36,12 @@ public string Name /// public object? Scope { get; set; } + /// + /// The optional schema URL specifies a location of a Schema File that + /// can be retrieved using HTTP or HTTPS protocol. + /// + public string? TelemetrySchemaUrl { get; set; } + /// /// Constructs a new instance of . /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs index 9640b68b8cf264..0768d8b456119e 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs @@ -153,7 +153,7 @@ public void HistogramValuePublished(string sessionId, string meterName, string? // Sent when we begin to monitor the value of a instrument, either because new session filter arguments changed subscriptions // or because an instrument matching the pre-existing filter has just been created. This event precedes all *MetricPublished events // for the same named instrument. - [Event(7, Keywords = Keywords.TimeSeriesValues, Version = 2)] + [Event(7, Keywords = Keywords.TimeSeriesValues, Version = 3)] #if !NET8_0_OR_GREATER [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] @@ -169,15 +169,16 @@ public void BeginInstrumentReporting( string instrumentTags, string meterTags, string meterScopeHash, - int instrumentId) + int instrumentId, + string? meterTelemetrySchemaUrl) { WriteEvent(7, sessionId, meterName, meterVersion ?? "", instrumentName, instrumentType, unit ?? "", description ?? "", - instrumentTags, meterTags, meterScopeHash, instrumentId); + instrumentTags, meterTags, meterScopeHash, instrumentId, meterTelemetrySchemaUrl); } // Sent when we stop monitoring the value of a instrument, either because new session filter arguments changed subscriptions // or because the Meter has been disposed. - [Event(8, Keywords = Keywords.TimeSeriesValues, Version = 2)] + [Event(8, Keywords = Keywords.TimeSeriesValues, Version = 3)] #if !NET8_0_OR_GREATER [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] @@ -193,10 +194,11 @@ public void EndInstrumentReporting( string instrumentTags, string meterTags, string meterScopeHash, - int instrumentId) + int instrumentId, + string? meterTelemetrySchemaUrl) { WriteEvent(8, sessionId, meterName, meterVersion ?? "", instrumentName, instrumentType, unit ?? "", description ?? "", - instrumentTags, meterTags, meterScopeHash, instrumentId); + instrumentTags, meterTags, meterScopeHash, instrumentId, meterTelemetrySchemaUrl); } [Event(9, Keywords = Keywords.TimeSeriesValues | Keywords.Messages | Keywords.InstrumentPublishing)] @@ -211,7 +213,7 @@ public void InitialInstrumentEnumerationComplete(string sessionId) WriteEvent(10, sessionId); } - [Event(11, Keywords = Keywords.InstrumentPublishing, Version = 2)] + [Event(11, Keywords = Keywords.InstrumentPublishing, Version = 3)] #if !NET8_0_OR_GREATER [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] @@ -227,10 +229,11 @@ public void InstrumentPublished( string instrumentTags, string meterTags, string meterScopeHash, - int instrumentId) + int instrumentId, + string? meterTelemetrySchemaUrl) { WriteEvent(11, sessionId, meterName, meterVersion ?? "", instrumentName, instrumentType, unit ?? "", description ?? "", - instrumentTags, meterTags, meterScopeHash, instrumentId); + instrumentTags, meterTags, meterScopeHash, instrumentId, meterTelemetrySchemaUrl); } [Event(12, Keywords = Keywords.TimeSeriesValues)] @@ -463,11 +466,11 @@ public void OnEventCommand(EventCommandEventArgs command) beginCollection: (startIntervalTime, endIntervalTime) => Parent.CollectionStart(sessionId, startIntervalTime, endIntervalTime), endCollection: (startIntervalTime, endIntervalTime) => Parent.CollectionStop(sessionId, startIntervalTime, endIntervalTime), beginInstrumentMeasurements: (i, state) => Parent.BeginInstrumentReporting(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description, - Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state.ID), + Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state.ID, i.Meter.TelemetrySchemaUrl), endInstrumentMeasurements: (i, state) => Parent.EndInstrumentReporting(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description, - Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state.ID), + Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state.ID, i.Meter.TelemetrySchemaUrl), instrumentPublished: (i, state) => Parent.InstrumentPublished(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description, - Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state is null ? 0 : state.ID), + Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state is null ? 0 : state.ID, i.Meter.TelemetrySchemaUrl), initialInstrumentEnumerationComplete: () => Parent.InitialInstrumentEnumerationComplete(sessionId), collectionError: e => Parent.Error(sessionId, e.ToString()), timeSeriesLimitReached: () => Parent.TimeSeriesLimitReached(sessionId), diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs index 5870822e5b03ad..5cba29522e1ea3 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs @@ -24,12 +24,29 @@ public void TestConstruction() Assert.Equal(String.Empty, as1.Version); Assert.False(as1.HasListeners()); Assert.Null(as1.Tags); + Assert.Null(as1.TelemetrySchemaUrl); + ActivitySourceOptions options = new ActivitySourceOptions("Source1"); + using ActivitySource as1_1 = new ActivitySource(options); + Assert.Equal("Source1", as1_1.Name); + Assert.Equal(String.Empty, as1_1.Version); + Assert.False(as1_1.HasListeners()); + Assert.Null(as1_1.Tags); + Assert.Null(as1_1.TelemetrySchemaUrl); using ActivitySource as2 = new ActivitySource("Source2", "1.1.1.2"); Assert.Equal("Source2", as2.Name); Assert.Equal("1.1.1.2", as2.Version); Assert.False(as2.HasListeners()); Assert.Null(as2.Tags); + Assert.Null(as2.TelemetrySchemaUrl); + options = new ActivitySourceOptions("Source2"); + options.Version = "1.1.1.2"; + using ActivitySource as2_2 = new ActivitySource(options); + Assert.Equal("Source2", as2_2.Name); + Assert.Equal("1.1.1.2", as2_2.Version); + Assert.False(as2_2.HasListeners()); + Assert.Null(as2_2.Tags); + Assert.Null(as2_2.TelemetrySchemaUrl); using ActivitySource as3 = new ActivitySource("Source3", "1.1.1.3", new TagList { { "key3", "value3" }, { "key2", "value2" }, { "key1", "value1" } }); Assert.Equal("Source3", as3.Name); @@ -37,6 +54,33 @@ public void TestConstruction() Assert.False(as3.HasListeners()); // Ensure the tags are sorted by key. Assert.Equal(new TagList { { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" } }, as3.Tags); + Assert.Null(as3.TelemetrySchemaUrl); + options = new ActivitySourceOptions("Source3"); + options.Version = "1.1.1.3"; + options.Tags = new TagList { { "key3", "value3" }, { "key2", "value2" }, { "key1", "value1" } }; + using ActivitySource as3_3 = new ActivitySource(options); + Assert.Equal("Source3", as3_3.Name); + Assert.Equal("1.1.1.3", as3_3.Version); + Assert.False(as3_3.HasListeners()); + Assert.Equal(new TagList { { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" } }, as3_3.Tags); + Assert.Null(as3_3.TelemetrySchemaUrl); + + using ActivitySource as4 = new ActivitySource("Source4", "1.1.1.4", new TagList { { "key4", "value4" }, { "key3", "value3" }, { "key2", "value2" }, { "key1", "value1" } }); + Assert.Equal("Source4", as4.Name); + Assert.Equal("1.1.1.4", as4.Version); + Assert.False(as4.HasListeners()); + Assert.Equal(new TagList { { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }, { "key4", "value4" } }, as4.Tags); + Assert.Null(as4.TelemetrySchemaUrl); + options = new ActivitySourceOptions("Source4"); + options.Version = "1.1.1.4"; + options.Tags = new TagList { { "key4", "value4" }, { "key3", "value3" }, { "key2", "value2" }, { "key1", "value1" } }; + options.TelemetrySchemaUrl = "https://example.com/schema"; + using ActivitySource as4_4 = new ActivitySource(options); + Assert.Equal("Source4", as4_4.Name); + Assert.Equal("1.1.1.4", as4_4.Version); + Assert.False(as4_4.HasListeners()); + Assert.Equal(new TagList { { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }, { "key4", "value4" } }, as4_4.Tags); + Assert.Equal("https://example.com/schema", as4_4.TelemetrySchemaUrl); }).Dispose(); } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs index 15bdf85ea25137..dbf25f79032aea 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs @@ -82,7 +82,13 @@ public void MultipleListeners_DifferentCounters() using Meter meter = new Meter("TestMeter1"); Counter c = meter.CreateCounter("counter1", null, null, new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); - using Meter meter2 = new Meter("TestMeter2", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object()); + using Meter meter2 = new Meter(new MeterOptions("TestMeter2") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c2 = meter2.CreateCounter("counter2"); EventWrittenEventArgs[] events, events2; @@ -124,7 +130,13 @@ public void MultipleListeners_ReuseCounter() using Meter meter = new Meter("TestMeter1"); Counter c = meter.CreateCounter("counter1", null, null, new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); - using Meter meter2 = new Meter("TestMeter2", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object()); + using Meter meter2 = new Meter(new MeterOptions("TestMeter2") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c2 = meter2.CreateCounter("counter2", null, null, new TagList() { { "cCk1", "cCv1" }, { "cCk2", "cCv2" } }); EventWrittenEventArgs[] events, events2; @@ -169,7 +181,13 @@ public void MultipleListeners_CollectAfterDisableListener() using Meter meter = new Meter("TestMeter1", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object()); Counter c = meter.CreateCounter("counter1", null, null, new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); - using Meter meter2 = new Meter("TestMeter2", null, new TagList() { { "MMk1", "MMv1" } }, new object()); + using Meter meter2 = new Meter(new MeterOptions("TestMeter2") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }}, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c2 = meter2.CreateCounter("counter2", null, null, new TagList() { { "cCk1", "cCv1" }, { "cCk2", "cCv2" } }); EventWrittenEventArgs[] events, events2; @@ -217,7 +235,13 @@ public void MultipleListeners_ThreeCounters() using Meter meter = new Meter("TestMeter1"); Counter c = meter.CreateCounter("counter1"); - using Meter meter2 = new Meter("TestMeter2", null, new TagList() { { "Mk1", "Mv1" } }, new object()); + using Meter meter2 = new Meter(new MeterOptions("TestMeter2") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c2 = meter2.CreateCounter("counter2"); using Meter meter3 = new Meter("TestMeter3", null, new TagList() { { "MMk1", null }, { "MMk2", null } }, new object()); @@ -271,7 +295,13 @@ public void SingleListener_Wildcard() using Meter meter = new Meter("Test.TestMeter1"); Counter c = meter.CreateCounter("counter1"); - using Meter meter2 = new Meter("Test.TestMeter2", null, new TagList() { { "Mk1", "Mv1" } }, new object()); + using Meter meter2 = new Meter(new MeterOptions("Test.TestMeter2") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c2 = meter2.CreateCounter("counter2"); using Meter meter3 = new Meter("Test.TestMeter3", null, new TagList() { { "MMk1", null }, { "MMk2", null } }, new object()); @@ -308,7 +338,13 @@ public void SingleListener_Prefix() using Meter meter = new Meter("Company1.TestMeter1"); Counter c = meter.CreateCounter("counter1"); - using Meter meter2 = new Meter("Company1.TestMeter2", null, new TagList() { { "Mk1", "Mv1" } }, new object()); + using Meter meter2 = new Meter(new MeterOptions("Company1.TestMeter2") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c2 = meter2.CreateCounter("counter2"); using Meter meter3 = new Meter("Company2.TestMeter3", null, new TagList() { { "MMk1", null }, { "MMk2", null } }, new object()); @@ -339,7 +375,13 @@ public void MultipleListeners_OverlappingListeners() using Meter meter = new Meter("TestMeter1", null, new TagList() { { "Mk1", "Mv1" } }, new object()); Counter c = meter.CreateCounter("counter1", null, null, new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); - using Meter meter2 = new Meter("TestMeter2"); + using Meter meter2 = new Meter(new MeterOptions("TestMeter2") + { + Version = null, + Tags = null, + Scope = null, + TelemetrySchemaUrl = "https://example.com" + }); Counter c2 = meter2.CreateCounter("counter2", null, null, new TagList() { { "cCk1", "cCv1" }, { "cCk2", "cCv2" } }); EventWrittenEventArgs[] events, events2; @@ -375,7 +417,13 @@ public void MultipleListeners_OverlappingListeners() [OuterLoop("Slow and has lots of console spew")] public void MultipleListeners_UnsharedSessionRejectsUnsharedListener() { - using Meter meter = new Meter("TestMeter7", null, new TagList() { { "Mk1", "Mv1" } }, new object()); + using Meter meter = new Meter(new MeterOptions("TestMeter7") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meter.CreateCounter("counter1", "hat", "Fooz!!", new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); int counterState = 3; ObservableCounter oc = meter.CreateObservableCounter("observableCounter1", () => { counterState += 7; return counterState; }, "MB", "Size of universe", new TagList() { { "ock1", "ocv1" }, { "ock2", "ocv2" } }); @@ -423,7 +471,13 @@ public void MultipleListeners_UnsharedSessionRejectsUnsharedListener() [OuterLoop("Slow and has lots of console spew")] public void MultipleListeners_UnsharedSessionRejectsSharedListener() { - using Meter meter = new Meter("TestMeter7", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object()); + using Meter meter = new Meter(new MeterOptions("TestMeter7") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meter.CreateCounter("counter1", "hat", "Fooz!!", new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); int counterState = 3; ObservableCounter oc = meter.CreateObservableCounter("observableCounter1", () => { counterState += 7; return counterState; }, "MB", "Size of universe"); @@ -474,7 +528,13 @@ public void MultipleListeners_UnsharedSessionRejectsSharedListener() [OuterLoop("Slow and has lots of console spew")] public void MultipleListeners_SharedSessionRejectsUnsharedListener() { - using Meter meter = new Meter("TestMeter7", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object()); + using Meter meter = new Meter(new MeterOptions("TestMeter7") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meter.CreateCounter("counter1", "hat", "Fooz!!"); int counterState = 3; ObservableCounter oc = meter.CreateObservableCounter("observableCounter1", () => { counterState += 7; return counterState; }, "MB", "Size of universe"); @@ -524,7 +584,13 @@ public void MultipleListeners_SharedSessionRejectsUnsharedListener() [OuterLoop("Slow and has lots of console spew")] public void MultipleListeners_SharedSessionRejectsListenerWithDifferentArgs() { - using Meter meter = new Meter("TestMeter7", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }); + using Meter meter = new Meter(new MeterOptions("TestMeter7") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = null, + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meter.CreateCounter("counter1", "hat", "Fooz!!", new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); EventWrittenEventArgs[] events, events2; @@ -558,7 +624,13 @@ public void MultipleListeners_SharedSessionRejectsListenerWithDifferentArgs() [ActiveIssue("This test appears to interfere with the others due to the session not being shut down.")] public void MultipleListeners_SharedSessionWithoutClientIdRejectsSharedListenerWithDifferentArgsAfterListenerDisposed() { - using Meter meter = new Meter("TestMeter7"); + using Meter meter = new Meter(new MeterOptions("TestMeter7") + { + Version = null, + Tags = null, + Scope = null, + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meter.CreateCounter("counter1", "hat", "Fooz!!"); EventWrittenEventArgs[] events, events2; @@ -590,7 +662,13 @@ public void MultipleListeners_SharedSessionWithoutClientIdRejectsSharedListenerW [OuterLoop("Slow and has lots of console spew")] public void MultipleListeners_SharedSessionRejectsListenerWithDifferentInterval() { - using Meter meter = new Meter("TestMeter7", null, new TagList() { { "Mk1", null }, { "Mk2", null } }, new object()); + using Meter meter = new Meter(new MeterOptions("TestMeter7") + { + Version = null, + Tags = new TagList() { { "Mk1", null }, { "Mk2", null } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meter.CreateCounter("counter1", "hat", "Fooz!!"); int counterState = 3; ObservableCounter oc = meter.CreateObservableCounter("observableCounter1", () => { counterState += 7; return counterState; }, "MB", "Size of universe", new TagList() { { "Ck1", null }, { "Ck2", "" } }); @@ -644,7 +722,13 @@ public void MultipleListeners_SharedSessionRejectsListenerWithDifferentInterval( public void MultipleListeners_DisposeMeterBeforeSecondListener() { using Meter meterA = new Meter("TestMeter8", null, null, new object()); - using Meter meterB = new Meter("TestMeter9", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }); + using Meter meterB = new Meter(new MeterOptions("TestMeter9") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = null, + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meterA.CreateCounter("counter1", "hat", "Fooz!!"); int counterState = 3; ObservableCounter oc = meterA.CreateObservableCounter("observableCounter1", () => { counterState += 7; return counterState; }, "MB", "Size of universe", new TagList() { { "Ck1", "Cv1" }, { "Ck2", "Cv2" } }); @@ -704,7 +788,13 @@ public void MultipleListeners_DisposeMeterBeforeSecondListener() public void MultipleListeners_DisposeMetersDuringAndAfterSecondListener() { using Meter meterA = new Meter("TestMeter8", null, new TagList() { { "1Mk1", "1Mv1" }, { "1Mk2", "Mv2" } }); - using Meter meterB = new Meter("TestMeter9", null, new TagList() { { "2Mk1", "2Mv1" } }, new object()); + using Meter meterB = new Meter(new MeterOptions("TestMeter9") + { + Version = null, + Tags = new TagList() { { "2Mk1", "2Mv1" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meterA.CreateCounter("counter1", "hat", "Fooz!!", new TagList() { { "Ck1", "Cv1" } }); Gauge g = meterA.CreateGauge("gauge1", "C", "Temperature", new TagList() { { "Ck1", "Cv1" } }); int counterState = 3; @@ -768,7 +858,13 @@ public void MultipleListeners_DisposeMetersDuringAndAfterSecondListener() [OuterLoop("Slow and has lots of console spew")] public void MultipleListeners_PublishingInstruments() { - using Meter meterA = new Meter("TestMeter10", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2"}, { "Mk3", null }}); + using Meter meterA = new Meter(new MeterOptions("TestMeter10") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2"}, { "Mk3", null }}, + Scope = null, + TelemetrySchemaUrl = "https://example.com" + }); using Meter meterB = new Meter("TestMeter11", null, null, new object()); Counter c = meterA.CreateCounter("counter1", "hat", "Fooz!!", new TagList() { { "Ck1", "Cv1" } }); Gauge g = meterA.CreateGauge("gauge1", "C", "Temperature", new TagList() { { "Ck1", "Cv1" } }); @@ -809,7 +905,13 @@ public void EventSourcePublishesTimeSeriesWithEmptyMetadata() { CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("fi-FI"); - using Meter meter = new Meter("TestMeter1", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, new object()); + using Meter meter = new Meter(new MeterOptions("TestMeter1") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = new object(), + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meter.CreateCounter("counter1"); Gauge g = meter.CreateGauge("gauge1"); int counterState = 3; @@ -1119,7 +1221,13 @@ public void EventSourceFiltersInstruments() { object scope = new object(); using Meter meterA = new Meter("TestMeterA", null, new TagList() { { "1Mk1", null } }, scope); - using Meter meterB = new Meter("TestMeterB", null, new TagList() { { "2Mk1", "" }}, scope); + using Meter meterB = new Meter(new MeterOptions("TestMeterB") + { + Version = null, + Tags = new TagList() { { "2Mk1", "" }}, + Scope = scope, + TelemetrySchemaUrl = "https://example.com" + }); using Meter meterC = new Meter("TestMeterC", null, new TagList() { { "3Mk1", "Mv1" }, { "3Mk2", "Mv2" } }, scope); Counter c1a = meterA.CreateCounter("counter1"); Counter c2a = meterA.CreateCounter("counter2"); @@ -1273,7 +1381,13 @@ public void EventSourcePublishesEndEventsOnMeterDispose() { object scope = new object(); using Meter meterA = new Meter("TestMeter8", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", null } }, scope); - using Meter meterB = new Meter("TestMeter9", null, new TagList() { { "Mk1", null }, { "Mk2", "Mv2" } }, scope); + using Meter meterB = new Meter(new MeterOptions("TestMeter9") + { + Version = null, + Tags = new TagList() { { "Mk1", null }, { "Mk2", "Mv2" } }, + Scope = scope, + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meterA.CreateCounter("counter1", "hat", "Fooz!!"); Gauge g = meterA.CreateGauge("gauge1", "C", "Temperature"); int counterState = 3; @@ -1331,7 +1445,13 @@ public void EventSourcePublishesInstruments() object scope = new object(); using Meter meterA = new Meter("TestMeter10", null, null, scope); - using Meter meterB = new Meter("TestMeter11", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", null } }, scope); + using Meter meterB = new Meter(new MeterOptions("TestMeter11") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", null } }, + Scope = scope, + TelemetrySchemaUrl = "https://example.com" + }); Counter c = meterA.CreateCounter("counter1", "hat", "Fooz!!"); Gauge g = meterA.CreateGauge("gauge1", "C", "Temperature"); int counterState = 3; @@ -1602,7 +1722,13 @@ public void EventSourceWorksWithSequentialListeners() [OuterLoop("Slow and has lots of console spew")] public void EventSourceEnforcesHistogramLimitAndNotMaxTimeSeries() { - using Meter meter = new Meter("TestMeter17", null, new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }); + using Meter meter = new Meter(new MeterOptions("TestMeter17") + { + Version = null, + Tags = new TagList() { { "Mk1", "Mv1" }, { "Mk2", "Mv2" } }, + Scope = null, + TelemetrySchemaUrl = "https://example.com" + }); Histogram h = meter.CreateHistogram("histogram1", null, null, new TagList() { { "hk1", "hv1" }, { "hk2", "hv2" } }); EventWrittenEventArgs[] events; @@ -1716,6 +1842,7 @@ private static void AssertBeginInstrumentReportingEventsPresent(EventWrittenEven MeterTags = e.Payload[8].ToString(), ScopeHash = e.Payload[9].ToString(), InstrumentId = (int)(e.Payload[10]), + TelemetrySchemaUrl = e.Payload[11].ToString(), }).ToArray(); foreach(Instrument i in expectedInstruments) @@ -1729,6 +1856,7 @@ private static void AssertBeginInstrumentReportingEventsPresent(EventWrittenEven Assert.Equal(Helpers.FormatTags(i.Tags), e.InstrumentTags); Assert.Equal(Helpers.FormatTags(i.Meter.Tags), e.MeterTags); Assert.Equal(Helpers.FormatObjectHash(i.Meter.Scope), e.ScopeHash); + Assert.Equal(i.Meter.TelemetrySchemaUrl ?? "", e.TelemetrySchemaUrl); Assert.True(e.InstrumentId > 0); } @@ -1750,6 +1878,7 @@ private static void AssertEndInstrumentReportingEventsPresent(EventWrittenEventA MeterTags = e.Payload[8].ToString(), ScopeHash = e.Payload[9].ToString(), InstrumentId = (int)(e.Payload[10]), + TelemetrySchemaUrl = e.Payload[11].ToString(), }).ToArray(); foreach (Instrument i in expectedInstruments) @@ -1763,6 +1892,7 @@ private static void AssertEndInstrumentReportingEventsPresent(EventWrittenEventA Assert.Equal(Helpers.FormatTags(i.Tags), e.InstrumentTags); Assert.Equal(Helpers.FormatTags(i.Meter.Tags), e.MeterTags); Assert.Equal(Helpers.FormatObjectHash(i.Meter.Scope), e.ScopeHash); + Assert.Equal(i.Meter.TelemetrySchemaUrl ?? "", e.TelemetrySchemaUrl); Assert.True(e.InstrumentId > 0); } @@ -1804,6 +1934,7 @@ private static void AssertInstrumentPublishingEventsPresent(EventWrittenEventArg MeterTags = e.Payload[8].ToString(), ScopeHash = e.Payload[9].ToString(), InstrumentId = (int)(e.Payload[10]), + TelemetrySchemaUrl = e.Payload[11].ToString(), }).ToArray(); foreach (Instrument i in expectedInstruments) @@ -1817,6 +1948,7 @@ private static void AssertInstrumentPublishingEventsPresent(EventWrittenEventArg Assert.Equal(Helpers.FormatTags(i.Tags), e.InstrumentTags); Assert.Equal(Helpers.FormatTags(i.Meter.Tags), e.MeterTags); Assert.Equal(Helpers.FormatObjectHash(i.Meter.Scope), e.ScopeHash); + Assert.Equal(i.Meter.TelemetrySchemaUrl ?? "", e.TelemetrySchemaUrl); Assert.True(e.InstrumentId >= 0); // It is possible getting Id 0 with InstrumentPublished event when measurements are not enabling (e.g. CounterRateValuePublished event) } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs index 161c9431df5dd1..05bd3aed1bd0e1 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs @@ -1450,18 +1450,21 @@ public void TestMeterCreationWithOptions() Assert.Null(meter1.Version); Assert.Null(meter1.Tags); Assert.Null(meter1.Scope); + Assert.Null(meter1.TelemetrySchemaUrl); using Meter meter2 = new Meter("TestMeterCreationWithOptions2", "2.0", new TagList() { { "Key1", "Value1" } }); Assert.Equal("TestMeterCreationWithOptions2", meter2.Name); Assert.Equal("2.0", meter2.Version); Assert.Equal(new[] { new KeyValuePair("Key1", "Value1") }, meter2.Tags); Assert.Null(meter2.Scope); + Assert.Null(meter2.TelemetrySchemaUrl); using Meter meter3 = new Meter("TestMeterCreationWithOptions3", "3.0", new TagList() { { "Key3", "Value3" } }, "Scope"); Assert.Equal("TestMeterCreationWithOptions3", meter3.Name); Assert.Equal("3.0", meter3.Version); Assert.Equal(new[] { new KeyValuePair("Key3", "Value3") }, meter3.Tags); Assert.Equal("Scope", meter3.Scope); + Assert.Null(meter3.TelemetrySchemaUrl); Assert.Throws(() => new MeterOptions(null!)); Assert.Throws(() => new MeterOptions("Something").Name = null!); @@ -1471,30 +1474,35 @@ public void TestMeterCreationWithOptions() Assert.Null(meter4.Version); Assert.Null(meter4.Tags); Assert.Null(meter4.Scope); + Assert.Null(meter4.TelemetrySchemaUrl); using Meter meter5 = new Meter(new MeterOptions("TestMeterCreationWithOptions5") { Version = "5.0" }); Assert.Equal("TestMeterCreationWithOptions5", meter5.Name); Assert.Equal("5.0", meter5.Version); Assert.Null(meter5.Tags); Assert.Null(meter5.Scope); + Assert.Null(meter5.TelemetrySchemaUrl); using Meter meter6 = new Meter(new MeterOptions("TestMeterCreationWithOptions6") { Tags = new TagList() { { "Key6", "Value6"} } }); Assert.Equal("TestMeterCreationWithOptions6", meter6.Name); Assert.Null(meter6.Version); Assert.Equal(new[] { new KeyValuePair("Key6", "Value6") }, meter6.Tags); Assert.Null(meter5.Scope); + Assert.Null(meter6.TelemetrySchemaUrl); using Meter meter7 = new Meter(new MeterOptions("TestMeterCreationWithOptions7") { Scope = "Scope7" }); Assert.Equal("TestMeterCreationWithOptions7", meter7.Name); Assert.Null(meter7.Version); Assert.Null(meter7.Tags); Assert.Equal("Scope7", meter7.Scope); + Assert.Null(meter7.TelemetrySchemaUrl); using Meter meter8 = new Meter(new MeterOptions("TestMeterCreationWithOptions8") { Version = "8.0", Tags = new TagList() { { "Key8", "Value8" } }, Scope = "Scope8" }); Assert.Equal("TestMeterCreationWithOptions8", meter8.Name); Assert.Equal("8.0", meter8.Version); Assert.Equal(new[] { new KeyValuePair("Key8", "Value8") }, meter8.Tags); Assert.Equal("Scope8", meter8.Scope); + Assert.Null(meter8.TelemetrySchemaUrl); // Test tags sorting order TagList l = new TagList() { { "f", "a" }, { "d", "b" }, { "w", "b" }, { "h", new object() }, { "N", null }, { "a", "b" }, { "a", null } }; @@ -1505,6 +1513,18 @@ public void TestMeterCreationWithOptions() { Assert.True(string.Compare(insArray[i].Key, insArray[i + 1].Key, StringComparison.Ordinal) <= 0); } + + using Meter meter10 = new Meter(new MeterOptions("TestMeterCreationWithOptions10") { Version = "10.0", Tags = l, Scope = "Scope10", TelemetrySchemaUrl = "https://example.com" }); + insArray = meter10.Tags.ToArray(); + Assert.Equal(l.Count, insArray.Length); + for (int i = 0; i < insArray.Length - 1; i++) + { + Assert.True(string.Compare(insArray[i].Key, insArray[i + 1].Key, StringComparison.Ordinal) <= 0); + } + Assert.Equal("https://example.com", meter10.TelemetrySchemaUrl); + Assert.Equal("10.0", meter10.Version); + Assert.Equal("Scope10", meter10.Scope); + Assert.Equal("TestMeterCreationWithOptions10", meter10.Name); }).Dispose(); }