Skip to content

Commit 2481fc6

Browse files
nicklaslclaude
andcommitted
feat: add provider_init_rate to telemetry
On the first telemetry flush after provider initialization, include a ProviderInitRate entry with labels describing the SDK configuration (e.g. encryption: true/false). This lets the backend track which customers have adopted encryption without tagging every metric. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 353a4e3 commit 2481fc6

27 files changed

Lines changed: 324 additions & 103 deletions

File tree

confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ message WriteFlagAssignedResponse {
112112
// consumers everything needed to reconstruct bucket boundaries and resample
113113
// between different histogram configurations if needed.
114114
message TelemetryData {
115+
reserved 1; // was: int64 dropped_events
116+
115117
// Information about the SDK/provider
116118
Sdk sdk = 2 [
117119
(google.api.field_behavior) = OPTIONAL
@@ -128,6 +130,14 @@ message TelemetryData {
128130
// Set from the confidence-resolver crate version at build time.
129131
string resolver_version = 8;
130132

133+
repeated ProviderInitRate provider_init_rate = 9;
134+
135+
message ProviderInitRate {
136+
uint32 count = 1;
137+
reserved 2; // status — tbd
138+
map<string, string> labels = 3;
139+
}
140+
131141
message ResolveLatency {
132142
// Delta sum of observed values since the last flush.
133143
uint32 sum = 1;

confidence-resolver/src/telemetry.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ impl Telemetry {
498498
state_age,
499499
memory_bytes: (self.memory_provider)(),
500500
resolver_version: crate::version::VERSION.to_string(),
501+
provider_init_rate: Vec::new(),
501502
}
502503
}
503504
}
Binary file not shown.

openfeature-provider/go/confidence/internal/local_resolver/local_resolver.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,16 @@ type localResolverImpl struct {
4444
}
4545

4646
func NewLocalResolverWithPoolSize(ctx context.Context, logSink LogSink, poolSize int) LocalResolver {
47-
factory := NewWasmResolverFactory(logSink)
47+
return NewLocalResolverWithLabels(ctx, logSink, poolSize, nil)
48+
}
49+
50+
func NewLocalResolverWithLabels(ctx context.Context, logSink LogSink, poolSize int, initLabels map[string]string) LocalResolver {
51+
var factory LocalResolverFactory
52+
if len(initLabels) > 0 {
53+
factory = NewWasmResolverFactoryWithLabels(logSink, initLabels)
54+
} else {
55+
factory = NewWasmResolverFactory(logSink)
56+
}
4857
factory = NewRecoveringResolverFactory(factory)
4958
if poolSize <= 0 {
5059
poolSize = DefaultPoolSize

openfeature-provider/go/confidence/internal/local_resolver/wasm.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ type WasmResolver struct {
4242
mu *sync.Mutex
4343
instanceID string
4444
fnCache sync.Map
45+
initLabels map[string]string
46+
firstFlush bool
4547
}
4648

4749
var _ LocalResolver = (*WasmResolver)(nil)
@@ -85,6 +87,16 @@ func (r *WasmResolver) ApplyFlags(request *resolver.ApplyFlagsRequest) error {
8587
func (r *WasmResolver) FlushAllLogs() error {
8688
resp := &resolverv1.WriteFlagLogsRequest{}
8789
err := r.call("wasm_msg_guest_bounded_flush_logs", nil, resp)
90+
if err == nil && r.firstFlush {
91+
r.firstFlush = false
92+
if resp.TelemetryData == nil {
93+
resp.TelemetryData = &resolverv1.TelemetryData{}
94+
}
95+
resp.TelemetryData.ProviderInitRate = append(
96+
resp.TelemetryData.ProviderInitRate,
97+
&resolverv1.TelemetryData_ProviderInitRate{Count: 1, Labels: r.initLabels},
98+
)
99+
}
88100
if err == nil && proto.Size(resp) > 0 {
89101
r.logSink(resp)
90102
}
@@ -154,9 +166,10 @@ func (r *WasmResolver) call(fnName string, request proto.Message, response proto
154166
}
155167

156168
type WasmResolverFactory struct {
157-
runtime wazero.Runtime
158-
module wazero.CompiledModule
159-
logSink LogSink
169+
runtime wazero.Runtime
170+
module wazero.CompiledModule
171+
logSink LogSink
172+
initLabels map[string]string
160173
}
161174

162175
var _ LocalResolverFactory = (*WasmResolverFactory)(nil)
@@ -208,6 +221,12 @@ func NewWasmResolverFactory(logSink LogSink) LocalResolverFactory {
208221
}
209222
}
210223

224+
func NewWasmResolverFactoryWithLabels(logSink LogSink, initLabels map[string]string) LocalResolverFactory {
225+
factory := NewWasmResolverFactory(logSink).(*WasmResolverFactory)
226+
factory.initLabels = initLabels
227+
return factory
228+
}
229+
211230
func (wrf *WasmResolverFactory) New() LocalResolver {
212231
ctx := context.Background()
213232
config := wazero.NewModuleConfig().WithName("")
@@ -221,6 +240,8 @@ func (wrf *WasmResolverFactory) New() LocalResolver {
221240
logSink: wrf.logSink,
222241
mu: &sync.Mutex{},
223242
instanceID: fmt.Sprintf("%d", id),
243+
initLabels: wrf.initLabels,
244+
firstFlush: true,
224245
}
225246
}
226247

openfeature-provider/go/confidence/internal/proto/admin/resolver.pb.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

openfeature-provider/go/confidence/internal/proto/resolver/api_grpc.pb.go

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

openfeature-provider/go/confidence/internal/proto/resolver/types.pb.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)