-
Notifications
You must be signed in to change notification settings - Fork 21
feat: Move OTEL hooks to the SDK #338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 20 commits
Commits
Show all changes
53 commits
Select commit
Hold shift + click to select a range
e7d40c7
Added metrics hook.
askpt 46e5711
Adding the traces hook.
askpt ced2d34
Adding Metrics Hook tests.
askpt 633859c
Adding tracing hook tests.
askpt 6d4378f
Fix typos.
askpt 8a32ca9
Simplify code.
askpt 629b900
Cleanup tracing hook tests.
askpt 766caa5
More test cleanup.
askpt 703f418
Cleanup tests.
askpt 729bd65
Adding empty span.
askpt 7f5af18
Adding .ConfigureAwait
askpt c0b6cc0
Fix dotnet format.
askpt d0157ae
Removed comma
askpt 902a102
Adding README information.
askpt 60813c5
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 6a3d911
Using the new API.
askpt 52b47da
Fix subscribed Meter.
askpt 8e1e884
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 1a0c16d
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 41c915d
Fix breaking change.
askpt 4bf70d2
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 7b6ef96
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 066706d
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 5cfb99b
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt a39ebbd
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 415de4d
feat: add System.Diagnostics.DiagnosticSource package reference and u…
askpt 4a3bacf
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt dd86dd5
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 94a1fcb
refactor: Replace MetricsConstants with TelemetryConstants in Metrics…
askpt a8789f4
refactor: Enhance documentation for TracingHook methods and clarify e…
askpt d34ede3
fix: Update return statements in TracingHook to call base methods for…
askpt 345a164
fix: Correct documentation and update tag keys in TracingHook tests f…
askpt bc38b0c
refactor: Optimize Meter initialization in MetricsHook constructor fo…
askpt cd9811e
fix: Correct indentation in README.md for OpenTelemetry OTLP exporter…
askpt ed68e95
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt fe05709
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 3309850
chore: remove unused usings from hook files
askpt 904fd44
chore: remove variant assignment from MetricsHook
askpt 0200319
feat: add additional tags for flag evaluation details in TracingHook
askpt ed543dd
feat: add value and reason tags to telemetry in TracingHook
askpt 5309232
fix: update remarks for MetricsHook and TracingHook to clarify experi…
askpt 4359a37
refactor: rename AfterAsync to FinallyAsync in TracingHook and update…
askpt 8038a69
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt d3cf9d2
feat: add TraceEnricherHook and corresponding tests for telemetry tra…
askpt b8b3436
refactor: remove ErrorAsync method from TraceEnricherHook to streamli…
askpt 46fcf38
refactor: update event name in TraceEnricherHook and remove unused Tr…
askpt cc5fde8
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt 4a3d3bc
refactor: streamline event tagging in TraceEnricherHook by using Eval…
askpt fea94e9
refactor: update event name and enhance assertions in TraceEnricherHo…
askpt 78044d1
refactor: rename variable for clarity in TraceEnricherHookTests
askpt 1a7f62a
docs: improve README formatting and enhance Trace Enricher Hook descr…
askpt a0319e4
feat: integrate OpenTelemetry for tracing and metrics in ASP.NET Core…
askpt 2b4306a
Merge branch 'main' into askpt/175-promote-otel-hooks
askpt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
namespace OpenFeature.Hooks; | ||
|
||
internal static class MetricsConstants | ||
{ | ||
internal const string ActiveCountName = "feature_flag.evaluation_active_count"; | ||
internal const string RequestsTotalName = "feature_flag.evaluation_requests_total"; | ||
internal const string SuccessTotalName = "feature_flag.evaluation_success_total"; | ||
internal const string ErrorTotalName = "feature_flag.evaluation_error_total"; | ||
|
||
internal const string ActiveDescription = "active flag evaluations counter"; | ||
internal const string RequestsDescription = "feature flag evaluation request counter"; | ||
internal const string SuccessDescription = "feature flag evaluation success counter"; | ||
internal const string ErrorDescription = "feature flag evaluation error counter"; | ||
|
||
internal const string KeyAttr = "key"; | ||
internal const string ProviderNameAttr = "provider_name"; | ||
internal const string VariantAttr = "variant"; | ||
internal const string ReasonAttr = "reason"; | ||
internal const string ExceptionAttr = "exception"; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Diagnostics.Metrics; | ||
using System.Reflection; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using OpenFeature.Model; | ||
|
||
namespace OpenFeature.Hooks; | ||
|
||
/// <summary> | ||
/// Represents a hook for capturing metrics related to flag evaluations. | ||
beeme1mr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// The meter instrumentation name is "OpenFeature". | ||
/// </summary> | ||
public class MetricsHook : Hook | ||
{ | ||
private static readonly AssemblyName AssemblyName = typeof(MetricsHook).Assembly.GetName(); | ||
private static readonly string InstrumentationName = AssemblyName.Name ?? "OpenFeature"; | ||
private static readonly string InstrumentationVersion = AssemblyName.Version?.ToString() ?? "1.0.0"; | ||
|
||
private readonly UpDownCounter<long> _evaluationActiveUpDownCounter; | ||
private readonly Counter<long> _evaluationRequestCounter; | ||
private readonly Counter<long> _evaluationSuccessCounter; | ||
private readonly Counter<long> _evaluationErrorCounter; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="MetricsHook"/> class. | ||
/// </summary> | ||
public MetricsHook() | ||
{ | ||
var meter = new Meter(InstrumentationName, InstrumentationVersion); | ||
kylejuliandev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
this._evaluationActiveUpDownCounter = meter.CreateUpDownCounter<long>(MetricsConstants.ActiveCountName, description: MetricsConstants.ActiveDescription); | ||
this._evaluationRequestCounter = meter.CreateCounter<long>(MetricsConstants.RequestsTotalName, "{request}", MetricsConstants.RequestsDescription); | ||
this._evaluationSuccessCounter = meter.CreateCounter<long>(MetricsConstants.SuccessTotalName, "{impression}", MetricsConstants.SuccessDescription); | ||
this._evaluationErrorCounter = meter.CreateCounter<long>(MetricsConstants.ErrorTotalName, description: MetricsConstants.ErrorDescription); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override ValueTask<EvaluationContext> BeforeAsync<T>(HookContext<T> context, IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default) | ||
{ | ||
var tagList = new TagList | ||
{ | ||
{ MetricsConstants.KeyAttr, context.FlagKey }, | ||
{ MetricsConstants.ProviderNameAttr, context.ProviderMetadata.Name } | ||
}; | ||
|
||
this._evaluationActiveUpDownCounter.Add(1, tagList); | ||
this._evaluationRequestCounter.Add(1, tagList); | ||
|
||
return base.BeforeAsync(context, hints, cancellationToken); | ||
} | ||
|
||
|
||
/// <inheritdoc/> | ||
public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDetails<T> details, IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default) | ||
{ | ||
var tagList = new TagList | ||
{ | ||
{ MetricsConstants.KeyAttr, context.FlagKey }, | ||
{ MetricsConstants.ProviderNameAttr, context.ProviderMetadata.Name }, | ||
{ MetricsConstants.VariantAttr, details.Variant ?? details.Value?.ToString() }, | ||
{ MetricsConstants.ReasonAttr, details.Reason ?? "UNKNOWN" } | ||
}; | ||
|
||
this._evaluationSuccessCounter.Add(1, tagList); | ||
|
||
return base.AfterAsync(context, details, hints, cancellationToken); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override ValueTask ErrorAsync<T>(HookContext<T> context, Exception error, IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default) | ||
{ | ||
var tagList = new TagList | ||
{ | ||
{ MetricsConstants.KeyAttr, context.FlagKey }, | ||
{ MetricsConstants.ProviderNameAttr, context.ProviderMetadata.Name }, | ||
{ MetricsConstants.ExceptionAttr, error.Message } | ||
}; | ||
|
||
this._evaluationErrorCounter.Add(1, tagList); | ||
|
||
return base.ErrorAsync(context, error, hints, cancellationToken); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override ValueTask FinallyAsync<T>(HookContext<T> context, | ||
FlagEvaluationDetails<T> evaluationDetails, | ||
IReadOnlyDictionary<string, object>? hints = null, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
var tagList = new TagList | ||
{ | ||
{ MetricsConstants.KeyAttr, context.FlagKey }, | ||
{ MetricsConstants.ProviderNameAttr, context.ProviderMetadata.Name } | ||
}; | ||
|
||
this._evaluationActiveUpDownCounter.Add(-1, tagList); | ||
|
||
return base.FinallyAsync(context, evaluationDetails, hints, cancellationToken); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace OpenFeature.Hooks; | ||
|
||
internal static class TracingConstants | ||
{ | ||
internal const string AttributeExceptionEventName = "exception"; | ||
internal const string AttributeExceptionType = "exception.type"; | ||
internal const string AttributeExceptionMessage = "exception.message"; | ||
internal const string AttributeExceptionStacktrace = "exception.stacktrace"; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using OpenFeature.Model; | ||
|
||
namespace OpenFeature.Hooks; | ||
|
||
/// <summary> | ||
/// Stub. | ||
kinyoklion marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// </summary> | ||
public class TracingHook : Hook | ||
{ | ||
/// <inheritdoc/> | ||
public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDetails<T> details, | ||
beeme1mr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default) | ||
{ | ||
Activity.Current? | ||
.SetTag("feature_flag.key", details.FlagKey) | ||
.SetTag("feature_flag.variant", details.Variant) | ||
.SetTag("feature_flag.provider_name", context.ProviderMetadata.Name) | ||
.AddEvent(new ActivityEvent("feature_flag", tags: new ActivityTagsCollection | ||
{ | ||
["feature_flag.key"] = details.FlagKey, | ||
["feature_flag.variant"] = details.Variant, | ||
["feature_flag.provider_name"] = context.ProviderMetadata.Name | ||
})); | ||
|
||
return default; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override ValueTask ErrorAsync<T>(HookContext<T> context, System.Exception error, | ||
IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default) | ||
{ | ||
#if NET9_0_OR_GREATER | ||
// For dotnet9 we should use the new API https://learn.microsoft.com/en-gb/dotnet/api/system.diagnostics.activity.addexception?view=net-9.0 | ||
Activity.Current?.AddException(error); | ||
#else | ||
var tagsCollection = new ActivityTagsCollection | ||
{ | ||
{ TracingConstants.AttributeExceptionType, error.GetType().FullName }, | ||
{ TracingConstants.AttributeExceptionStacktrace, error.ToString() }, | ||
}; | ||
if (!string.IsNullOrWhiteSpace(error.Message)) | ||
{ | ||
tagsCollection.Add(TracingConstants.AttributeExceptionMessage, error.Message); | ||
} | ||
|
||
Activity.Current?.AddEvent(new ActivityEvent(TracingConstants.AttributeExceptionEventName, default, tagsCollection)); | ||
#endif | ||
return default; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.