Skip to content

Commit f845134

Browse files
authored
feat!: use (and require) OpenFeature SDK v2 (#262)
Signed-off-by: Todd Baert <[email protected]>
1 parent 1f69529 commit f845134

File tree

34 files changed

+296
-422
lines changed

34 files changed

+296
-422
lines changed

Diff for: build/Common.props

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
Please sort alphabetically.
2424
Refer to https://docs.microsoft.com/nuget/concepts/package-versioning for semver syntax.
2525
-->
26-
<!-- 1.5-1.9999 -->
27-
<OpenFeatureVer>[1.5,2.0)</OpenFeatureVer>
26+
<!-- 2.0-2.9999 -->
27+
<OpenFeatureVer>[2.0,3.0)</OpenFeatureVer>
2828
</PropertyGroup>
2929

3030
<ItemGroup Condition="'$(OS)' == 'Unix'">

Diff for: src/OpenFeature.Contrib.Hooks.Otel/MetricsHook.cs

+13-46
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Diagnostics;
44
using System.Diagnostics.Metrics;
55
using System.Reflection;
6+
using System.Threading;
67
using System.Threading.Tasks;
78
using OpenFeature.Model;
89

@@ -36,17 +37,8 @@ public MetricsHook()
3637
_evaluationErrorCounter = meter.CreateCounter<long>(MetricsConstants.ErrorTotalName, description: MetricsConstants.ErrorDescription);
3738
}
3839

39-
/// <summary>
40-
/// Executes before the flag evaluation and captures metrics related to the evaluation.
41-
/// The metrics are captured in the following order:
42-
/// 1. The active count is incremented. (feature_flag.evaluation_active_count)
43-
/// 2. The request count is incremented. (feature_flag.evaluation_requests_total)
44-
/// </summary>
45-
/// <typeparam name="T">The type of the flag value.</typeparam>
46-
/// <param name="context">The hook context.</param>
47-
/// <param name="hints">The optional hints.</param>
48-
/// <returns>The evaluation context.</returns>
49-
public override Task<EvaluationContext> Before<T>(HookContext<T> context, IReadOnlyDictionary<string, object> hints = null)
40+
/// <inheritdoc/>
41+
public override ValueTask<EvaluationContext> BeforeAsync<T>(HookContext<T> context, IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
5042
{
5143
var tagList = new TagList
5244
{
@@ -57,21 +49,12 @@ public override Task<EvaluationContext> Before<T>(HookContext<T> context, IReadO
5749
_evaluationActiveUpDownCounter.Add(1, tagList);
5850
_evaluationRequestCounter.Add(1, tagList);
5951

60-
return base.Before(context, hints);
52+
return base.BeforeAsync(context, hints);
6153
}
6254

6355

64-
/// <summary>
65-
/// Executes after the flag evaluation and captures metrics related to the evaluation.
66-
/// The metrics are captured in the following order:
67-
/// 1. The success count is incremented. (feature_flag.evaluation_success_total)
68-
/// </summary>
69-
/// <typeparam name="T">The type of the flag value.</typeparam>
70-
/// <param name="context">The hook context.</param>
71-
/// <param name="details">The flag evaluation details.</param>
72-
/// <param name="hints">The optional hints.</param>
73-
/// <returns>The evaluation context.</returns>
74-
public override Task After<T>(HookContext<T> context, FlagEvaluationDetails<T> details, IReadOnlyDictionary<string, object> hints = null)
56+
/// <inheritdoc/>
57+
public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDetails<T> details, IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
7558
{
7659
var tagList = new TagList
7760
{
@@ -83,20 +66,11 @@ public override Task After<T>(HookContext<T> context, FlagEvaluationDetails<T> d
8366

8467
_evaluationSuccessCounter.Add(1, tagList);
8568

86-
return base.After(context, details, hints);
69+
return base.AfterAsync(context, details, hints);
8770
}
8871

89-
/// <summary>
90-
/// Executes when an error occurs during flag evaluation and captures metrics related to the error.
91-
/// The metrics are captured in the following order:
92-
/// 1. The error count is incremented. (feature_flag.evaluation_error_total)
93-
/// </summary>
94-
/// <typeparam name="T">The type of the flag value.</typeparam>
95-
/// <param name="context">The hook context.</param>
96-
/// <param name="error">The exception that occurred.</param>
97-
/// <param name="hints">The optional hints.</param>
98-
/// <returns>The evaluation context.</returns>
99-
public override Task Error<T>(HookContext<T> context, Exception error, IReadOnlyDictionary<string, object> hints = null)
72+
/// <inheritdoc/>
73+
public override ValueTask ErrorAsync<T>(HookContext<T> context, Exception error, IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
10074
{
10175
var tagList = new TagList
10276
{
@@ -107,18 +81,11 @@ public override Task Error<T>(HookContext<T> context, Exception error, IReadOnly
10781

10882
_evaluationErrorCounter.Add(1, tagList);
10983

110-
return base.Error(context, error, hints);
84+
return base.ErrorAsync(context, error, hints);
11185
}
11286

113-
/// <summary>
114-
/// Executes after the flag evaluation is complete and captures metrics related to the evaluation.
115-
/// The active count is decremented. (feature_flag.evaluation_active_count)
116-
/// </summary>
117-
/// <typeparam name="T">The type of the flag value.</typeparam>
118-
/// <param name="context">The hook context.</param>
119-
/// <param name="hints">The optional hints.</param>
120-
/// <returns>The evaluation context.</returns>
121-
public override Task Finally<T>(HookContext<T> context, IReadOnlyDictionary<string, object> hints = null)
87+
/// <inheritdoc/>
88+
public override ValueTask FinallyAsync<T>(HookContext<T> context, IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
12289
{
12390
var tagList = new TagList
12491
{
@@ -128,7 +95,7 @@ public override Task Finally<T>(HookContext<T> context, IReadOnlyDictionary<stri
12895

12996
_evaluationActiveUpDownCounter.Add(-1, tagList);
13097

131-
return base.Finally(context, hints);
98+
return base.FinallyAsync(context, hints);
13299
}
133100
}
134101
}

Diff for: src/OpenFeature.Contrib.Hooks.Otel/OtelHook.cs

+11-22
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Diagnostics.CodeAnalysis;
55
using System;
6+
using System.Threading;
67

78
namespace OpenFeature.Contrib.Hooks.Otel
89

@@ -16,34 +17,22 @@ public class OtelHook : Hook
1617
{
1718
private readonly TracingHook _tracingHook = new TracingHook();
1819

19-
/// <summary>
20-
/// After is executed after a feature flag has been evaluated.
21-
/// </summary>
22-
/// <param name="context">The hook context</param>
23-
/// <param name="details">The result of the feature flag evaluation</param>
24-
/// <param name="hints">Hints for the feature flag evaluation</param>
25-
/// <returns>An awaitable Task object</returns>
26-
public override Task After<T>(HookContext<T> context, FlagEvaluationDetails<T> details,
27-
IReadOnlyDictionary<string, object> hints = null)
20+
/// <inheritdoc/>
21+
public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDetails<T> details,
22+
IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
2823
{
29-
_tracingHook.After(context, details, hints);
24+
_tracingHook.AfterAsync(context, details, hints);
3025

31-
return Task.CompletedTask;
26+
return default;
3227
}
3328

34-
/// <summary>
35-
/// Error is executed when an error during a feature flag evaluation occured.
36-
/// </summary>
37-
/// <param name="context">The hook context</param>
38-
/// <param name="error">The exception thrown by feature flag provider</param>
39-
/// <param name="hints">Hints for the feature flag evaluation</param>
40-
/// <returns>An awaitable Task object</returns>
41-
public override Task Error<T>(HookContext<T> context, System.Exception error,
42-
IReadOnlyDictionary<string, object> hints = null)
29+
/// <inheritdoc/>
30+
public override ValueTask ErrorAsync<T>(HookContext<T> context, System.Exception error,
31+
IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
4332
{
44-
_tracingHook.Error(context, error, hints);
33+
_tracingHook.ErrorAsync(context, error, hints);
4534

46-
return Task.CompletedTask;
35+
return default;
4736
}
4837

4938
}

Diff for: src/OpenFeature.Contrib.Hooks.Otel/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ namespace OpenFeatureTestApp
4848

4949
var client = OpenFeature.Api.Instance.GetClient("my-app");
5050

51-
var val = client.GetBooleanValue("myBoolFlag", false, null);
51+
var val = client.GetBooleanValueAsync("myBoolFlag", false, null);
5252

5353
// Print the value of the 'myBoolFlag' feature flag
5454
System.Console.WriteLine(val.Result.ToString());
@@ -114,7 +114,7 @@ namespace OpenFeatureTestApp
114114

115115
var client = OpenFeature.Api.Instance.GetClient("my-app");
116116

117-
var val = client.GetBooleanValue("myBoolFlag", false, null);
117+
var val = client.GetBooleanValueAsync("myBoolFlag", false, null);
118118

119119
// Print the value of the 'myBoolFlag' feature flag
120120
System.Console.WriteLine(val.Result.ToString());

Diff for: src/OpenFeature.Contrib.Hooks.Otel/TracingHook.cs

+9-20
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Diagnostics;
55
using OpenTelemetry.Trace;
6+
using System.Threading;
67

78
namespace OpenFeature.Contrib.Hooks.Otel
89

@@ -13,15 +14,9 @@ namespace OpenFeature.Contrib.Hooks.Otel
1314
public class TracingHook : Hook
1415
{
1516

16-
/// <summary>
17-
/// After is executed after a feature flag has been evaluated.
18-
/// </summary>
19-
/// <param name="context">The hook context</param>
20-
/// <param name="details">The result of the feature flag evaluation</param>
21-
/// <param name="hints">Hints for the feature flag evaluation</param>
22-
/// <returns>An awaitable Task object</returns>
23-
public override Task After<T>(HookContext<T> context, FlagEvaluationDetails<T> details,
24-
IReadOnlyDictionary<string, object> hints = null)
17+
/// <inheritdoc/>
18+
public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDetails<T> details,
19+
IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
2520
{
2621
Activity.Current?
2722
.SetTag("feature_flag.key", details.FlagKey)
@@ -34,22 +29,16 @@ public override Task After<T>(HookContext<T> context, FlagEvaluationDetails<T> d
3429
["feature_flag.provider_name"] = context.ProviderMetadata.Name
3530
}));
3631

37-
return Task.CompletedTask;
32+
return default;
3833
}
3934

40-
/// <summary>
41-
/// Error is executed when an error during a feature flag evaluation occured.
42-
/// </summary>
43-
/// <param name="context">The hook context</param>
44-
/// <param name="error">The exception thrown by feature flag provider</param>
45-
/// <param name="hints">Hints for the feature flag evaluation</param>
46-
/// <returns>An awaitable Task object</returns>
47-
public override Task Error<T>(HookContext<T> context, System.Exception error,
48-
IReadOnlyDictionary<string, object> hints = null)
35+
/// <inheritdoc/>
36+
public override ValueTask ErrorAsync<T>(HookContext<T> context, System.Exception error,
37+
IReadOnlyDictionary<string, object> hints = null, CancellationToken cancellationToken = default)
4938
{
5039
Activity.Current?.RecordException(error);
5140

52-
return Task.CompletedTask;
41+
return default;
5342
}
5443

5544
}

Diff for: src/OpenFeature.Contrib.Providers.ConfigCat/ConfigCatProvider.cs

+13-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Threading;
23
using System.Threading.Tasks;
34
using ConfigCat.Client;
45
using ConfigCat.Client.Configuration;
@@ -35,34 +36,34 @@ public override Metadata GetMetadata()
3536
}
3637

3738
/// <inheritdoc/>
38-
public override Task<ResolutionDetails<bool>> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null)
39+
public override Task<ResolutionDetails<bool>> ResolveBooleanValueAsync(string flagKey, bool defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
3940
{
40-
return ResolveFlag(flagKey, context, defaultValue);
41+
return ResolveFlag(flagKey, context, defaultValue, cancellationToken);
4142
}
4243

4344
/// <inheritdoc/>
44-
public override Task<ResolutionDetails<string>> ResolveStringValue(string flagKey, string defaultValue, EvaluationContext context = null)
45+
public override Task<ResolutionDetails<string>> ResolveStringValueAsync(string flagKey, string defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
4546
{
46-
return ResolveFlag(flagKey, context, defaultValue);
47+
return ResolveFlag(flagKey, context, defaultValue, cancellationToken);
4748
}
4849

4950
/// <inheritdoc/>
50-
public override Task<ResolutionDetails<int>> ResolveIntegerValue(string flagKey, int defaultValue, EvaluationContext context = null)
51+
public override Task<ResolutionDetails<int>> ResolveIntegerValueAsync(string flagKey, int defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
5152
{
52-
return ResolveFlag(flagKey, context, defaultValue);
53+
return ResolveFlag(flagKey, context, defaultValue, cancellationToken);
5354
}
5455

5556
/// <inheritdoc/>
56-
public override Task<ResolutionDetails<double>> ResolveDoubleValue(string flagKey, double defaultValue, EvaluationContext context = null)
57+
public override Task<ResolutionDetails<double>> ResolveDoubleValueAsync(string flagKey, double defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
5758
{
58-
return ResolveFlag(flagKey, context, defaultValue);
59+
return ResolveFlag(flagKey, context, defaultValue, cancellationToken);
5960
}
6061

6162
/// <inheritdoc/>
62-
public override async Task<ResolutionDetails<Value>> ResolveStructureValue(string flagKey, Value defaultValue, EvaluationContext context = null)
63+
public override async Task<ResolutionDetails<Value>> ResolveStructureValueAsync(string flagKey, Value defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
6364
{
6465
var user = context?.BuildUser();
65-
var result = await Client.GetValueDetailsAsync(flagKey, defaultValue?.AsObject, user);
66+
var result = await Client.GetValueDetailsAsync(flagKey, defaultValue?.AsObject, user, cancellationToken);
6667
var returnValue = result.IsDefaultValue ? defaultValue : new Value(result.Value);
6768
var details = new ResolutionDetails<Value>(flagKey, returnValue, TranslateErrorCode(result.ErrorCode), errorMessage: result.ErrorMessage, variant: result.VariationId);
6869
if (details.ErrorType == ErrorType.None)
@@ -73,10 +74,10 @@ public override async Task<ResolutionDetails<Value>> ResolveStructureValue(strin
7374
throw new FeatureProviderException(details.ErrorType, details.ErrorMessage);
7475
}
7576

76-
private async Task<ResolutionDetails<T>> ResolveFlag<T>(string flagKey, EvaluationContext context, T defaultValue)
77+
private async Task<ResolutionDetails<T>> ResolveFlag<T>(string flagKey, EvaluationContext context, T defaultValue, CancellationToken cancellationToken)
7778
{
7879
var user = context?.BuildUser();
79-
var result = await Client.GetValueDetailsAsync(flagKey, defaultValue, user);
80+
var result = await Client.GetValueDetailsAsync(flagKey, defaultValue, user, cancellationToken);
8081
var details = new ResolutionDetails<T>(flagKey, result.Value, TranslateErrorCode(result.ErrorCode), errorMessage: result.ErrorMessage, variant: result.VariationId);
8182
if (details.ErrorType == ErrorType.None)
8283
{

Diff for: src/OpenFeature.Contrib.Providers.ConfigCat/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ namespace OpenFeatureTestApp
6060

6161
var client = OpenFeature.Api.Instance.GetClient();
6262

63-
var val = client.GetBooleanValue("isMyAwesomeFeatureEnabled", false);
63+
var val = client.GetBooleanValueAsync("isMyAwesomeFeatureEnabled", false);
6464

6565
if(isMyAwesomeFeatureEnabled)
6666
{

Diff for: src/OpenFeature.Contrib.Providers.FeatureManagement/FeatureManagementProvider.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public FeatureManagementProvider(IConfiguration configuration, FeatureManagement
4646
public override Metadata GetMetadata() => metadata;
4747

4848
/// <inheritdoc />
49-
public override async Task<ResolutionDetails<bool>> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null)
49+
public override async Task<ResolutionDetails<bool>> ResolveBooleanValueAsync(string flagKey, bool defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
5050
{
5151
var variant = await Evaluate(flagKey, context, CancellationToken.None);
5252

@@ -56,7 +56,7 @@ public override async Task<ResolutionDetails<bool>> ResolveBooleanValue(string f
5656
}
5757

5858
/// <inheritdoc />
59-
public override async Task<ResolutionDetails<double>> ResolveDoubleValue(string flagKey, double defaultValue, EvaluationContext context = null)
59+
public override async Task<ResolutionDetails<double>> ResolveDoubleValueAsync(string flagKey, double defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
6060
{
6161
var variant = await Evaluate(flagKey, context, CancellationToken.None);
6262

@@ -67,7 +67,7 @@ public override async Task<ResolutionDetails<double>> ResolveDoubleValue(string
6767
}
6868

6969
/// <inheritdoc />
70-
public override async Task<ResolutionDetails<int>> ResolveIntegerValue(string flagKey, int defaultValue, EvaluationContext context = null)
70+
public override async Task<ResolutionDetails<int>> ResolveIntegerValueAsync(string flagKey, int defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
7171
{
7272
var variant = await Evaluate(flagKey, context, CancellationToken.None);
7373

@@ -78,7 +78,7 @@ public override async Task<ResolutionDetails<int>> ResolveIntegerValue(string fl
7878
}
7979

8080
/// <inheritdoc />
81-
public override async Task<ResolutionDetails<string>> ResolveStringValue(string flagKey, string defaultValue, EvaluationContext context = null)
81+
public override async Task<ResolutionDetails<string>> ResolveStringValueAsync(string flagKey, string defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
8282
{
8383
var variant = await Evaluate(flagKey, context, CancellationToken.None);
8484

@@ -89,7 +89,7 @@ public override async Task<ResolutionDetails<string>> ResolveStringValue(string
8989
}
9090

9191
/// <inheritdoc />
92-
public override async Task<ResolutionDetails<Value>> ResolveStructureValue(string flagKey, Value defaultValue, EvaluationContext context = null)
92+
public override async Task<ResolutionDetails<Value>> ResolveStructureValueAsync(string flagKey, Value defaultValue, EvaluationContext context = null, CancellationToken cancellationToken = default)
9393
{
9494
var variant = await Evaluate(flagKey, context, CancellationToken.None);
9595

Diff for: src/OpenFeature.Contrib.Providers.FeatureManagement/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ namespace OpenFeatureTestApp
7070

7171
var client = OpenFeature.Api.Instance.GetClient();
7272

73-
var val = await client.GetBooleanValue("myBoolFlag", false, null);
73+
var val = await client.GetBooleanValueAsync("myBoolFlag", false, null);
7474

7575
System.Console.WriteLine(val.ToString());
7676
}

0 commit comments

Comments
 (0)