Skip to content

Commit 50f5578

Browse files
vahidlazioclaude
andauthored
docs: add event tracking documentation for local resolve providers (#545)
Co-authored-by: vahidlazio <vahidlazio@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 825ef1b commit 50f5578

6 files changed

Lines changed: 176 additions & 3 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ The tools and SDKs published for direct usage:
1818

1919
Underlying building blocks:
2020
- `confidence-resolver`: Core resolver crate
21-
- `wasm` and `wasm-msg`: WASM resolver with communication contract towards the hosting environment
21+
- `confidence-event-engine`: Event batching engine compiled to WASM (shared by all providers for `track()` support)
22+
- `wasm` and `wasm-msg`: WASM resolver with communication contract towards the hosting environment
2223
- `data`: Sample local development data (e.g., resolver state)
2324

2425

openfeature-provider/INTEGRATION_GUIDE.md

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ For language-specific installation and quick start instructions, see your provid
66
- [Go Provider](go/README.md)
77
- [Java Provider](java/README.md)
88
- [JavaScript Provider](js/README.md)
9+
- [Python Provider](python/README.md)
910
- [Ruby Provider](ruby/README.md)
1011

1112
---
@@ -15,8 +16,9 @@ For language-specific installation and quick start instructions, see your provid
1516
1. [Getting Your Credentials](#getting-your-credentials)
1617
2. [Encryption](#encryption)
1718
3. [Error Handling](#error-handling)
18-
4. [Sticky Assignments](#sticky-assignments)
19-
5. [Deferred Apply and Resolve Token Security](#deferred-apply-and-resolve-token-security)
19+
4. [Event Tracking](#event-tracking)
20+
5. [Sticky Assignments](#sticky-assignments)
21+
6. [Deferred Apply and Resolve Token Security](#deferred-apply-and-resolve-token-security)
2022

2123
---
2224

@@ -143,6 +145,52 @@ For debugging, use the `details` methods to get error information:
143145

144146
---
145147

148+
## Event Tracking
149+
150+
All local-resolve providers support the [OpenFeature tracking API](https://openfeature.dev/specification/sections/tracking), enabling you to send custom events to the [Confidence events backend](https://confidence.spotify.com/docs). Events are batched inside a shared WebAssembly engine and flushed periodically alongside flag logs — no additional configuration is required.
151+
152+
### How It Works
153+
154+
1. You call `track()` on the OpenFeature client with an event name, optional evaluation context, and optional tracking details (a numeric `value` and arbitrary custom data).
155+
2. The event is queued inside the WASM event engine.
156+
3. A background flush publishes batches to the Confidence events service at the same interval as flag log flushing.
157+
4. On provider shutdown, pending events are drained (up to 100 batches).
158+
159+
### Delivery Guarantees
160+
161+
Events are delivered **at-most-once, best-effort**. Once a batch is flushed from the WASM buffer, a failed publish drops it — there is no re-queue or persistence. This matches the flag-log path. Transient failures are absorbed by transport-level retries (gRPC retry policy or fetch-layer retries), and sustained failures are surfaced via periodic warning logs rather than per-failure noise.
162+
163+
On shutdown, each provider drains pending events on a best-effort basis (up to 100 batches, with a timeout). Events buffered when the process is killed uncleanly (e.g. `SIGKILL`) are lost.
164+
165+
### Event Name Mapping
166+
167+
You pass bare event names (e.g. `"checkout_completed"`). The WASM engine automatically prepends the `eventDefinitions/` prefix, so the event arrives at the Confidence backend as `eventDefinitions/checkout_completed`. This matches the [event definition](https://confidence.spotify.com/docs) resource naming in Confidence — you do not need to include the prefix yourself.
168+
169+
### Payload Mapping
170+
171+
The event payload is built by merging inputs in this order:
172+
173+
1. **`data`** — your custom key-value fields from tracking details
174+
2. **`value`** — the numeric value from tracking details (overwrites a same-named key from `data`)
175+
3. **`context`** — the evaluation context (overwrites same-named keys from `data` and `value`)
176+
177+
`value` and `context` are reserved keys. If your custom data contains a key named `"value"` or `"context"`, it will be overwritten.
178+
179+
### Known Provider Differences
180+
181+
**Go cannot distinguish `value: 0` from an unset value.** Go's `TrackingEventDetails` stores `value` as a plain `float64` with no "is set" flag. The Go provider treats `0` as unset and omits it to avoid attaching a spurious `value: 0` to every event. Java (`Optional<Number>`), JavaScript (`number | undefined`), and Python (`Optional[float]`) can distinguish them and forward an explicit `0` correctly. If you need to record a zero-valued event from Go, put it in the custom data instead.
182+
183+
### Language-Specific Examples
184+
185+
See your provider's README for usage examples:
186+
187+
- [JavaScript](js/README.md#event-tracking)
188+
- [Java](java/README.md#event-tracking)
189+
- [Go](go/README.md#event-tracking)
190+
- [Python](python/README.md#event-tracking)
191+
192+
---
193+
146194
## Sticky Assignments
147195

148196
Confidence provides **sticky** flag assignments to ensure users receive consistent variant assignments across evaluations. It can be used for two things:
@@ -225,6 +273,7 @@ The provider only needs to see the original token at apply time — anything you
225273
- [Go Provider](go/README.md)
226274
- [Java Provider](java/README.md)
227275
- [JavaScript Provider](js/README.md)
276+
- [Python Provider](python/README.md)
228277
- [Ruby Provider](ruby/README.md)
229278
- [Root Repository README](../README.md)
230279
- [Sticky Assignments Technical Guide](../STICKY_ASSIGNMENTS.md)

openfeature-provider/go/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A high-performance OpenFeature provider for [Confidence](https://confidence.spot
1010
- **Low Latency**: No network calls during flag evaluation
1111
- **Automatic Sync**: Periodically syncs flag configurations from Confidence
1212
- **Exposure Logging**: Fully supported exposure logging and resolve analytics
13+
- **[Event Tracking](#event-tracking)**: Send custom events via the OpenFeature `Track()` API
1314
- **OpenFeature Compatible**: Works with the standard OpenFeature Go SDK
1415

1516
## Installation
@@ -563,6 +564,38 @@ The provider logs at different levels: `Debug` (flag resolution details), `Info`
563564

564565
The shutdown respects the context timeout you provide.
565566

567+
## Event Tracking
568+
569+
The provider supports the [OpenFeature tracking API](https://openfeature.dev/specification/sections/tracking) for sending custom events to the Confidence events backend. Event tracking is automatically enabled when using `NewProvider` — no configuration needed.
570+
571+
**📖 See the [Integration Guide: Event Tracking](../INTEGRATION_GUIDE.md#event-tracking)** for delivery guarantees, payload mapping rules, and cross-provider differences.
572+
573+
### Usage
574+
575+
```go
576+
client := openfeature.NewClient("my-app")
577+
578+
evalCtx := openfeature.NewEvaluationContext("user-123", map[string]interface{}{
579+
"country": "US",
580+
})
581+
582+
// Track a simple event
583+
client.Track(ctx, "checkout_completed", evalCtx, openfeature.NewTrackingEventDetails(0))
584+
585+
// Track with a numeric value
586+
client.Track(ctx, "purchase", evalCtx, openfeature.NewTrackingEventDetails(49.99))
587+
588+
// Track with custom data
589+
details := openfeature.NewTrackingEventDetails(1)
590+
details.Add("sku", "ABC-123")
591+
details.Add("category", "electronics")
592+
client.Track(ctx, "item_added", evalCtx, details)
593+
```
594+
595+
Events are batched internally and flushed to the Confidence events service at the same interval as flag logs (configurable via `LogPollInterval`). On shutdown, pending events are drained on a best-effort basis (up to 100 batches within a 3-second timeout).
596+
597+
> **Note:** Go cannot distinguish `value: 0` from an unset value. The provider treats `0` as unset and omits it. If you need to record a zero-valued event, put it in the custom data instead of `value`. See the [Integration Guide](../INTEGRATION_GUIDE.md#known-provider-differences) for details.
598+
566599
## Advanced: Controlling Exposure Events
567600

568601
By default, every flag evaluation records an exposure event (apply). Only disable this for exceptional cases where this provider must not collect exposures at all.

openfeature-provider/java/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A high-performance OpenFeature provider for [Confidence](https://confidence.spot
1010
- **Low Latency**: No network calls during flag evaluation
1111
- **Automatic Sync**: Periodically syncs flag configurations from Confidence
1212
- **Exposure Logging**: Fully supported exposure logging (and other resolve analytics)
13+
- **[Event Tracking](#event-tracking)**: Send custom events via the OpenFeature `track()` API
1314
- **OpenFeature Compatible**: Works with the standard OpenFeature SDK
1415
- **HTTP Proxy Service**: Proxy requests from client SDKs through your backend for enhanced control
1516

@@ -401,6 +402,33 @@ const confidence = Confidence.create({
401402
});
402403
```
403404

405+
## Event Tracking
406+
407+
The provider supports the [OpenFeature tracking API](https://openfeature.dev/specification/sections/tracking) for sending custom events to the Confidence events backend. Event tracking is automatically enabled — no configuration needed.
408+
409+
**📖 See the [Integration Guide: Event Tracking](../INTEGRATION_GUIDE.md#event-tracking)** for delivery guarantees, payload mapping rules, and cross-provider differences.
410+
411+
### Usage
412+
413+
```java
414+
Client client = OpenFeatureAPI.getInstance().getClient();
415+
416+
// Track a simple event
417+
MutableContext ctx = new MutableContext("user-123");
418+
client.track("checkout_completed", ctx);
419+
420+
// Track with a numeric value
421+
client.track("purchase", ctx, new MutableTrackingEventDetails(49.99f));
422+
423+
// Track with custom data
424+
MutableTrackingEventDetails details = new MutableTrackingEventDetails(1.0f);
425+
details.add("sku", "ABC-123");
426+
details.add("category", "electronics");
427+
client.track("item_added", ctx, details);
428+
```
429+
430+
Events are batched internally and flushed to the Confidence events service every 15 seconds. On shutdown, pending events are drained on a best-effort basis (up to 100 batches within a 5-second grace period).
431+
404432
## Advanced: Controlling Exposure Events
405433

406434
By default, every flag evaluation records an exposure event (apply). Only disable this for exceptional cases where this provider must not collect exposures at all.

openfeature-provider/js/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ OpenFeature provider for the Spotify Confidence resolver (local mode, powered by
66

77
- Local flag evaluation via WASM (no per-eval network calls)
88
- Automatic state refresh and batched flag log flushing
9+
- [Event tracking](#event-tracking) via the OpenFeature `track()` API
910
- Pluggable `fetch` with retries, timeouts and routing
1011
- Optional logging using `debug`
1112
- **[React integration](./README-REACT.md)** for Next.js with Server Components
@@ -361,6 +362,35 @@ yarn add debug
361362

362363
---
363364

365+
## Event Tracking
366+
367+
The provider supports the [OpenFeature tracking API](https://openfeature.dev/specification/sections/tracking) for sending custom events to the Confidence events backend. Event tracking is automatically enabled — no configuration needed.
368+
369+
**📖 See the [Integration Guide: Event Tracking](../INTEGRATION_GUIDE.md#event-tracking)** for delivery guarantees, payload mapping rules, and cross-provider differences.
370+
371+
### Usage
372+
373+
```typescript
374+
const client = OpenFeature.getClient();
375+
376+
// Track a simple event
377+
client.track('checkout_completed', { targetingKey: 'user-123' });
378+
379+
// Track with a numeric value
380+
client.track('purchase', { targetingKey: 'user-123' }, { value: 49.99 });
381+
382+
// Track with custom data
383+
client.track('item_added', { targetingKey: 'user-123' }, {
384+
value: 1,
385+
sku: 'ABC-123',
386+
category: 'electronics',
387+
});
388+
```
389+
390+
Events are batched internally and flushed to the Confidence events service at the same interval as flag logs (configurable via `flushInterval`). On shutdown (`onClose()`), pending events are drained on a best-effort basis (up to 100 batches).
391+
392+
---
393+
364394
## Advanced: Controlling Exposure Events
365395

366396
By default, every flag evaluation records an exposure event (apply). Only disable this for exceptional cases where this provider must not collect exposures at all.

openfeature-provider/python/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A high-performance OpenFeature provider for [Confidence](https://confidence.spot
1010
- **Low Latency**: No network calls during flag evaluation
1111
- **Automatic Sync**: Periodically syncs flag configurations from Confidence
1212
- **Exposure Logging**: Fully supported exposure logging (and other resolve analytics)
13+
- **[Event Tracking](#event-tracking)**: Send custom events via the OpenFeature `track()` API
1314
- **OpenFeature Compatible**: Works with the standard OpenFeature SDK
1415

1516
## Requirements
@@ -254,6 +255,37 @@ import logging
254255
logging.getLogger("confidence").setLevel(logging.DEBUG)
255256
```
256257

258+
## Event Tracking
259+
260+
The provider supports the [OpenFeature tracking API](https://openfeature.dev/specification/sections/tracking) for sending custom events to the Confidence events backend. Event tracking is automatically enabled — no configuration needed.
261+
262+
**📖 See the [Integration Guide: Event Tracking](../INTEGRATION_GUIDE.md#event-tracking)** for delivery guarantees, payload mapping rules, and cross-provider differences.
263+
264+
### Usage
265+
266+
```python
267+
client = api.get_client()
268+
269+
context = EvaluationContext(
270+
targeting_key="user-123",
271+
attributes={"country": "US"},
272+
)
273+
274+
# Track a simple event
275+
client.track("checkout_completed", context)
276+
277+
# Track with a numeric value
278+
client.track("purchase", context, TrackingEventDetails(value=49.99))
279+
280+
# Track with custom data
281+
client.track("item_added", context, TrackingEventDetails(
282+
value=1,
283+
attributes={"sku": "ABC-123", "category": "electronics"},
284+
))
285+
```
286+
287+
Events are batched internally and flushed to the Confidence events service at the same interval as flag logs (configurable via `log_poll_interval`). On shutdown, pending events are drained on a best-effort basis (up to 100 batches).
288+
257289
## Advanced: Controlling Exposure Events
258290

259291
By default, every flag evaluation records an exposure event (apply). Only disable this for exceptional cases where this provider must not collect exposures at all.

0 commit comments

Comments
 (0)