From 88e95b846521db913eebdb799b2d2cebcbf80c49 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Thu, 12 Dec 2024 11:09:27 +0000 Subject: [PATCH 1/2] Refactor Telemetry Metric generator to work with arbitrary number of tags No changes to the generated code or anything, just making it work... --- .../TelemetryMetric/Sources.cs | 624 +++++++++--------- .../TelemetryMetricGenerator.cs | 57 +- 2 files changed, 352 insertions(+), 329 deletions(-) diff --git a/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.cs b/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.cs index a84981ec4da1..68c3cab96e6d 100644 --- a/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.cs +++ b/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.cs @@ -97,28 +97,15 @@ internal partial interface IMetricsTelemetryCollector sb.AppendLine(); var (property, metric) = names[i]; - if (metric.Tag2FullyQualifiedName is { } tagName2) - { - var tagName1 = metric.Tag1FullyQualifiedName!; - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int increment = 1); - """); - } - else if (metric.Tag1FullyQualifiedName is { } tagName) - { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, int increment = 1); - """); - } - else - { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}(int increment = 1); - """); - } + sb.Append( + $$""" + public void Record{{details.ShortName}}{{property}}( + """); + + var array = metric.TagFullyQualifiedNames.AsArray() ?? []; + WriteTagArgList(sb, array); + + sb.AppendLine("int increment = 1);"); } } @@ -153,28 +140,15 @@ internal partial interface IMetricsTelemetryCollector sb.AppendLine(); var (property, metric) = names[i]; - if (metric.Tag2FullyQualifiedName is { } tagName2) - { - var tagName1 = metric.Tag1FullyQualifiedName!; - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int value); - """); - } - else if (metric.Tag1FullyQualifiedName is { } tagName) - { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, int value); - """); - } - else - { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}(int value); - """); - } + sb.Append( + $$""" + public void Record{{details.ShortName}}{{property}}( + """); + + var array = metric.TagFullyQualifiedNames.AsArray() ?? []; + WriteTagArgList(sb, array); + + sb.AppendLine("int value);"); } } @@ -209,28 +183,15 @@ internal partial interface IMetricsTelemetryCollector sb.AppendLine(); var (property, metric) = names[i]; - if (metric.Tag2FullyQualifiedName is { } tagName2) - { - var tagName1 = metric.Tag1FullyQualifiedName!; - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, double value); - """); - } - else if (metric.Tag1FullyQualifiedName is { } tagName) - { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, double value); - """); - } - else - { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}(double value); - """); - } + sb.Append( + $$""" + public void Record{{details.ShortName}}{{property}}( + """); + + var array = metric.TagFullyQualifiedNames.AsArray() ?? []; + WriteTagArgList(sb, array); + + sb.AppendLine("double value);"); } } @@ -760,38 +721,13 @@ internal partial class {{collectorName}} var (property, metric) = names[i]; var index = metricsToLocation[i]; - if (metric.Tag2FullyQualifiedName is { } tagName2) + if (doRecord) { - if (doRecord) - { - WriteRecordCount(sb, in details, property, index, metric.Tag1FullyQualifiedName!, tagName2, enumDictionary[tagName2].Count); - } - else - { - WriteNoopCount(sb, in details, property, metric.Tag1FullyQualifiedName!, tagName2); - } - } - else if (metric.Tag1FullyQualifiedName is { } tagName) - { - if (doRecord) - { - WriteRecordCount(sb, in details, property, index, tagName); - } - else - { - WriteNoopCount(sb, in details, property, tagName); - } + WriteRecordCount(sb, in details, property, index, metric.TagFullyQualifiedNames, enumDictionary); } else { - if (doRecord) - { - WriteRecordCount(sb, details, property, index); - } - else - { - WriteNoopCount(sb, in details, property); - } + WriteNoopCount(sb, in details, property, metric.TagFullyQualifiedNames, enumDictionary); } } } @@ -860,38 +796,13 @@ internal partial class {{collectorName}} var (property, metric) = names[i]; var index = metricsToLocation[i]; - if (metric.Tag2FullyQualifiedName is { } tagName2) - { - if (doRecord) - { - WriteRecordGauge(sb, in details, property, index, metric.Tag1FullyQualifiedName!, tagName2, enumDictionary[tagName2].Count); - } - else - { - WriteNoopGauge(sb, in details, property, metric.Tag1FullyQualifiedName!, tagName2); - } - } - else if (metric.Tag1FullyQualifiedName is { } tagName) + if (doRecord) { - if (doRecord) - { - WriteRecordGauge(sb, in details, property, index, tagName); - } - else - { - WriteNoopGauge(sb, in details, property, tagName); - } + WriteRecordGauge(sb, in details, property, index, metric.TagFullyQualifiedNames, enumDictionary); } else { - if (doRecord) - { - WriteRecordGauge(sb, details, property, index); - } - else - { - WriteNoopGauge(sb, in details, property); - } + WriteNoopGauge(sb, in details, property, metric.TagFullyQualifiedNames, enumDictionary); } } } @@ -959,38 +870,13 @@ internal partial class {{collectorName}} var (property, metric) = names[i]; var index = metricsToLocation[i]; - if (metric.Tag2FullyQualifiedName is { } tagName2) + if (doRecord) { - if (doRecord) - { - WriteRecordDistribution(sb, in details, property, index, metric.Tag1FullyQualifiedName!, tagName2, enumDictionary[tagName2].Count); - } - else - { - WriteNoopDistribution(sb, in details, property, metric.Tag1FullyQualifiedName!, tagName2); - } - } - else if (metric.Tag1FullyQualifiedName is { } tagName) - { - if (doRecord) - { - WriteRecordDistribution(sb, in details, property, index, tagName); - } - else - { - WriteNoopDistribution(sb, in details, property, tagName); - } + WriteRecordDistribution(sb, in details, property, index, metric.TagFullyQualifiedNames, enumDictionary); } else { - if (doRecord) - { - WriteRecordDistribution(sb, details, property, index); - } - else - { - WriteNoopDistribution(sb, in details, property); - } + WriteNoopDistribution(sb, in details, property, metric.TagFullyQualifiedNames, enumDictionary); } } } @@ -1027,69 +913,96 @@ private static void AddAggregatedMetrics(StringBuilder sb, in TelemetryMetricGen return; } - var i = 0; + var index = 0; foreach (var (_, metric) in names) { sb.AppendLine( $$""" - // {{metric.MetricName}}, index = {{i}} + // {{metric.MetricName}}, index = {{index}} """); const string prefix = """ new( """; - if (metric.Tag1FullyQualifiedName is { } tag1Type && enumDictionary[tag1Type].AsArray() is { } tag1Values) + + // Write the cartesian product of all the arrays + var tags = metric.TagFullyQualifiedNames.AsArray() ?? []; + List tagValues = new(tags.Length); + bool haveTags = false; + + foreach (var tag in tags) { - foreach (var tag1Value in tag1Values) + var values = enumDictionary[tag].AsArray() ?? []; + tagValues.Add([..values]); + haveTags |= values.Length > 0; + } + + if (haveTags) + { + // Could reduce allocations here, e.g. use stackalloc, but in a loop so meh + var indices = new int[tagValues.Count]; + while (true) { - if (metric.Tag2FullyQualifiedName is { } tag2Type && enumDictionary[tag2Type].AsArray() is { } tag2Values) + index++; + // Build the current combination + // if every entry is empty, we write null instead of an array + // so need to check first + bool haveNonNullValues = false; + for (var i = 0; i < tagValues.Count; i++) { - foreach (var tag2Value in tag2Values) + if (!string.IsNullOrEmpty(tagValues[i][indices[i]])) { - i++; - sb.Append(prefix); - - if (string.IsNullOrEmpty(tag1Value) && string.IsNullOrEmpty(tag2Value)) - { - sb.AppendLine("null),"); - continue; - } - - sb.Append("new[] { "); - - WriteAllValues(sb, tag1Value); - WriteAllValues(sb, tag2Value); + haveNonNullValues = true; + break; + } + } - sb.Remove(sb.Length - 2, 2); // remove the final ', ' - sb.AppendLine(" }),"); + if (haveNonNullValues) + { + // write the full set + sb.Append($$"""{{prefix}}new[] { """); + for (var i = 0; i < tagValues.Count; i++) + { + WriteAllValues(sb, tagValues[i][indices[i]]); } + + sb.Remove(sb.Length - 2, 2); // remove the final ', ' + sb.AppendLine(" }),"); } else { - i++; - sb.Append(prefix); + // no non-empty tags + sb.AppendLine($$"""{{prefix}}null),"""); + } - if (string.IsNullOrEmpty(tag1Value)) + // Advance to the next combination + var incrementIndex = tagValues.Count - 1; + while (incrementIndex >= 0) + { + indices[incrementIndex]++; + if (indices[incrementIndex] < tagValues[incrementIndex].Length) { - sb.AppendLine("null),"); - continue; + // We've successfully incremented this index, so we're ready to write the next combo + break; } - sb.Append("new[] { "); - - WriteAllValues(sb, tag1Value); + // we went off the end, so reset, and increment the first tag + indices[incrementIndex] = 0; + incrementIndex--; + } - sb.Remove(sb.Length - 2, 2); // remove the final ', ' - sb.AppendLine(" }),"); + // If we've wrapped around at the first index, we're done + if (incrementIndex < 0) + { + break; } } } else { - i++; - sb - .Append(prefix) - .AppendLine("null),"); + // no tags + index++; + sb.AppendLine($$"""{{prefix}}null),"""); } } @@ -1160,196 +1073,311 @@ private static string GetValues( return sb.ToString(); } - private static void WriteRecordCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index) + private static void WriteRecordCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, EquatableArray tagNames, Dictionary> enumDictionary) { - sb.AppendLine( + var tagArray = tagNames.AsArray() ?? []; + if (tagArray.Length == 0) + { + // we don't need to keep this separate technically, could easily inline it, but it would change the generated code + // very slightly (though the IL will remain the same) + + sb.AppendLine( + $$""" + public void Record{{details.ShortName}}{{property}}(int increment = 1) + { + Interlocked.Add(ref _buffer.{{details.ShortName}}[{{index}}], increment); + } + """); + return; + } + + // Produces something similar to this: + // public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int increment = 1) + // { + // var index = {{index}} + ((int)tag1 * {{tag2EntryCount}}) + (int)tag2; + // Interlocked.Add(ref _buffer.{{details.ShortName}}[index], increment); + // } + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}(int increment = 1) - { - Interlocked.Add(ref _buffer.{{details.ShortName}}[{{index}}], increment); - } + public void Record{{details.ShortName}}{{property}}( """); - } - private static void WriteRecordCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, string tagName) - { - sb.AppendLine( + WriteTagArgList(sb, tagArray); + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, int increment = 1) + int increment = 1) { - var index = {{index}} + (int)tag; - Interlocked.Add(ref _buffer.{{details.ShortName}}[index], increment); - } + var index = {{index}} """); - } - private static void WriteRecordCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, string tagName1, string tagName2, int tag2EntryCount) - { + WriteTagIndices(sb, enumDictionary, tagArray); + sb.AppendLine( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int increment = 1) - { - var index = {{index}} + ((int)tag1 * {{tag2EntryCount}}) + (int)tag2; + ; Interlocked.Add(ref _buffer.{{details.ShortName}}[index], increment); } """); } - private static void WriteRecordGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index) + private static void WriteRecordGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, EquatableArray tagNames, Dictionary> enumDictionary) { - sb.AppendLine( + var tagArray = tagNames.AsArray() ?? []; + if (tagArray.Length == 0) + { + // we don't need to keep this separate technically, could easily inline it, but it would change the generated code + // very slightly (though the IL will remain the same) + + sb.AppendLine( + $$""" + public void Record{{details.ShortName}}{{property}}(int value) + { + Interlocked.Exchange(ref _buffer.{{details.ShortName}}[{{index}}], value); + } + """); + return; + } + + // Produces something similar to this: + // public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int value) + // { + // var index = {{index}} + ((int)tag1 * {{tag2EntryCount}}) + (int)tag2; + // Interlocked.Exchange(ref _buffer.{{details.ShortName}}[index], value); + // } + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}(int value) - { - Interlocked.Exchange(ref _buffer.{{details.ShortName}}[{{index}}], value); - } + public void Record{{details.ShortName}}{{property}}( """); - } - private static void WriteRecordGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, string tagName) - { - sb.AppendLine( + WriteTagArgList(sb, tagArray); + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, int value) + int value) { - var index = {{index}} + (int)tag; - Interlocked.Exchange(ref _buffer.{{details.ShortName}}[index], value); - } + var index = {{index}} """); - } - private static void WriteRecordGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, string tagName1, string tagName2, int tag2EntryCount) - { + WriteTagIndices(sb, enumDictionary, tagArray); + sb.AppendLine( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int value) - { - var index = {{index}} + ((int)tag1 * {{tag2EntryCount}}) + (int)tag2; + ; Interlocked.Exchange(ref _buffer.{{details.ShortName}}[index], value); } """); } - private static void WriteRecordDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index) + private static void WriteRecordDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, EquatableArray tagNames, Dictionary> enumDictionary) { - sb.AppendLine( + var tagArray = tagNames.AsArray() ?? []; + if (tagArray.Length == 0) + { + // we don't need to keep this separate technically, could easily inline it, but it would change the generated code + // very slightly (though the IL will remain the same) + sb.AppendLine( + $$""" + public void Record{{details.ShortName}}{{property}}(double value) + { + _buffer.{{details.ShortName}}[{{index}}].TryEnqueue(value); + } + """); + return; + } + + // Produces something similar to this: + // public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int value) + // { + // var index = {{index}} + ((int)tag1 * {{tag2EntryCount}}) + (int)tag2; + // Interlocked.Exchange(ref _buffer.{{details.ShortName}}[index], value); + // } + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}(double value) - { - _buffer.{{details.ShortName}}[{{index}}].TryEnqueue(value); - } + public void Record{{details.ShortName}}{{property}}( """); - } - private static void WriteRecordDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, string tagName) - { - sb.AppendLine( + WriteTagArgList(sb, tagArray); + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, double value) + double value) { - var index = {{index}} + (int)tag; - _buffer.{{details.ShortName}}[index].TryEnqueue(value); - } + var index = {{index}} """); - } - private static void WriteRecordDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, int index, string tagName1, string tagName2, int tag2EntryCount) - { + WriteTagIndices(sb, enumDictionary, tagArray); + sb.AppendLine( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, double value) - { - var index = {{index}} + ((int)tag1 * {{tag2EntryCount}}) + (int)tag2; + ; _buffer.{{details.ShortName}}[index].TryEnqueue(value); } """); } - private static void WriteNoopCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property) + private static void WriteTagArgList(StringBuilder sb, string[] tagArray) { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}(int increment = 1) - { - } - """); - } + for (var i = 0; i < tagArray.Length; i++) + { + sb.Append(tagArray[i]) + .Append(" tag"); - private static void WriteNoopCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, string tagName) - { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, int increment = 1) - { - } - """); + if (tagArray.Length > 1) + { + sb.Append(i + 1); + } + + sb.Append(", "); + } } - private static void WriteNoopCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, string tagName1, string tagName2) + private static void WriteTagIndices(StringBuilder sb, Dictionary> enumDictionary, string[] tagArray) { - sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int increment = 1) - { - } - """); + if (tagArray.Length == 0) + { + return; + } + + Span multipliers = stackalloc int[tagArray.Length]; + var indexer = 1; + + // set the multipliers for each tag + for (var i = tagArray.Length - 1; i >= 0; i--) + { + multipliers[i] = indexer; + indexer *= enumDictionary.TryGetValue(tagArray[i], out var entries) ? entries.Count : 1; + } + + for (var i = 0; i < tagArray.Length; i++) + { + var multiplier = multipliers[i]; + if (multiplier == 1) + { + sb.Append(" + (int)tag"); + + if (tagArray.Length > 1) + { + sb.Append(i + 1); + } + } + else + { + sb.Append(" + ((int)tag") + .Append(i + 1) + .Append(" * ") + .Append(multiplier) + .Append(')'); + } + } } - private static void WriteNoopGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property) + private static void WriteNoopCount(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, EquatableArray tagNames, Dictionary> enumDictionary) { - sb.AppendLine( + var tagArray = tagNames.AsArray() ?? []; + if (tagArray.Length == 0) + { + // we don't need to keep this separate technically, could easily inline it, but it would change the generated code + // very slightly (though the IL will remain the same) + sb.AppendLine( + $$""" + public void Record{{details.ShortName}}{{property}}(int increment = 1) + { + } + """); + return; + } + + // Produces something similar to this: + // public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int increment = 1) + // { + // } + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}(int value) - { - } + public void Record{{details.ShortName}}{{property}}( """); - } - private static void WriteNoopGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, string tagName) - { + WriteTagArgList(sb, tagArray); + sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, int value) + """ + int increment = 1) { } """); } - private static void WriteNoopGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, string tagName1, string tagName2) + private static void WriteNoopGauge(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, EquatableArray tagNames, Dictionary> enumDictionary) { - sb.AppendLine( + var tagArray = tagNames.AsArray() ?? []; + if (tagArray.Length == 0) + { + // we don't need to keep this separate technically, could easily inline it, but it would change the generated code + // very slightly (though the IL will remain the same) + sb.AppendLine( + $$""" + public void Record{{details.ShortName}}{{property}}(int value) + { + } + """); + return; + } + + // Produces something similar to this: + // public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int value) + // { + // } + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int value) - { - } + public void Record{{details.ShortName}}{{property}}( """); - } - private static void WriteNoopDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property) - { + WriteTagArgList(sb, tagArray); + sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}(double value) + """ + int value) { } """); } - private static void WriteNoopDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, string tagName) + private static void WriteNoopDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, EquatableArray tagNames, Dictionary> enumDictionary) { - sb.AppendLine( + var tagArray = tagNames.AsArray() ?? []; + if (tagArray.Length == 0) + { + // we don't need to keep this separate technically, could easily inline it, but it would change the generated code + // very slightly (though the IL will remain the same) + sb.AppendLine( + $$""" + public void Record{{details.ShortName}}{{property}}(double value) + { + } + """); + return; + } + + // Produces something similar to this: + // public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, int value) + // { + // } + + sb.Append( $$""" - public void Record{{details.ShortName}}{{property}}({{tagName}} tag, double value) - { - } + public void Record{{details.ShortName}}{{property}}( """); - } - private static void WriteNoopDistribution(StringBuilder sb, in TelemetryMetricGenerator.EnumDetails details, string property, string tagName1, string tagName2) - { + WriteTagArgList(sb, tagArray); + sb.AppendLine( - $$""" - public void Record{{details.ShortName}}{{property}}({{tagName1}} tag1, {{tagName2}} tag2, double value) + """ + double value) { } """); diff --git a/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/TelemetryMetricGenerator.cs b/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/TelemetryMetricGenerator.cs index 8f00708c8e15..f5a9180e9e3d 100644 --- a/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/TelemetryMetricGenerator.cs +++ b/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/TelemetryMetricGenerator.cs @@ -136,15 +136,16 @@ static Dictionary> GetEnumDictionary(in EnumDetai { locations[i] = index; var (_, metric) = names[i]; - var tag1Count = metric.Tag1FullyQualifiedName is { } tag1Type && enumDictionary[tag1Type].AsArray() is { } tag1Values - ? tag1Values.Length - : 1; - var tag2Count = metric.Tag2FullyQualifiedName is { } tag2Type && enumDictionary[tag2Type].AsArray() is { } tag2Values - ? tag2Values.Length - : 1; + var entryCount = 1; + foreach (var tagType in metric.TagFullyQualifiedNames.AsArray() ?? []) + { + if (enumDictionary[tagType].AsArray() is { } tagValues) + { + entryCount *= tagValues.Length; + } + } - var entryCount = tag1Count * tag2Count; entryCounts[i] = entryCount; index += entryCount; } @@ -224,8 +225,7 @@ private static void GenerateAggregateCollectors(in ImmutableArray e string? metricName = null; bool isCommon = true; string? nameSpace = null; - string? tag1FullyQualifiedName = null; - string? tag2FullyQualifiedName = null; + string[]? tagFullyQualifiedNames = null; foreach (var attribute in memberSymbol.GetAttributes()) { if (attribute.AttributeClass?.Name is "TelemetryMetricAttribute" or "TelemetryMetric" @@ -245,24 +245,20 @@ private static void GenerateAggregateCollectors(in ImmutableArray e nameSpace = args[2].Value?.ToString(); } - var tagCount = attribute.AttributeClass.TypeParameters.Length; - if (tagCount > 0) - { - var tag1TypeParameter = attribute.AttributeClass.TypeArguments[0]; - tag1FullyQualifiedName = tag1TypeParameter.ToString(); - if (!enumTypeDictionary.ContainsKey(tag1FullyQualifiedName)) - { - enumTypeDictionary[tag1FullyQualifiedName] = GetTagValues(tag1TypeParameter, ref diagnostics); - } - } - - if (tagCount == 2) + var typeArgCount = attribute.AttributeClass.TypeParameters.Length; + if (typeArgCount > 0) { - var tag2TypeParameter = attribute.AttributeClass.TypeArguments[1]; - tag2FullyQualifiedName = tag2TypeParameter.ToString(); - if (!enumTypeDictionary.ContainsKey(tag2FullyQualifiedName)) + tagFullyQualifiedNames ??= new string[typeArgCount]; + for (var typeArg = 0; typeArg < typeArgCount; typeArg++) { - enumTypeDictionary[tag2FullyQualifiedName] = GetTagValues(tag2TypeParameter, ref diagnostics); + var tagType = attribute.AttributeClass.TypeArguments[typeArg]; + var tagFullyQualifiedName = tagType.ToString(); + if (!enumTypeDictionary.ContainsKey(tagFullyQualifiedName)) + { + enumTypeDictionary[tagFullyQualifiedName] = GetTagValues(tagType, ref diagnostics); + } + + tagFullyQualifiedNames[typeArg] = tagFullyQualifiedName; } } } @@ -276,7 +272,8 @@ private static void GenerateAggregateCollectors(in ImmutableArray e continue; } - members.Add((memberSymbol.Name, new MetricDetails(metricName!, isCommon, nameSpace, tag1FullyQualifiedName, tag2FullyQualifiedName))); + var tagNames = tagFullyQualifiedNames is not null ? new EquatableArray(tagFullyQualifiedNames) : new(); + members.Add((memberSymbol.Name, new MetricDetails(metricName!, isCommon, nameSpace, tagNames))); if (!uniqueValues.Add($"{metricName} {nameSpace ?? string.Empty} {(isCommon ? "true" : "false")}")) { diagnostics ??= new List(); @@ -388,16 +385,14 @@ internal readonly record struct MetricDetails public readonly string MetricName; public readonly bool IsCommon; public readonly string? NameSpace; - public readonly string? Tag1FullyQualifiedName; - public readonly string? Tag2FullyQualifiedName; + public readonly EquatableArray TagFullyQualifiedNames; - public MetricDetails(string metricName, bool isCommon, string? nameSpace, string? tag1FullyQualifiedName, string? tag2FullyQualifiedName) + public MetricDetails(string metricName, bool isCommon, string? nameSpace, EquatableArray tagFullyQualifiedNames) { MetricName = metricName; IsCommon = isCommon; NameSpace = nameSpace; - Tag1FullyQualifiedName = tag1FullyQualifiedName; - Tag2FullyQualifiedName = tag2FullyQualifiedName; + TagFullyQualifiedNames = tagFullyQualifiedNames; } } } From 630847449fc418d6f309b1c4f72ad21953363775 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Thu, 12 Dec 2024 12:12:09 +0000 Subject: [PATCH 2/2] Add support for adding more tags to metrics --- .../TelemetryMetric/Sources.Attributes.cs | 200 +++++++++++++++--- .../TelemetryMetricAttribute.g.cs | 200 +++++++++++++++--- .../TelemetryMetricAttribute.g.cs | 200 +++++++++++++++--- .../TelemetryMetricAttribute.g.cs | 200 +++++++++++++++--- .../TelemetryMetricAttribute.g.cs | 200 +++++++++++++++--- .../TelemetryMetricGeneratorTests.cs | 110 +++++++++- 6 files changed, 973 insertions(+), 137 deletions(-) diff --git a/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.Attributes.cs b/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.Attributes.cs index bee0077c2984..da3b3a45d19f 100644 --- a/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.Attributes.cs +++ b/tracer/src/Datadog.Trace.SourceGenerators/TelemetryMetric/Sources.Attributes.cs @@ -122,7 +122,7 @@ public TelemetryMetricAttribute(string metricName) /// which has a single tag /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] - internal class TelemetryMetricAttribute : System.Attribute + internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag : System.Enum { /// @@ -132,10 +132,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -145,45 +143,119 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } + } + /// + /// Used to describe a specific metric defined as a field + /// inside an enum decorated with + /// which has two tags + /// + [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] + internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + { /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } + + /// + /// Used to describe a specific metric defined as a field + /// inside an enum decorated with + /// which has two tags + /// + [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] + internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + { + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } + } + /// /// Used to describe a specific metric defined as a field /// inside an enum decorated with /// which has two tags /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] - internal class TelemetryMetricAttribute : System.Attribute + internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag1 : System.Enum where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum { /// /// Initializes a new instance of the class. @@ -192,10 +264,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -205,34 +275,112 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) + { + } + } + + /// + /// Used to describe a specific metric defined as a field + /// inside an enum decorated with + /// which has two tags + /// + [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] + internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum + { + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { } /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } + } + + /// + /// Used to describe a specific metric defined as a field + /// inside an enum decorated with + /// which has two tags + /// + [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] + internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum + where TTag6 : System.Enum + { + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } """; } diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs index e7f48e2b15c6..586d54aba6dd 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs @@ -118,7 +118,7 @@ public TelemetryMetricAttribute(string metricName) /// which has a single tag /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag : System.Enum { /// @@ -128,10 +128,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -141,34 +139,62 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } /// @@ -177,9 +203,10 @@ public TelemetryMetricAttribute(string metricName) /// which has two tags /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag1 : System.Enum where TTag2 : System.Enum + where TTag3 : System.Enum { /// /// Initializes a new instance of the class. @@ -188,10 +215,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -201,32 +226,155 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum + where TTag6 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs index e7f48e2b15c6..586d54aba6dd 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs @@ -118,7 +118,7 @@ public TelemetryMetricAttribute(string metricName) /// which has a single tag /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag : System.Enum { /// @@ -128,10 +128,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -141,34 +139,62 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } /// @@ -177,9 +203,10 @@ public TelemetryMetricAttribute(string metricName) /// which has two tags /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag1 : System.Enum where TTag2 : System.Enum + where TTag3 : System.Enum { /// /// Initializes a new instance of the class. @@ -188,10 +215,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -201,32 +226,155 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum + where TTag6 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs index e7f48e2b15c6..586d54aba6dd 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs @@ -118,7 +118,7 @@ public TelemetryMetricAttribute(string metricName) /// which has a single tag /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag : System.Enum { /// @@ -128,10 +128,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -141,34 +139,62 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } /// @@ -177,9 +203,10 @@ public TelemetryMetricAttribute(string metricName) /// which has two tags /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag1 : System.Enum where TTag2 : System.Enum + where TTag3 : System.Enum { /// /// Initializes a new instance of the class. @@ -188,10 +215,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -201,32 +226,155 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum + where TTag6 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs index e7f48e2b15c6..586d54aba6dd 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/TelemetryMetricAttribute.g.cs @@ -118,7 +118,7 @@ public TelemetryMetricAttribute(string metricName) /// which has a single tag /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag : System.Enum { /// @@ -128,10 +128,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -141,34 +139,62 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } /// @@ -177,9 +203,10 @@ public TelemetryMetricAttribute(string metricName) /// which has two tags /// [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] -internal class TelemetryMetricAttribute : System.Attribute +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute where TTag1 : System.Enum where TTag2 : System.Enum + where TTag3 : System.Enum { /// /// Initializes a new instance of the class. @@ -188,10 +215,8 @@ internal class TelemetryMetricAttribute : System.Attribute /// Is the metric a "common" metric, shared across languages? /// The namespace of the metric, if not the default (Tracer) public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) { - MetricName = metricName; - IsCommon = isCommon; - NameSpace = nameSpace; } /// @@ -201,32 +226,155 @@ public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpa /// The name of the metric, as reported to Datadog /// Is the metric a "common" metric, shared across languages? public TelemetryMetricAttribute(string metricName, bool isCommon) - : this(metricName, isCommon, null!) + : base(metricName, isCommon, null!) { } /// /// Initializes a new instance of the class. - /// Uses the default namespace and sets to true + /// Uses the default namespace and sets to true /// /// The name of the metric, as reported to Datadog public TelemetryMetricAttribute(string metricName) - : this(metricName, isCommon: true, null!) + : base(metricName, isCommon: true, null!) { } +} +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum +{ /// - /// Gets the name of the metric, as reported to Datadog + /// Initializes a new instance of the class. /// - public string MetricName { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } /// - /// Gets a value indicating whether the metric a "common" metric, shared across languages? + /// Initializes a new instance of the class. + /// Uses the default namespace /// - public bool IsCommon { get; } + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } /// - /// Gets the namespace of the metric, if not the default (Tracer) + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true /// - public string? NameSpace { get; } + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } +} + +/// +/// Used to describe a specific metric defined as a field +/// inside an enum decorated with +/// which has two tags +/// +[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)] +internal class TelemetryMetricAttribute : Datadog.Trace.SourceGenerators.TelemetryMetricAttribute + where TTag1 : System.Enum + where TTag2 : System.Enum + where TTag3 : System.Enum + where TTag4 : System.Enum + where TTag5 : System.Enum + where TTag6 : System.Enum +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + /// The namespace of the metric, if not the default (Tracer) + public TelemetryMetricAttribute(string metricName, bool isCommon, string nameSpace) + : base(metricName, isCommon, nameSpace) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace + /// + /// The name of the metric, as reported to Datadog + /// Is the metric a "common" metric, shared across languages? + public TelemetryMetricAttribute(string metricName, bool isCommon) + : base(metricName, isCommon, null!) + { + } + + /// + /// Initializes a new instance of the class. + /// Uses the default namespace and sets to true + /// + /// The name of the metric, as reported to Datadog + public TelemetryMetricAttribute(string metricName) + : base(metricName, isCommon: true, null!) + { + } } \ No newline at end of file diff --git a/tracer/test/Datadog.Trace.SourceGenerators.Tests/TelemetryMetricGeneratorTests.cs b/tracer/test/Datadog.Trace.SourceGenerators.Tests/TelemetryMetricGeneratorTests.cs index 0e3368ec04e7..65c11db30cc1 100644 --- a/tracer/test/Datadog.Trace.SourceGenerators.Tests/TelemetryMetricGeneratorTests.cs +++ b/tracer/test/Datadog.Trace.SourceGenerators.Tests/TelemetryMetricGeneratorTests.cs @@ -451,10 +451,16 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta var index = 5 + ((int)tag1 * 3) + (int)tag2; Interlocked.Add(ref _buffer.TestMetric[index], increment); } + + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int increment = 1) + { + var index = 17 + ((int)tag1 * 9) + ((int)tag2 * 3) + (int)tag3; + Interlocked.Add(ref _buffer.TestMetric[index], increment); + } public void RecordTestMetricZeroAgainTagMetric(int increment = 1) { - Interlocked.Add(ref _buffer.TestMetric[17], increment); + Interlocked.Add(ref _buffer.TestMetric[53], increment); } } """; @@ -477,6 +483,10 @@ public void RecordTestMetricOneTagMetric(MyTests.TestMetricNameSpace.LogLevel ta public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, int increment = 1) { } + + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int increment = 1) + { + } public void RecordTestMetricZeroAgainTagMetric(int increment = 1) { @@ -494,6 +504,8 @@ internal partial interface IMetricsTelemetryCollector public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, int increment = 1); + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int increment = 1); + public void RecordTestMetricZeroAgainTagMetric(int increment = 1); } """; @@ -517,6 +529,10 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta { } + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int increment = 1) + { + } + public void RecordTestMetricZeroAgainTagMetric(int increment = 1) { } @@ -745,9 +761,15 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta Interlocked.Exchange(ref _buffer.TestMetric[index], value); } + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int value) + { + var index = 17 + ((int)tag1 * 9) + ((int)tag2 * 3) + (int)tag3; + Interlocked.Exchange(ref _buffer.TestMetric[index], value); + } + public void RecordTestMetricZeroAgainTagMetric(int value) { - Interlocked.Exchange(ref _buffer.TestMetric[17], value); + Interlocked.Exchange(ref _buffer.TestMetric[53], value); } } """; @@ -771,6 +793,10 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta { } + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int value) + { + } + public void RecordTestMetricZeroAgainTagMetric(int value) { } @@ -787,6 +813,8 @@ internal partial interface IMetricsTelemetryCollector public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, int value); + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int value); + public void RecordTestMetricZeroAgainTagMetric(int value); } """; @@ -810,6 +838,10 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta { } + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, int value) + { + } + public void RecordTestMetricZeroAgainTagMetric(int value) { } @@ -1040,9 +1072,15 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta _buffer.TestMetric[index].TryEnqueue(value); } + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, double value) + { + var index = 17 + ((int)tag1 * 9) + ((int)tag2 * 3) + (int)tag3; + _buffer.TestMetric[index].TryEnqueue(value); + } + public void RecordTestMetricZeroAgainTagMetric(double value) { - _buffer.TestMetric[17].TryEnqueue(value); + _buffer.TestMetric[53].TryEnqueue(value); } } """; @@ -1066,6 +1104,10 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta { } + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, double value) + { + } + public void RecordTestMetricZeroAgainTagMetric(double value) { } @@ -1082,6 +1124,8 @@ internal partial interface IMetricsTelemetryCollector public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, double value); + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, double value); + public void RecordTestMetricZeroAgainTagMetric(double value); } """; @@ -1105,6 +1149,10 @@ public void RecordTestMetricTwoTagMetric(MyTests.TestMetricNameSpace.LogLevel ta { } + public void RecordTestMetricThreeTagMetric(MyTests.TestMetricNameSpace.LogLevel tag1, MyTests.TestMetricNameSpace.ErrorType tag2, MyTests.TestMetricNameSpace.OtherTag tag3, double value) + { + } + public void RecordTestMetricZeroAgainTagMetric(double value) { } @@ -1400,7 +1448,7 @@ internal static partial class TestMetricExtensions /// /// The number of separate metrics in the metric. /// - public const int Length = 4; + public const int Length = 5; /// /// Gets the metric name for the provided metric @@ -1413,6 +1461,7 @@ public static string GetName(this MyTests.TestMetricNameSpace.TestMetric metric) MyTests.TestMetricNameSpace.TestMetric.ZeroTagMetric => "metric.zero", MyTests.TestMetricNameSpace.TestMetric.OneTagMetric => "metric.one", MyTests.TestMetricNameSpace.TestMetric.TwoTagMetric => "metric.two", + MyTests.TestMetricNameSpace.TestMetric.ThreeTagMetric => "metric.three", MyTests.TestMetricNameSpace.TestMetric.ZeroAgainTagMetric => "metric.zeroagain", _ => null!, }; @@ -2277,7 +2326,7 @@ public static string GetTestMetricBuffers(bool isDistribution = false) { var aggregation = isDistribution ? "AggregatedDistribution" : "AggregatedMetric"; return $$""" - private const int TestMetricLength = 18; + private const int TestMetricLength = 54; /// /// Creates the buffer for the values. @@ -2305,7 +2354,44 @@ public static string GetTestMetricBuffers(bool isDistribution = false) new(new[] { "error" }), new(new[] { "error", "random" }), new(new[] { "error", "ducktyping", "othertag", "somethingelse" }), - // metric.zeroagain, index = 17 + // metric.three, index = 17 + new(new[] { "one" }), + new(new[] { "two" }), + new(new[] { "three" }), + new(new[] { "random", "one" }), + new(new[] { "random", "two" }), + new(new[] { "random", "three" }), + new(new[] { "ducktyping", "othertag", "somethingelse", "one" }), + new(new[] { "ducktyping", "othertag", "somethingelse", "two" }), + new(new[] { "ducktyping", "othertag", "somethingelse", "three" }), + new(new[] { "debug", "one" }), + new(new[] { "debug", "two" }), + new(new[] { "debug", "three" }), + new(new[] { "debug", "random", "one" }), + new(new[] { "debug", "random", "two" }), + new(new[] { "debug", "random", "three" }), + new(new[] { "debug", "ducktyping", "othertag", "somethingelse", "one" }), + new(new[] { "debug", "ducktyping", "othertag", "somethingelse", "two" }), + new(new[] { "debug", "ducktyping", "othertag", "somethingelse", "three" }), + new(new[] { "info", "one" }), + new(new[] { "info", "two" }), + new(new[] { "info", "three" }), + new(new[] { "info", "random", "one" }), + new(new[] { "info", "random", "two" }), + new(new[] { "info", "random", "three" }), + new(new[] { "info", "ducktyping", "othertag", "somethingelse", "one" }), + new(new[] { "info", "ducktyping", "othertag", "somethingelse", "two" }), + new(new[] { "info", "ducktyping", "othertag", "somethingelse", "three" }), + new(new[] { "error", "one" }), + new(new[] { "error", "two" }), + new(new[] { "error", "three" }), + new(new[] { "error", "random", "one" }), + new(new[] { "error", "random", "two" }), + new(new[] { "error", "random", "three" }), + new(new[] { "error", "ducktyping", "othertag", "somethingelse", "one" }), + new(new[] { "error", "ducktyping", "othertag", "somethingelse", "two" }), + new(new[] { "error", "ducktyping", "othertag", "somethingelse", "three" }), + // metric.zeroagain, index = 53 new(null), }; @@ -2315,7 +2401,7 @@ public static string GetTestMetricBuffers(bool isDistribution = false) /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] TestMetricEntryCounts { get; } - = new int[]{ 1, 4, 12, 1, }; + = new int[]{ 1, 4, 12, 36, 1, }; """; } @@ -2426,6 +2512,9 @@ public enum TestMetric [TelemetryMetric("metric.two")] TwoTagMetric, + [TelemetryMetric("metric.three")] + ThreeTagMetric, + [TelemetryMetric("metric.zeroagain")] ZeroAgainTagMetric, } @@ -2470,6 +2559,13 @@ public enum ErrorType [Description("random;;")] Random, [Description("ducktyping;;othertag;somethingelse")] DuckTyping, } + + public enum OtherTag + { + [Description("one")] One, + [Description("two")] Two, + [Description("three")] Three, + } """; } }