feat: Add trace when evaluating feature flags#755
Conversation
Signed-off-by: Kyle Julian <[email protected]>
Signed-off-by: Kyle Julian <[email protected]>
Signed-off-by: Kyle Julian <[email protected]>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #755 +/- ##
==========================================
+ Coverage 93.47% 93.63% +0.16%
==========================================
Files 68 70 +2
Lines 2956 3050 +94
Branches 351 368 +17
==========================================
+ Hits 2763 2856 +93
Misses 135 135
- Partials 58 59 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review
This pull request implements OpenTelemetry tracing for feature flag evaluations in the OpenFeature client, including the addition of an activity source and corresponding unit tests. The review feedback highlights several discrepancies with OpenTelemetry Semantic Conventions, suggesting the use of standard attribute names (e.g., 'feature_flag.provider_name', 'feature_flag.evaluation_reason', 'feature_flag.evaluation_value', 'feature_flag.variant') and recommending that span statuses be explicitly set to 'Error' when failures occur to improve telemetry accuracy.
Signed-off-by: Kyle Julian <[email protected]>
Signed-off-by: Kyle Julian <[email protected]>
Signed-off-by: Kyle Julian <[email protected]>
Signed-off-by: Kyle Julian <[email protected]>
askpt
left a comment
There was a problem hiding this comment.
LGTM! I expect this change to be mentioned in a README since the consumer might need to add extra configuration to remove or add these traces.
cc: @beeme1mr, @open-feature/technical-steering-committee, @WeihanLi, @arttonoyan
| static string GetLibraryVersion() | ||
| => typeof(OpenFeatureActivitySource).Assembly | ||
| .GetCustomAttribute<AssemblyInformationalVersionAttribute>()? | ||
| .InformationalVersion ?? "UNKNOWN"; |
There was a problem hiding this comment.
Could you please remove the +<sha> in the version. You can see it in the screenshots you posted.
Also I wonder if we should "cache" the version string somewhere to prevent doing GetCustomAttribute all the time.
There was a problem hiding this comment.
The ActivitySource is static, so it's initialized once during the first flag evaluation and then subsequent evaluations don't fetch a new version
There was a problem hiding this comment.
I've opted to use AssemblyVersion instead of the InformationalVersion in 3b8eac5
In Common.prod.props we set the Assembly version
dotnet-sdk/build/Common.prod.props
Lines 22 to 24 in b3fa7f4
I do a ToString on the Version, so we get major.minor.patch in the trace:
| var resolveValueDelegate = providerInfo.Item1; | ||
| var provider = providerInfo.Item2; | ||
|
|
||
| var activity = OpenFeatureActivitySource.StartActivity("feature_flag.evaluation"); |
There was a problem hiding this comment.
Wonder if we should set it as Client. See: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.activitykind?view=net-10.0
There was a problem hiding this comment.
Wonder if we should set it as Client
personally think it's fine to keep it using default Internal
There was a problem hiding this comment.
I think if the Provider (InMemory, Flagd, etc..) traces, they may opt to use Client in this example. I figured here at this point we don't necessarily know if the flag evaluation is remote. But we are confident we are delegating the actual evaluation to another component that is running in the same process
| var resolveValueDelegate = providerInfo.Item1; | ||
| var provider = providerInfo.Item2; | ||
|
|
||
| var activity = OpenFeatureActivitySource.StartActivity("feature_flag.evaluation"); |
There was a problem hiding this comment.
| var activity = OpenFeatureActivitySource.StartActivity("feature_flag.evaluation"); | |
| using var activity = OpenFeatureActivitySource.StartActivity("feature_flag.evaluation"); |
maybe we could add using for this
There was a problem hiding this comment.
Great spot, this was probably leaving activity sources undisposed of (potentially leaving resources hanging). Fixed in 3b8eac5
| var provider = providerInfo.Item2; | ||
|
|
||
| var activity = OpenFeatureActivitySource.StartActivity("feature_flag.evaluation"); | ||
| activity?.SetTag("feature_flag.key", flagKey); |
There was a problem hiding this comment.
for the SetTag/SetStatus, think we could add tags in one place and add tags only when IsAllDataRequested
There was a problem hiding this comment.
Fixed in 6e943fa - this was a great spot! It helps avoid allocations in high performance scenarios
I wonder if we should add feature_flag.provider.name in all instances or only when IsAllDataRequested is true
|
maybe we want to deprecate the |
| var providerMetadata = provider.GetMetadata(); | ||
| if (providerMetadata != null) | ||
| { | ||
| activity?.SetTag("feature_flag.provider.name", providerMetadata.Name); |
There was a problem hiding this comment.
Would we like to keep these tagName/activityName to be constants in a separated place?
There was a problem hiding this comment.
Fixed in 6e943fa - moved the tag names (apart from error.type) to the OpenFeatureActivitySource class
| .ConfigureResource(resource => resource.AddService("openfeature-aspnetcore-sample")) | ||
| .WithTracing(tracing => tracing | ||
| .AddAspNetCoreInstrumentation() | ||
| .SetSampler(new AlwaysOnSampler()) |
There was a problem hiding this comment.
Maybe we should add AddSource("OpenFeature") to collect OpenFeature activity?
* Ensure OpenFeature traces are recorded in sample app * Ensure ActivitySource is disposed of Signed-off-by: Kyle Julian <[email protected]>
* Add check on IsAllDataRequested to save on allocations on the activity span Signed-off-by: Kyle Julian <[email protected]>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces OpenTelemetry instrumentation to the OpenFeature .NET SDK by adding a new OpenFeatureActivitySource and integrating activity tracking into the OpenFeatureClient evaluation logic. The changes include mapping evaluation results and errors to standard semantic conventions and adding comprehensive tests. Review feedback suggests aligning specific attribute names with OpenTelemetry standards (specifically provider_name and variant), normalizing reason strings to lowercase, and removing a redundant Dispose() call on an activity already managed by a using statement.
Signed-off-by: Kyle Julian <[email protected]>
This PR
Add trace when evaluating feature flags. This is different from the
TraceEnricherHookwhich enriches the current span or trace with an event, instead this more closely follows the semantic conventions: https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-events/. Also add OpenTelemetry logging to the sample application and ensure traces are always sampled.Success tracwe
Error trace
Related Issues
Fixes #595
Fixes #541
Notes
Follow-up Tasks
How to test