Skip to content

Commit 2f088aa

Browse files
Add variant allocation and flag telemetry information to request tracing (#540)
* WIP create featurevariantstracing class * WIP class structure * add first working draft, combine tracing for fm and add allocation/telemetry * remove unused string * fix naming, add variant present tag * change constants names * update highest variants key and usesSeed tag * variant configuration suggestion * change variant config info to tag for ref only * reformatting tracing * add method for new features key in request tracing * fix tracing reference * PR comments * adjust features to have flag/other features lists * remove features key * Update src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs Co-authored-by: Avani Gupta <avanigupta@users.noreply.github.com> * rename variables and methods --------- Co-authored-by: Avani Gupta <avanigupta@users.noreply.github.com>
1 parent 8a00750 commit 2f088aa

File tree

7 files changed

+99
-22
lines changed

7 files changed

+99
-22
lines changed

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ internal IEnumerable<IKeyValueAdapter> Adapters
124124
/// <summary>
125125
/// Indicates all types of feature filters used by the application.
126126
/// </summary>
127-
internal FeatureFilterTracing FeatureFilterTracing { get; set; } = new FeatureFilterTracing();
127+
internal FeatureFlagTracing FeatureFlagTracing { get; set; } = new FeatureFlagTracing();
128128

129129
/// <summary>
130130
/// Options used to configure provider startup.
@@ -140,7 +140,7 @@ public AzureAppConfigurationOptions()
140140
{
141141
new AzureKeyVaultKeyValueAdapter(new AzureKeyVaultSecretProvider()),
142142
new JsonKeyValueAdapter(),
143-
new FeatureManagementKeyValueAdapter(FeatureFilterTracing)
143+
new FeatureManagementKeyValueAdapter(FeatureFlagTracing)
144144
};
145145
}
146146

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -560,8 +560,8 @@ private async Task<Dictionary<string, string>> PrepareData(Dictionary<string, Co
560560
{
561561
var applicationData = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
562562

563-
// Reset old filter tracing in order to track the filter types present in the current response from server.
564-
_options.FeatureFilterTracing.ResetFeatureFilterTracing();
563+
// Reset old feature flag tracing in order to track the information present in the current response from server.
564+
_options.FeatureFlagTracing.ResetFeatureFlagTracing();
565565

566566
foreach (KeyValuePair<string, ConfigurationSetting> kvp in data)
567567
{
@@ -968,7 +968,7 @@ private void SetRequestTracingOptions()
968968
IsKeyVaultConfigured = _options.IsKeyVaultConfigured,
969969
IsKeyVaultRefreshConfigured = _options.IsKeyVaultRefreshConfigured,
970970
ReplicaCount = _options.Endpoints?.Count() - 1 ?? _options.ConnectionStrings?.Count() - 1 ?? 0,
971-
FilterTracing = _options.FeatureFilterTracing
971+
FeatureFlagTracing = _options.FeatureFlagTracing
972972
};
973973
}
974974

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,19 @@ internal class RequestTracingConstants
3030
public const string KeyVaultConfiguredTag = "UsesKeyVault";
3131
public const string KeyVaultRefreshConfiguredTag = "RefreshesKeyVault";
3232
public const string ReplicaCountKey = "ReplicaCount";
33+
public const string FeatureFlagUsesTelemetryTag = "Telemetry";
34+
public const string FeatureFlagUsesSeedTag = "Seed";
35+
public const string FeatureFlagMaxVariantsKey = "MaxVariants";
36+
public const string FeatureFlagUsesVariantConfigurationReferenceTag = "ConfigRef";
37+
public const string FeatureFlagFeaturesKey = "FFFeatures";
3338

3439
public const string DiagnosticHeaderActivityName = "Azure.CustomDiagnosticHeaders";
3540
public const string CorrelationContextHeader = "Correlation-Context";
3641
public const string UserAgentHeader = "User-Agent";
3742

3843
public const string FeatureManagementAssemblyName = "Microsoft.FeatureManagement";
3944
public const string FeatureManagementAspNetCoreAssemblyName = "Microsoft.FeatureManagement.AspNetCore";
45+
46+
public const string Delimiter = "+";
4047
}
4148
}
Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.FeatureManage
1212
/// <summary>
1313
/// Tracing for tracking built-in feature filter usage.
1414
/// </summary>
15-
internal class FeatureFilterTracing
15+
internal class FeatureFlagTracing
1616
{
1717
private const string CustomFilter = "CSTM";
1818
private const string PercentageFilter = "PRCNT";
1919
private const string TimeWindowFilter = "TIME";
2020
private const string TargetingFilter = "TRGT";
21-
private const string FilterTypeDelimiter = "+";
2221

2322
// Built-in Feature Filter Names
2423
private readonly List<string> PercentageFilterNames = new List<string> { "Percentage", "Microsoft.Percentage", "PercentageFilter", "Microsoft.PercentageFilter" };
@@ -29,18 +28,31 @@ internal class FeatureFilterTracing
2928
public bool UsesPercentageFilter { get; set; } = false;
3029
public bool UsesTimeWindowFilter { get; set; } = false;
3130
public bool UsesTargetingFilter { get; set; } = false;
32-
31+
public bool UsesSeed { get; set; } = false;
32+
public bool UsesTelemetry { get; set; } = false;
33+
public bool UsesVariantConfigurationReference { get; set; } = false;
34+
public int MaxVariants { get; set; }
35+
3336
public bool UsesAnyFeatureFilter()
3437
{
3538
return UsesCustomFilter || UsesPercentageFilter || UsesTimeWindowFilter || UsesTargetingFilter;
3639
}
3740

38-
public void ResetFeatureFilterTracing()
41+
public bool UsesAnyTracingFeature()
42+
{
43+
return UsesSeed || UsesTelemetry || UsesVariantConfigurationReference;
44+
}
45+
46+
public void ResetFeatureFlagTracing()
3947
{
4048
UsesCustomFilter = false;
4149
UsesPercentageFilter = false;
4250
UsesTimeWindowFilter = false;
4351
UsesTargetingFilter = false;
52+
UsesSeed = false;
53+
UsesTelemetry = false;
54+
UsesVariantConfigurationReference = false;
55+
MaxVariants = 0;
4456
}
4557

4658
public void UpdateFeatureFilterTracing(string filterName)
@@ -63,11 +75,19 @@ public void UpdateFeatureFilterTracing(string filterName)
6375
}
6476
}
6577

78+
public void NotifyMaxVariants(int currentFlagTotalVariants)
79+
{
80+
if (currentFlagTotalVariants > MaxVariants)
81+
{
82+
MaxVariants = currentFlagTotalVariants;
83+
}
84+
}
85+
6686
/// <summary>
6787
/// Returns a formatted string containing code names, indicating which feature filters are used by the application.
6888
/// </summary>
6989
/// <returns>Formatted string like: "CSTM+PRCNT+TIME+TRGT", "PRCNT+TRGT", etc. If no filters are used, empty string will be returned.</returns>
70-
public override string ToString()
90+
public string CreateFiltersString()
7191
{
7292
if (!UsesAnyFeatureFilter())
7393
{
@@ -85,7 +105,7 @@ public override string ToString()
85105
{
86106
if (sb.Length > 0)
87107
{
88-
sb.Append(FilterTypeDelimiter);
108+
sb.Append(RequestTracingConstants.Delimiter);
89109
}
90110

91111
sb.Append(PercentageFilter);
@@ -95,7 +115,7 @@ public override string ToString()
95115
{
96116
if (sb.Length > 0)
97117
{
98-
sb.Append(FilterTypeDelimiter);
118+
sb.Append(RequestTracingConstants.Delimiter);
99119
}
100120

101121
sb.Append(TimeWindowFilter);
@@ -105,13 +125,45 @@ public override string ToString()
105125
{
106126
if (sb.Length > 0)
107127
{
108-
sb.Append(FilterTypeDelimiter);
128+
sb.Append(RequestTracingConstants.Delimiter);
109129
}
110130

111131
sb.Append(TargetingFilter);
112132
}
113133

114134
return sb.ToString();
115135
}
136+
137+
public string CreateFeaturesString()
138+
{
139+
var sb = new StringBuilder();
140+
141+
if (UsesSeed)
142+
{
143+
sb.Append(RequestTracingConstants.FeatureFlagUsesSeedTag);
144+
}
145+
146+
if (UsesVariantConfigurationReference)
147+
{
148+
if (sb.Length > 0)
149+
{
150+
sb.Append(RequestTracingConstants.Delimiter);
151+
}
152+
153+
sb.Append(RequestTracingConstants.FeatureFlagUsesVariantConfigurationReferenceTag);
154+
}
155+
156+
if (UsesTelemetry)
157+
{
158+
if (sb.Length > 0)
159+
{
160+
sb.Append(RequestTracingConstants.Delimiter);
161+
}
162+
163+
sb.Append(RequestTracingConstants.FeatureFlagUsesTelemetryTag);
164+
}
165+
166+
return sb.ToString();
167+
}
116168
}
117169
}

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.FeatureManage
1616
{
1717
internal class FeatureManagementKeyValueAdapter : IKeyValueAdapter
1818
{
19-
private FeatureFilterTracing _featureFilterTracing;
19+
private FeatureFlagTracing _featureFlagTracing;
2020
private int _featureFlagIndex = 0;
2121

22-
public FeatureManagementKeyValueAdapter(FeatureFilterTracing featureFilterTracing)
22+
public FeatureManagementKeyValueAdapter(FeatureFlagTracing featureFlagTracing)
2323
{
24-
_featureFilterTracing = featureFilterTracing ?? throw new ArgumentNullException(nameof(featureFilterTracing));
24+
_featureFlagTracing = featureFlagTracing ?? throw new ArgumentNullException(nameof(featureFlagTracing));
2525
}
2626

2727
public Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(ConfigurationSetting setting, Uri endpoint, Logger logger, CancellationToken cancellationToken)
@@ -91,7 +91,7 @@ private List<KeyValuePair<string, string>> ProcessDotnetSchemaFeatureFlag(Featur
9191
{
9292
ClientFilter clientFilter = featureFlag.Conditions.ClientFilters[i];
9393

94-
_featureFilterTracing.UpdateFeatureFilterTracing(clientFilter.Name);
94+
_featureFlagTracing.UpdateFeatureFilterTracing(clientFilter.Name);
9595

9696
string clientFiltersPath = $"{featureFlagPath}:{FeatureManagementConstants.DotnetSchemaEnabledFor}:{i}";
9797

@@ -148,7 +148,7 @@ private List<KeyValuePair<string, string>> ProcessMicrosoftSchemaFeatureFlag(Fea
148148
{
149149
ClientFilter clientFilter = featureFlag.Conditions.ClientFilters[i];
150150

151-
_featureFilterTracing.UpdateFeatureFilterTracing(clientFilter.Name);
151+
_featureFlagTracing.UpdateFeatureFilterTracing(clientFilter.Name);
152152

153153
string clientFiltersPath = $"{featureFlagPath}:{FeatureManagementConstants.Conditions}:{FeatureManagementConstants.ClientFilters}:{i}";
154154

@@ -189,6 +189,8 @@ private List<KeyValuePair<string, string>> ProcessMicrosoftSchemaFeatureFlag(Fea
189189

190190
if (featureVariant.ConfigurationReference != null)
191191
{
192+
_featureFlagTracing.UsesVariantConfigurationReference = true;
193+
192194
keyValues.Add(new KeyValuePair<string, string>($"{variantsPath}:{FeatureManagementConstants.ConfigurationReference}", featureVariant.ConfigurationReference));
193195
}
194196

@@ -199,6 +201,8 @@ private List<KeyValuePair<string, string>> ProcessMicrosoftSchemaFeatureFlag(Fea
199201

200202
i++;
201203
}
204+
205+
_featureFlagTracing.NotifyMaxVariants(i);
202206
}
203207

204208
if (featureFlag.Allocation != null)
@@ -277,6 +281,8 @@ private List<KeyValuePair<string, string>> ProcessMicrosoftSchemaFeatureFlag(Fea
277281

278282
if (allocation.Seed != null)
279283
{
284+
_featureFlagTracing.UsesSeed = true;
285+
280286
keyValues.Add(new KeyValuePair<string, string>($"{allocationPath}:{FeatureManagementConstants.Seed}", allocation.Seed));
281287
}
282288
}
@@ -289,6 +295,8 @@ private List<KeyValuePair<string, string>> ProcessMicrosoftSchemaFeatureFlag(Fea
289295

290296
if (telemetry.Enabled)
291297
{
298+
_featureFlagTracing.UsesTelemetry = true;
299+
292300
if (telemetry.Metadata != null)
293301
{
294302
foreach (KeyValuePair<string, string> kvp in telemetry.Metadata)

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/RequestTracingOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ internal class RequestTracingOptions
3333
public int ReplicaCount { get; set; } = 0;
3434

3535
/// <summary>
36-
/// Type of feature filters used by the application.
36+
/// Information about feature flags in the application, like filter and variant usage.
3737
/// </summary>
38-
public FeatureFilterTracing FilterTracing { get; set; } = new FeatureFilterTracing();
38+
public FeatureFlagTracing FeatureFlagTracing { get; set; } = new FeatureFlagTracing();
3939

4040
/// <summary>
4141
/// Version of the Microsoft.FeatureManagement assembly, if present in the application.

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,19 @@ private static string CreateCorrelationContextHeader(RequestType requestType, Re
156156
correlationContextKeyValues.Add(new KeyValuePair<string, string>(RequestTracingConstants.EnvironmentKey, RequestTracingConstants.DevEnvironmentValue));
157157
}
158158

159-
if (requestTracingOptions.FilterTracing.UsesAnyFeatureFilter())
159+
if (requestTracingOptions.FeatureFlagTracing.UsesAnyFeatureFilter())
160160
{
161-
correlationContextKeyValues.Add(new KeyValuePair<string, string>(RequestTracingConstants.FilterTypeKey, requestTracingOptions.FilterTracing.ToString()));
161+
correlationContextKeyValues.Add(new KeyValuePair<string, string>(RequestTracingConstants.FilterTypeKey, requestTracingOptions.FeatureFlagTracing.CreateFiltersString()));
162+
}
163+
164+
if (requestTracingOptions.FeatureFlagTracing.MaxVariants > 0)
165+
{
166+
correlationContextKeyValues.Add(new KeyValuePair<string, string>(RequestTracingConstants.FeatureFlagMaxVariantsKey, requestTracingOptions.FeatureFlagTracing.MaxVariants.ToString()));
167+
}
168+
169+
if (requestTracingOptions.FeatureFlagTracing.UsesAnyTracingFeature())
170+
{
171+
correlationContextKeyValues.Add(new KeyValuePair<string, string>(RequestTracingConstants.FeatureFlagFeaturesKey, requestTracingOptions.FeatureFlagTracing.CreateFeaturesString()));
162172
}
163173

164174
if (requestTracingOptions.FeatureManagementVersion != null)

0 commit comments

Comments
 (0)