From a7ee6721e8fc56daa8dd3ac2c863683fbda0c436 Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 11:22:18 +0100 Subject: [PATCH 1/8] updates --- .../MetricFactoryEmitter.cs | 10 +- .../Model/MetricMethod.cs | 1 + .../Microsoft.Gen.Metrics/Parser.cs | 35 +++-- .../StrongTypeAttributeParameters.cs | 1 + .../Metrics/CounterAttribute.cs | 5 + .../Metrics/CounterAttributeT.cs | 5 + .../Metrics/GaugeAttribute.cs | 5 + .../Metrics/HistogramAttribute.cs | 5 + .../Metrics/HistogramAttributeT.cs | 5 + .../Metrics/TagNameAttribute.cs | 5 + .../Generated/MetricTests.Ext.Unit.cs | 120 ++++++++++++++++++ .../TestClasses/MetricsWithUnit.cs | 43 +++++++ .../Unit/ParserTests.StrongTypes.cs | 19 +++ .../Microsoft.Gen.Metrics/Unit/ParserTests.cs | 13 ++ 14 files changed, 261 insertions(+), 11 deletions(-) create mode 100644 test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs create mode 100644 test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs diff --git a/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs b/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs index 531095d0c85..a947f9aac05 100644 --- a/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs +++ b/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs @@ -146,7 +146,15 @@ private void GenMetricFactoryMethods(MetricMethod metricMethod, string nspace) OutOpenBrace(); OutLn($"return {GetMetricDictionaryName(metricMethod)}.GetOrAdd({meterParam.Name}, static _meter =>"); OutLn(" {"); - OutLn($" var instrument = _meter.{createMethodName}(@\"{metricMethod.MetricName}\");"); + if (string.IsNullOrEmpty(metricMethod.MetricUnit)) + { + OutLn($" var instrument = _meter.{createMethodName}(@\"{metricMethod.MetricName}\");"); + } + else + { + OutLn($" var instrument = _meter.{createMethodName}(@\"{metricMethod.MetricName}\", \"{metricMethod.MetricUnit}\");"); + } + OutLn($" return new {nsprefix}{metricMethod.MetricTypeName}(instrument);"); OutLn(" });"); OutCloseBrace(); diff --git a/src/Generators/Microsoft.Gen.Metrics/Model/MetricMethod.cs b/src/Generators/Microsoft.Gen.Metrics/Model/MetricMethod.cs index 8a2db1ed8ff..dc5f45b1bad 100644 --- a/src/Generators/Microsoft.Gen.Metrics/Model/MetricMethod.cs +++ b/src/Generators/Microsoft.Gen.Metrics/Model/MetricMethod.cs @@ -12,6 +12,7 @@ internal sealed class MetricMethod public Dictionary TagDescriptionDictionary = []; public string? Name; public string? MetricName; + public string? MetricUnit; public string? XmlDefinition; public bool IsExtensionMethod; public string Modifiers = string.Empty; diff --git a/src/Generators/Microsoft.Gen.Metrics/Parser.cs b/src/Generators/Microsoft.Gen.Metrics/Parser.cs index 680bf579f2c..e78b1cfdf32 100644 --- a/src/Generators/Microsoft.Gen.Metrics/Parser.cs +++ b/src/Generators/Microsoft.Gen.Metrics/Parser.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -273,13 +274,14 @@ private static bool TryGetTagNameFromAttribute(ISymbol symbol, SymbolHolder symb return false; } - private (string metricName, HashSet tagNames, Dictionary dimensionDescriptions) ExtractAttributeParameters( + private (string metricName, string metricUnit, HashSet tagNames, Dictionary dimensionDescriptions) ExtractAttributeParameters( AttributeData attribute, SemanticModel semanticModel) { var tagHashSet = new HashSet(); var tagDescriptionMap = new Dictionary(); string metricNameFromAttribute = string.Empty; + string metricUnitFromAttribute = string.Empty; if (!attribute.NamedArguments.IsDefaultOrEmpty) { foreach (var arg in attribute.NamedArguments) @@ -288,7 +290,11 @@ private static bool TryGetTagNameFromAttribute(ISymbol symbol, SymbolHolder symb arg.Key is "MetricName" or "Name") { metricNameFromAttribute = (arg.Value.Value ?? string.Empty).ToString().Replace("\\\\", "\\"); - break; + } + else if (arg.Value.Kind == TypedConstantKind.Primitive && + arg.Key is "Unit") + { + metricUnitFromAttribute = (arg.Value.Value ?? string.Empty).ToString(); } } } @@ -330,7 +336,7 @@ private static bool TryGetTagNameFromAttribute(ISymbol symbol, SymbolHolder symb } } - return (metricNameFromAttribute, tagHashSet, tagDescriptionMap); + return (metricNameFromAttribute, metricUnitFromAttribute, tagHashSet, tagDescriptionMap); } private string GetSymbolXmlCommentSummary(ISymbol symbol) @@ -422,20 +428,20 @@ private void GetTagDescription( if (!methodAttribute.ConstructorArguments.IsDefaultOrEmpty && methodAttribute.ConstructorArguments[0].Kind == TypedConstantKind.Type) { - KeyValuePair namedArg = default; + ImmutableArray> namedArgs = ImmutableArray>.Empty; var ctorArg = methodAttribute.ConstructorArguments[0]; if (!methodAttribute.NamedArguments.IsDefaultOrEmpty) { - namedArg = methodAttribute.NamedArguments[0]; + namedArgs = methodAttribute.NamedArguments; } - strongTypeAttrParams = ExtractStrongTypeAttributeParameters(ctorArg, namedArg, symbols); + strongTypeAttrParams = ExtractStrongTypeAttributeParameters(ctorArg, namedArgs, symbols); } else { var parameters = ExtractAttributeParameters(methodAttribute, semanticModel); - (strongTypeAttrParams.MetricNameFromAttribute, strongTypeAttrParams.TagHashSet, strongTypeAttrParams.TagDescriptionDictionary) = parameters; + (strongTypeAttrParams.MetricNameFromAttribute, strongTypeAttrParams.MetricUnitFromAttribute, strongTypeAttrParams.TagHashSet, strongTypeAttrParams.TagDescriptionDictionary) = parameters; } string metricNameFromMethod = methodSymbol.ReturnType.Name; @@ -444,6 +450,7 @@ private void GetTagDescription( { Name = methodSymbol.Name, MetricName = string.IsNullOrWhiteSpace(strongTypeAttrParams.MetricNameFromAttribute) ? metricNameFromMethod : strongTypeAttrParams.MetricNameFromAttribute, + MetricUnit = strongTypeAttrParams.MetricUnitFromAttribute, InstrumentKind = instrumentKind, GenericType = genericType.ToDisplayString(_genericTypeSymbolFormat), TagKeys = strongTypeAttrParams.TagHashSet, @@ -605,14 +612,22 @@ private void Diag(DiagnosticDescriptor desc, Location? location, params object?[ private StrongTypeAttributeParameters ExtractStrongTypeAttributeParameters( TypedConstant constructorArg, - KeyValuePair namedArgument, + ImmutableArray> namedArguments, SymbolHolder symbols) { var strongTypeAttributeParameters = new StrongTypeAttributeParameters(); - if (namedArgument is { Key: "Name", Value.Value: { } }) + // i want to check namedArguments array for key == name and for key == unit + foreach (var namedArgument in namedArguments) { - strongTypeAttributeParameters.MetricNameFromAttribute = namedArgument.Value.Value.ToString(); + if (namedArgument.Key == "Name" && namedArgument.Value.Value is { } nameValue) + { + strongTypeAttributeParameters.MetricNameFromAttribute = nameValue.ToString(); + } + else if (namedArgument.Key == "Unit" && namedArgument.Value.Value is { } unitValue) + { + strongTypeAttributeParameters.MetricUnitFromAttribute = unitValue.ToString(); + } } if (constructorArg.IsNull || diff --git a/src/Generators/Microsoft.Gen.Metrics/StrongTypeAttributeParameters.cs b/src/Generators/Microsoft.Gen.Metrics/StrongTypeAttributeParameters.cs index 139973aa661..96abf55fe40 100644 --- a/src/Generators/Microsoft.Gen.Metrics/StrongTypeAttributeParameters.cs +++ b/src/Generators/Microsoft.Gen.Metrics/StrongTypeAttributeParameters.cs @@ -9,6 +9,7 @@ namespace Microsoft.Gen.Metrics; internal sealed class StrongTypeAttributeParameters { public string MetricNameFromAttribute = string.Empty; + public string MetricUnitFromAttribute = string.Empty; public HashSet TagHashSet = []; public Dictionary TagDescriptionDictionary = []; public List StrongTypeConfigs = []; diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs index 00d333c0c12..6ef199e1add 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs @@ -76,4 +76,9 @@ public CounterAttribute(Type type) /// Gets the type that supplies metric tags values. /// public Type? Type { get; } + + /// + /// Gets or sets the unit of measurement for the metric. + /// + public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs index cc6548f2bf0..c447d93ce64 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs @@ -82,4 +82,9 @@ public CounterAttribute(Type type) /// Gets the type that supplies metric tag values. /// public Type? Type { get; } + + /// + /// Gets or sets the unit of measurement for the metric. + /// + public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs index 5886c221480..b96c00ff566 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs @@ -75,4 +75,9 @@ public GaugeAttribute(Type type) /// Gets the type that supplies metric tag values. /// public Type? Type { get; } + + /// + /// Gets or sets the unit of measurement for the metric. + /// + public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs index 77780e4803c..92422e11cc2 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs @@ -75,4 +75,9 @@ public HistogramAttribute(Type type) /// Gets the type that supplies metric tag values. /// public Type? Type { get; } + + /// + /// Gets or sets the unit of measurement for the metric. + /// + public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs index b6207b4477c..cdfcc3dd64b 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs @@ -82,4 +82,9 @@ public HistogramAttribute(Type type) /// Gets the type that supplies metric tag values. /// public Type? Type { get; } + + /// + /// Gets or sets the unit of measurement for the metric. + /// + public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs index 77b9811c395..a46af7623f2 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs @@ -41,4 +41,9 @@ public TagNameAttribute(string name) /// Gets the name of the tag. /// public string Name { get; } + + /// + /// Gets or sets the unit of measurement for the metric. + /// + public string? Unit { get; set; } } diff --git a/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs new file mode 100644 index 00000000000..bd9b231525b --- /dev/null +++ b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs @@ -0,0 +1,120 @@ +// 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; +using System.Linq; +using Microsoft.Extensions.Diagnostics.Metrics.Testing; +using TestClasses; +using Xunit; +namespace Microsoft.Gen.Metrics.Test; + +public partial class MetricTests +{ + [Fact] + public void ValidateCounterWithUnit() + { + // Verify that a counter created with a unit works correctly + using var collector = new MetricCollector(_meter, "CounterWithUnit"); + + // You'll need to add this to TestClasses/MetricsWithUnit.cs + CounterWithUnit counter = MetricsWithUnit.CreateCounterWithUnit(_meter); + counter.Add(100L); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(100L, measurement.Value); + Assert.Empty(measurement.Tags); + Assert.NotNull(collector.Instrument); + Assert.Equal("seconds", collector.Instrument.Unit); + } + + [Fact] + public void ValidateHistogramWithUnit() + { + // Verify that a histogram created with a unit works correctly + using var collector = new MetricCollector(_meter, "HistogramWithUnit"); + + // You'll need to add this to TestClasses/HistogramTestExtensions.cs + HistogramWithUnit histogram = MetricsWithUnit.CreateHistogramWithUnit(_meter); + histogram.Record(50L); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(50L, measurement.Value); + Assert.Empty(measurement.Tags); + + Assert.NotNull(collector.Instrument); + Assert.Equal("milliseconds", collector.Instrument.Unit); + } + + [Fact] + public void ValidateCounterWithUnitAndDimensions() + { + const long Value = 12345L; + + using var collector = new MetricCollector(_meter, "CounterWithUnitAndDims"); + + CounterWithUnitAndDims counter = MetricsWithUnit.CreateCounterWithUnitAndDims(_meter); + counter.Add(Value, "dim1Value", "dim2Value"); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(Value, measurement.Value); + Assert.Equal(new (string, object?)[] { ("s1", "dim1Value"), ("s2", "dim2Value") }, + measurement.Tags.Select(x => (x.Key, x.Value))); + + // Verify the instrument has the correct unit + Assert.NotNull(collector.Instrument); + Assert.Equal("bytes", collector.Instrument.Unit); + } + + [Fact] + public void ValidateHistogramWithUnitAndDimensions() + { + const int Value = 9876; + + using var collector = new MetricCollector(_meter, "HistogramWithUnitAndDims"); + + HistogramWithUnitAndDims histogram = MetricsWithUnit.CreateHistogramWithUnitAndDims(_meter); + histogram.Record(Value, "val1"); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(Value, measurement.Value); + var tag = Assert.Single(measurement.Tags); + Assert.Equal(new KeyValuePair("s1", "val1"), tag); + + // Verify the instrument has the correct unit + Assert.NotNull(collector.Instrument); + Assert.Equal("requests", collector.Instrument.Unit); + } + + [Fact] + public void ValidateGenericCounterWithUnit() + { + using var collector = new MetricCollector(_meter, "GenericDoubleCounterWithUnit"); + + GenericDoubleCounterWithUnit counter = MetricsWithUnit.CreateGenericDoubleCounterWithUnit(_meter); + counter.Add(3.14); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(3.14, measurement.Value); + Assert.Empty(measurement.Tags); + + // Verify the instrument has the correct unit + Assert.NotNull(collector.Instrument); + Assert.Equal("meters", collector.Instrument.Unit); + } + + [Fact] + public void ValidateCounterWithEmptyUnit() + { + // Test that counters with empty/null units work + using var collector = new MetricCollector(_meter, nameof(Counter0D)); + Counter0D counter0D = CounterTestExtensions.CreateCounter0D(_meter); + counter0D.Add(10L); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(10L, measurement.Value); + + // Verify the instrument has no unit (or default unit) + Assert.NotNull(collector.Instrument); + Assert.Null(collector.Instrument.Unit); + } +} diff --git a/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs b/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs new file mode 100644 index 00000000000..9b26a686ba3 --- /dev/null +++ b/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Metrics; +using Microsoft.Extensions.Diagnostics.Metrics; + +namespace TestClasses +{ +#pragma warning disable SA1402 // File may only contain a single type + [SuppressMessage("Usage", "CA1801:Review unused parameters", + Justification = "For testing emitter for classes without namespace")] + public static partial class MetricsWithUnit + { + [Counter(Unit = "seconds")] + public static partial CounterWithUnit CreateCounterWithUnit(Meter meter); + + [Counter("s1", "s2", Unit = "bytes", Name = "CounterWithUnitAndDims")] + public static partial CounterWithUnitAndDims CreateCounterWithUnitAndDims(Meter meter); + + [Counter(typeof(Dimensions), Unit = "bytes")] + public static partial CounterStrongTypeWithUnit CreateCounterStrongTypeWithUnit(Meter meter); + + [Counter(Unit = "meters", Name = "GenericDoubleCounterWithUnit")] + public static partial GenericDoubleCounterWithUnit CreateGenericDoubleCounterWithUnit(Meter meter); + + [Histogram(Unit = "milliseconds", Name = "HistogramWithUnit")] + public static partial HistogramWithUnit CreateHistogramWithUnit(Meter meter); + + [Histogram(typeof(Dimensions), Unit = "s")] + public static partial HistogramStrongTypeWithUnit CreateHistogramStrongTypeWithUnit(Meter meter); + + [Histogram("s1", Unit = "requests", Name = "HistogramWithUnitAndDims")] + public static partial HistogramWithUnitAndDims CreateHistogramWithUnitAndDims(Meter meter); + } + + public class Dimensions + { + public string? Dim1; + public string? Dim2; + } +#pragma warning disable SA1402 +} diff --git a/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.StrongTypes.cs b/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.StrongTypes.cs index 6b345029492..892b6fa3e15 100644 --- a/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.StrongTypes.cs +++ b/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.StrongTypes.cs @@ -660,4 +660,23 @@ static partial class MetricClass }"); Assert.Empty(d); } + + [Fact] + public async Task StructTypeWithUnit() + { + var d = await RunGenerator(@" + public struct HistogramStruct + { + [Dimension(""Dim1_FromAttribute"")] + public string? Dim1 { get; set; } + } + + public static partial class MetricClass + { + [Histogram(typeof(HistogramStruct), Name=""TotalCountTest"", Unit = ""s"")] + public static partial TotalCount CreateTotalCountCounter(Meter meter); + }"); + + Assert.Empty(d); + } } diff --git a/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.cs b/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.cs index 54a19ea2e86..f9d98461b0d 100644 --- a/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.cs +++ b/test/Generators/Microsoft.Gen.Metrics/Unit/ParserTests.cs @@ -792,4 +792,17 @@ private static async Task> RunGenerator( return d; } + + [Fact] + public async Task UnitParameterTest() + { + var d = await RunGenerator(@" + partial class C + { + [Counter(Unit = ""s"", Name = ""myMetricName"")] + static partial MetricName CreateMetric(Meter meter); + }"); + + Assert.Empty(d); + } } From 0dfcceda5ac7c5288ffff555be0db9329fc6c130 Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 11:43:45 +0100 Subject: [PATCH 2/8] fixes --- src/Generators/Microsoft.Gen.Metrics/Parser.cs | 2 +- .../Metrics/TagNameAttribute.cs | 5 ----- .../Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Generators/Microsoft.Gen.Metrics/Parser.cs b/src/Generators/Microsoft.Gen.Metrics/Parser.cs index e78b1cfdf32..25c2b33b3e9 100644 --- a/src/Generators/Microsoft.Gen.Metrics/Parser.cs +++ b/src/Generators/Microsoft.Gen.Metrics/Parser.cs @@ -617,7 +617,7 @@ private StrongTypeAttributeParameters ExtractStrongTypeAttributeParameters( { var strongTypeAttributeParameters = new StrongTypeAttributeParameters(); - // i want to check namedArguments array for key == name and for key == unit + // Extract "Name" and "Unit" values from the named arguments, if present, and assign them to the corresponding properties. foreach (var namedArgument in namedArguments) { if (namedArgument.Key == "Name" && namedArgument.Value.Value is { } nameValue) diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs index a46af7623f2..77b9811c395 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/TagNameAttribute.cs @@ -41,9 +41,4 @@ public TagNameAttribute(string name) /// Gets the name of the tag. /// public string Name { get; } - - /// - /// Gets or sets the unit of measurement for the metric. - /// - public string? Unit { get; set; } } diff --git a/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs index bd9b231525b..759117e490a 100644 --- a/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs +++ b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs @@ -16,7 +16,6 @@ public void ValidateCounterWithUnit() // Verify that a counter created with a unit works correctly using var collector = new MetricCollector(_meter, "CounterWithUnit"); - // You'll need to add this to TestClasses/MetricsWithUnit.cs CounterWithUnit counter = MetricsWithUnit.CreateCounterWithUnit(_meter); counter.Add(100L); @@ -33,7 +32,6 @@ public void ValidateHistogramWithUnit() // Verify that a histogram created with a unit works correctly using var collector = new MetricCollector(_meter, "HistogramWithUnit"); - // You'll need to add this to TestClasses/HistogramTestExtensions.cs HistogramWithUnit histogram = MetricsWithUnit.CreateHistogramWithUnit(_meter); histogram.Record(50L); From 0d19bf7b73cd3e025ad3d24f6f37260ac7a4d343 Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 12:08:21 +0100 Subject: [PATCH 3/8] couple more tests --- .../Generated/MetricTests.Ext.Unit.cs | 60 +++++++++++++++++++ .../TestClasses/MetricsWithUnit.cs | 4 +- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs index 759117e490a..ddf5519ee40 100644 --- a/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs +++ b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs @@ -83,6 +83,66 @@ public void ValidateHistogramWithUnitAndDimensions() Assert.Equal("requests", collector.Instrument.Unit); } + [Fact] + public void ValidateHistogramWithUnitAndStrongType() + { + var newDimensions = new Dimensions + { + Dim1 = "s1", + Dim2 = "s2" + }; + + // Verify that a histogram created with a unit works correctly + using var collector = new MetricCollector(_meter, nameof(HistogramStrongTypeWithUnit)); + + HistogramStrongTypeWithUnit histogram = MetricsWithUnit.CreateHistogramStrongTypeWithUnit(_meter); + histogram.Record(50L, newDimensions); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(50L, measurement.Value); + + Assert.NotNull(collector.Instrument); + Assert.Equal("s", collector.Instrument.Unit); + + Assert.Equal( + new (string, object?)[] + { + ("Dim1", newDimensions.Dim1), + ("Dim2", newDimensions.Dim2) + }, + measurement.Tags.Select(x => (x.Key, x.Value))); + } + + [Fact] + public void ValidateCounterWithUnitAndStrongType() + { + var newDimensions = new Dimensions + { + Dim1 = "s1", + Dim2 = "s2" + }; + + // Verify that a histogram created with a unit works correctly + using var collector = new MetricCollector(_meter, nameof(CounterStrongTypeWithUnit)); + + CounterStrongTypeWithUnit counter = MetricsWithUnit.CreateCounterStrongTypeWithUnit(_meter); + counter.Add(50L, newDimensions); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(50L, measurement.Value); + + Assert.NotNull(collector.Instrument); + Assert.Equal("bytes", collector.Instrument.Unit); + + Assert.Equal( + new (string, object?)[] + { + ("Dim1", newDimensions.Dim1), + ("Dim2", newDimensions.Dim2) + }, + measurement.Tags.Select(x => (x.Key, x.Value))); + } + [Fact] public void ValidateGenericCounterWithUnit() { diff --git a/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs b/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs index 9b26a686ba3..4d844204723 100644 --- a/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs +++ b/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs @@ -36,8 +36,8 @@ public static partial class MetricsWithUnit public class Dimensions { - public string? Dim1; - public string? Dim2; + public string? Dim1 { get; set; } + public string? Dim2 { get; set; } } #pragma warning disable SA1402 } From f5f1670ca3c135b6fd3aef76c282659f44a19d0a Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 12:14:03 +0100 Subject: [PATCH 4/8] adding @verbatim --- src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs b/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs index a947f9aac05..76c6db3ef9d 100644 --- a/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs +++ b/src/Generators/Microsoft.Gen.Metrics/MetricFactoryEmitter.cs @@ -152,7 +152,7 @@ private void GenMetricFactoryMethods(MetricMethod metricMethod, string nspace) } else { - OutLn($" var instrument = _meter.{createMethodName}(@\"{metricMethod.MetricName}\", \"{metricMethod.MetricUnit}\");"); + OutLn($" var instrument = _meter.{createMethodName}(@\"{metricMethod.MetricName}\", @\"{metricMethod.MetricUnit}\");"); } OutLn($" return new {nsprefix}{metricMethod.MetricTypeName}(instrument);"); From 455e0352f55fd56abb07288a7968798caa78c66f Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 13:32:49 +0100 Subject: [PATCH 5/8] adding experimental attribute --- .../Metrics/CounterAttribute.cs | 3 +++ .../Metrics/CounterAttributeT.cs | 3 +++ .../Metrics/GaugeAttribute.cs | 3 +++ .../Metrics/HistogramAttribute.cs | 3 +++ .../Metrics/HistogramAttributeT.cs | 3 +++ 5 files changed, 15 insertions(+) diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs index 6ef199e1add..d65dd51c5dc 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs @@ -3,6 +3,8 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.Metrics; @@ -80,5 +82,6 @@ public CounterAttribute(Type type) /// /// Gets or sets the unit of measurement for the metric. /// + [Experimental(DiagnosticIds.Experiments.Telemetry)] public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs index c447d93ce64..91426ac71b2 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttributeT.cs @@ -3,6 +3,8 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.Metrics; @@ -86,5 +88,6 @@ public CounterAttribute(Type type) /// /// Gets or sets the unit of measurement for the metric. /// + [Experimental(DiagnosticIds.Experiments.Telemetry)] public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs index b96c00ff566..e26375eda90 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/GaugeAttribute.cs @@ -3,6 +3,8 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.Metrics; @@ -79,5 +81,6 @@ public GaugeAttribute(Type type) /// /// Gets or sets the unit of measurement for the metric. /// + [Experimental(DiagnosticIds.Experiments.Telemetry)] public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs index 92422e11cc2..43f7b914051 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttribute.cs @@ -3,6 +3,8 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.Metrics; @@ -79,5 +81,6 @@ public HistogramAttribute(Type type) /// /// Gets or sets the unit of measurement for the metric. /// + [Experimental(DiagnosticIds.Experiments.Telemetry)] public string? Unit { get; set; } } diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs index cdfcc3dd64b..afdd9a30828 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/HistogramAttributeT.cs @@ -3,6 +3,8 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Shared.DiagnosticIds; namespace Microsoft.Extensions.Diagnostics.Metrics; @@ -86,5 +88,6 @@ public HistogramAttribute(Type type) /// /// Gets or sets the unit of measurement for the metric. /// + [Experimental(DiagnosticIds.Experiments.Telemetry)] public string? Unit { get; set; } } From 81de4ed38801e8e684a7d707094e71aedaa0019a Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 13:43:07 +0100 Subject: [PATCH 6/8] testing unit in attribute --- .../Metrics/MetricAttributeTests.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs b/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs index 4d60eaa06a1..259120e949b 100644 --- a/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs +++ b/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs @@ -16,6 +16,7 @@ public void TestCounterAttribute() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.Type); + Assert.Null(attribute.Unit); Assert.Equal(new[] { "d1", "d2", "d3" }, attribute.TagNames); attribute.Name = MyMetric; @@ -29,6 +30,7 @@ public void TestHistogramAttribute() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.Type); + Assert.Null(attribute.Unit); Assert.Equal(new[] { "d1", "d2", "d3" }, attribute.TagNames); attribute.Name = MyMetric; @@ -42,6 +44,7 @@ public void TestCounterAttributeT() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.Type); + Assert.Null(attribute.Unit); Assert.Equal(new[] { "d1", "d2", "d3" }, attribute.TagNames); attribute.Name = MyMetric; @@ -55,6 +58,7 @@ public void TestHistogramAttributeT() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.Type); + Assert.Null(attribute.Unit); Assert.Equal(new[] { "d1", "d2", "d3" }, attribute.TagNames); attribute.Name = MyMetric; @@ -68,6 +72,7 @@ public void TestGaugeAttribute() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.Type); + Assert.Null(attribute.Unit); Assert.Equal(new[] { "d1", "d2", "d3" }, attribute.TagNames); attribute.Name = MyMetric; @@ -82,6 +87,7 @@ public void TestStrongTypeCounterAttribute() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.TagNames); + Assert.Null(attribute.Unit); Assert.Equal(typeof(TagNameTest), attribute.Type); attribute.Name = MyMetric; @@ -96,6 +102,7 @@ public void TestStrongTypeHistogramAttribute() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.TagNames); + Assert.Null(attribute.Unit); Assert.Equal(typeof(TagNameTest), attribute.Type); attribute.Name = MyMetric; @@ -110,6 +117,7 @@ public void TestStrongTypeCounterAttributeT() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.TagNames); + Assert.Null(attribute.Unit); Assert.Equal(typeof(TagNameTest), attribute.Type); attribute.Name = MyMetric; @@ -124,6 +132,7 @@ public void TestStrongTypeHistogramAttributeT() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.TagNames); + Assert.Null(attribute.Unit); Assert.Equal(typeof(TagNameTest), attribute.Type); attribute.Name = MyMetric; @@ -138,6 +147,7 @@ public void TestStrongTypeGaugeAttribute() Assert.NotNull(attribute); Assert.Null(attribute.Name); Assert.Null(attribute.TagNames); + Assert.Null(attribute.Unit); Assert.Equal(typeof(TagNameTest), attribute.Type); attribute.Name = MyMetric; From 0b716fa8e489bbc49ca44267babbaf83fc93ea10 Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 14:47:08 +0100 Subject: [PATCH 7/8] updating tests --- .../Metrics/MetricAttributeTests.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs b/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs index 259120e949b..bae3dc9f014 100644 --- a/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs +++ b/test/Libraries/Microsoft.Extensions.Telemetry.Abstractions.Tests/Metrics/MetricAttributeTests.cs @@ -21,6 +21,8 @@ public void TestCounterAttribute() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -35,6 +37,8 @@ public void TestHistogramAttribute() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -49,6 +53,8 @@ public void TestCounterAttributeT() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -63,6 +69,8 @@ public void TestHistogramAttributeT() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -77,6 +85,8 @@ public void TestGaugeAttribute() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -92,6 +102,8 @@ public void TestStrongTypeCounterAttribute() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -107,6 +119,8 @@ public void TestStrongTypeHistogramAttribute() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -122,6 +136,8 @@ public void TestStrongTypeCounterAttributeT() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -137,6 +153,8 @@ public void TestStrongTypeHistogramAttributeT() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] @@ -152,6 +170,8 @@ public void TestStrongTypeGaugeAttribute() attribute.Name = MyMetric; Assert.Equal(MyMetric, attribute.Name); + attribute.Unit = "items"; + Assert.Equal("items", attribute.Unit); } [Fact] From 6d566f7ef3115d35b55936075c5501d7abc005ce Mon Sep 17 00:00:00 2001 From: Mariam Aziz Date: Tue, 2 Dec 2025 16:55:29 +0100 Subject: [PATCH 8/8] comments --- .../Metrics/CounterAttribute.cs | 2 +- .../Generated/MetricTests.Ext.Unit.cs | 39 +++++++++++++------ .../TestClasses/MetricsWithUnit.cs | 5 ++- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs index d65dd51c5dc..43894559618 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry.Abstractions/Metrics/CounterAttribute.cs @@ -75,7 +75,7 @@ public CounterAttribute(Type type) public string[]? TagNames { get; } /// - /// Gets the type that supplies metric tags values. + /// Gets the type that supplies metric tag values. /// public Type? Type { get; } diff --git a/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs index ddf5519ee40..7e794d8a2ae 100644 --- a/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs +++ b/test/Generators/Microsoft.Gen.Metrics/Generated/MetricTests.Ext.Unit.cs @@ -11,9 +11,8 @@ namespace Microsoft.Gen.Metrics.Test; public partial class MetricTests { [Fact] - public void ValidateCounterWithUnit() + public void CounterWithUnit_WorkCorrectly() { - // Verify that a counter created with a unit works correctly using var collector = new MetricCollector(_meter, "CounterWithUnit"); CounterWithUnit counter = MetricsWithUnit.CreateCounterWithUnit(_meter); @@ -27,9 +26,8 @@ public void ValidateCounterWithUnit() } [Fact] - public void ValidateHistogramWithUnit() + public void HistogramWithUnit_WorkCorrectly() { - // Verify that a histogram created with a unit works correctly using var collector = new MetricCollector(_meter, "HistogramWithUnit"); HistogramWithUnit histogram = MetricsWithUnit.CreateHistogramWithUnit(_meter); @@ -44,7 +42,7 @@ public void ValidateHistogramWithUnit() } [Fact] - public void ValidateCounterWithUnitAndDimensions() + public void CounterWithUnitAndDimensions_WorkCorrectly() { const long Value = 12345L; @@ -64,11 +62,11 @@ public void ValidateCounterWithUnitAndDimensions() } [Fact] - public void ValidateHistogramWithUnitAndDimensions() + public void HistogramWithUnitAndDimensions_WorkCorrectly() { - const int Value = 9876; + const long Value = 9876; - using var collector = new MetricCollector(_meter, "HistogramWithUnitAndDims"); + using var collector = new MetricCollector(_meter, "HistogramWithUnitAndDims"); HistogramWithUnitAndDims histogram = MetricsWithUnit.CreateHistogramWithUnitAndDims(_meter); histogram.Record(Value, "val1"); @@ -84,7 +82,7 @@ public void ValidateHistogramWithUnitAndDimensions() } [Fact] - public void ValidateHistogramWithUnitAndStrongType() + public void HistogramStrongTypeAndUnit_WorkCorrectly() { var newDimensions = new Dimensions { @@ -114,7 +112,7 @@ public void ValidateHistogramWithUnitAndStrongType() } [Fact] - public void ValidateCounterWithUnitAndStrongType() + public void CounterStrongTypeAndUnit_WorkCorrectly() { var newDimensions = new Dimensions { @@ -144,7 +142,7 @@ public void ValidateCounterWithUnitAndStrongType() } [Fact] - public void ValidateGenericCounterWithUnit() + public void GenericCounterWithUnit_WorkCorrectly() { using var collector = new MetricCollector(_meter, "GenericDoubleCounterWithUnit"); @@ -161,7 +159,24 @@ public void ValidateGenericCounterWithUnit() } [Fact] - public void ValidateCounterWithEmptyUnit() + public void GenericHistogramWithUnit_WorkCorrectly() + { + using var collector = new MetricCollector(_meter, "GenericIntHistogramWithUnit"); + + GenericIntHistogramWithUnit counter = MetricsWithUnit.CreateGenericHistogramWithUnitAndDims(_meter); + counter.Record(3); + + var measurement = Assert.Single(collector.GetMeasurementSnapshot()); + Assert.Equal(3, measurement.Value); + Assert.Empty(measurement.Tags); + + // Verify the instrument has the correct unit + Assert.NotNull(collector.Instrument); + Assert.Equal("microseconds", collector.Instrument.Unit); + } + + [Fact] + public void CounterWithNoUnit_UnitInInstrumentIsNull() { // Test that counters with empty/null units work using var collector = new MetricCollector(_meter, nameof(Counter0D)); diff --git a/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs b/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs index 4d844204723..95432f4aa05 100644 --- a/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs +++ b/test/Generators/Microsoft.Gen.Metrics/TestClasses/MetricsWithUnit.cs @@ -30,8 +30,11 @@ public static partial class MetricsWithUnit [Histogram(typeof(Dimensions), Unit = "s")] public static partial HistogramStrongTypeWithUnit CreateHistogramStrongTypeWithUnit(Meter meter); - [Histogram("s1", Unit = "requests", Name = "HistogramWithUnitAndDims")] + [Histogram("s1", Unit = "requests", Name = "HistogramWithUnitAndDims")] public static partial HistogramWithUnitAndDims CreateHistogramWithUnitAndDims(Meter meter); + + [Histogram(Unit = "microseconds", Name = "GenericIntHistogramWithUnit")] + public static partial GenericIntHistogramWithUnit CreateGenericHistogramWithUnitAndDims(Meter meter); } public class Dimensions