Skip to content

Commit eb97dc7

Browse files
feat: Add SDK id and version to requests (#66)
Signed-off-by: Fabrizio Demaria <[email protected]>
1 parent 77ecd7d commit eb97dc7

File tree

5 files changed

+83
-11
lines changed

5 files changed

+83
-11
lines changed

pom.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@
176176
</extension>
177177
</extensions>
178178
<resources>
179-
<resource><directory>src/main/resources</directory></resource>
179+
<resource>
180+
<directory>src/main/resources</directory>
181+
<filtering>true</filtering>
182+
</resource>
180183
<resource><directory>src/main/proto</directory></resource>
181184
</resources>
182185
<plugins>

src/main/java/com/spotify/confidence/ConfidenceFeatureProvider.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import com.spotify.confidence.flags.resolver.v1.ResolveFlagsRequest;
99
import com.spotify.confidence.flags.resolver.v1.ResolveFlagsResponse;
1010
import com.spotify.confidence.flags.resolver.v1.ResolvedFlag;
11+
import com.spotify.confidence.flags.resolver.v1.Sdk;
12+
import com.spotify.confidence.flags.resolver.v1.SdkId;
1113
import dev.openfeature.sdk.EvaluationContext;
1214
import dev.openfeature.sdk.FeatureProvider;
1315
import dev.openfeature.sdk.Metadata;
@@ -19,13 +21,14 @@
1921
import dev.openfeature.sdk.exceptions.InvalidContextError;
2022
import dev.openfeature.sdk.exceptions.TargetingKeyMissingError;
2123
import dev.openfeature.sdk.exceptions.TypeMismatchError;
22-
import io.grpc.ManagedChannel;
2324
import io.grpc.ManagedChannelBuilder;
2425
import io.grpc.Status.Code;
2526
import io.grpc.StatusRuntimeException;
2627
import io.grpc.netty.shaded.io.netty.util.internal.StringUtil;
28+
import java.io.IOException;
2729
import java.util.Arrays;
2830
import java.util.List;
31+
import java.util.Properties;
2932
import java.util.concurrent.TimeUnit;
3033
import java.util.function.Function;
3134
import java.util.regex.Pattern;
@@ -38,6 +41,9 @@ public class ConfidenceFeatureProvider implements FeatureProvider {
3841
private final FlagResolverServiceBlockingStub stub;
3942
private final String clientSecret;
4043

44+
private final String SDK_VERSION;
45+
private static final SdkId SDK_ID = SdkId.SDK_ID_JAVA_PROVIDER;
46+
4147
static final String TARGETING_KEY = "targeting_key";
4248

4349
/**
@@ -49,6 +55,18 @@ public class ConfidenceFeatureProvider implements FeatureProvider {
4955
public ConfidenceFeatureProvider(String clientSecret, FlagResolverServiceBlockingStub stub) {
5056
this.clientSecret = clientSecret;
5157
this.stub = stub;
58+
59+
if (Strings.isNullOrEmpty(clientSecret)) {
60+
throw new IllegalArgumentException("clientSecret must be a non-empty string.");
61+
}
62+
63+
try {
64+
final Properties prop = new Properties();
65+
prop.load(this.getClass().getResourceAsStream("/version.properties"));
66+
this.SDK_VERSION = prop.getProperty("version");
67+
} catch (IOException e) {
68+
throw new RuntimeException("Can't determine version of the SDK", e);
69+
}
5270
}
5371

5472
/**
@@ -57,14 +75,10 @@ public ConfidenceFeatureProvider(String clientSecret, FlagResolverServiceBlockin
5775
* @param clientSecret generated from Confidence
5876
*/
5977
public ConfidenceFeatureProvider(String clientSecret) {
60-
final ManagedChannel channel =
61-
ManagedChannelBuilder.forAddress("edge-grpc.spotify.com", 443).build();
62-
this.stub = FlagResolverServiceGrpc.newBlockingStub(channel);
63-
64-
if (Strings.isNullOrEmpty(clientSecret)) {
65-
throw new IllegalArgumentException("clientSecret must be a non-empty string.");
66-
}
67-
this.clientSecret = clientSecret;
78+
this(
79+
clientSecret,
80+
FlagResolverServiceGrpc.newBlockingStub(
81+
ManagedChannelBuilder.forAddress("edge-grpc.spotify.com", 443).build()));
6882
}
6983

7084
@Override
@@ -157,6 +171,7 @@ public ProviderEvaluation<Value> getObjectEvaluation(
157171
.setClientSecret(clientSecret)
158172
.addAllFlags(List.of(requestFlagName))
159173
.setEvaluationContext(evaluationContext.build())
174+
.setSdk(Sdk.newBuilder().setId(SDK_ID).setVersion(SDK_VERSION).build())
160175
.setApply(true)
161176
.build());
162177

src/main/proto/confidence/flags/resolver/v1/api.proto

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ message ResolveFlagsRequest {
7272
bool apply = 4 [
7373
(google.api.field_behavior) = REQUIRED
7474
];
75+
76+
// Information about the SDK used to initiate the request.
77+
Sdk sdk = 5 [
78+
(google.api.field_behavior) = OPTIONAL
79+
];
7580
}
7681

7782
message ResolveFlagsResponse {
@@ -82,6 +87,9 @@ message ResolveFlagsResponse {
8287
// An opaque token that is used when `apply` is set to false in `ResolveFlags`.
8388
// When `apply` is set to false, the token must be passed to `ApplyFlags`.
8489
bytes resolve_token = 2;
90+
91+
// Unique identifier for this particular resolve request.
92+
string resolve_id = 3;
8593
}
8694

8795
message ApplyFlagsRequest {
@@ -104,6 +112,11 @@ message ApplyFlagsRequest {
104112
google.protobuf.Timestamp send_time = 4 [
105113
(google.api.field_behavior) = REQUIRED
106114
];
115+
116+
// Information about the SDK used to initiate the request.
117+
Sdk sdk = 5 [
118+
(google.api.field_behavior) = OPTIONAL
119+
];
107120
}
108121

109122
message ApplyFlagsResponse {

src/main/proto/confidence/flags/resolver/v1/types.proto

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@ syntax = "proto3";
22

33
package confidence.flags.resolver.v1;
44

5+
import "google/api/field_behavior.proto";
6+
57
option java_package = "com.spotify.confidence.flags.resolver.v1";
68
option java_multiple_files = true;
79
option java_outer_classname = "TypesProto";
810

11+
// (-- api-linter: core::0123::resource-annotation=disabled
12+
// aip.dev/not-precedent: SDKs are not internal Confidence resources. --)
13+
message Sdk {
14+
// Identifier of the SDK used to interact with the API.
15+
oneof sdk {
16+
// Name of a Confidence SDKs.
17+
SdkId id = 1;
18+
// Custom name for non-Confidence SDKs.
19+
string custom_id = 2;
20+
}
21+
22+
// Version of the SDK.
23+
string version = 3 [
24+
(google.api.field_behavior) = REQUIRED
25+
];
26+
}
27+
928
enum ResolveReason {
1029
// Unspecified enum.
1130
RESOLVE_REASON_UNSPECIFIED = 0;
@@ -18,6 +37,27 @@ enum ResolveReason {
1837
RESOLVE_REASON_NO_TREATMENT_MATCH = 3 [deprecated = true];
1938
// The flag could not be resolved because it was archived.
2039
RESOLVE_REASON_FLAG_ARCHIVED = 4;
40+
// The flag could not be resolved because the targeting key field was invalid
41+
RESOLVE_REASON_TARGETING_KEY_ERROR = 5;
2142
// Unknown error occurred during the resolve
22-
RESOLVE_REASON_ERROR = 5;
43+
RESOLVE_REASON_ERROR = 6;
44+
}
45+
46+
enum SdkId {
47+
// Unspecified enum.
48+
SDK_ID_UNSPECIFIED = 0;
49+
// Confidence OpenFeature Java Provider.
50+
SDK_ID_JAVA_PROVIDER = 1;
51+
// Confidence OpenFeature Kotlin Provider.
52+
SDK_ID_KOTLIN_PROVIDER = 2;
53+
// Confidence OpenFeature Swift Provider.
54+
SDK_ID_SWIFT_PROVIDER = 3;
55+
// Confidence OpenFeature JavaScript Provider for Web (client).
56+
SDK_ID_JS_WEB_PROVIDER = 4;
57+
// Confidence OpenFeature JavaScript Provider for server.
58+
SDK_ID_JS_SERVER_PROVIDER = 5;
59+
// Confidence OpenFeature Python Provider.
60+
SDK_ID_PYTHON_PROVIDER = 6;
61+
// Confidence OpenFeature GO Provider.
62+
SDK_ID_GO_PROVIDER = 7;
2363
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
version = ${project.version}

0 commit comments

Comments
 (0)