Skip to content

Commit bbd0c91

Browse files
committed
NewScopedClient, AddContext, OverwriteContextByKind emit usage events
1 parent cec8a13 commit bbd0c91

File tree

2 files changed

+79
-20
lines changed

2 files changed

+79
-20
lines changed

ldclient_scoped.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ type LDScopedClient struct {
8888
// guarantees or semantic versioning. It is not suitable for production usage. Do
8989
// not use it. You have been warned.
9090
func NewScopedClient(client *LDClient, context ldcontext.Context) *LDScopedClient {
91+
_ = client.TrackData("$ld:scoped:usage", context, ldvalue.String("new"))
9192
cc := &LDScopedClient{
9293
client: client,
9394
contexts: make(map[ldcontext.Kind]ldcontext.Context),
9495
rebuild: true,
9596
}
96-
cc.AddContext(context)
97+
cc.addContext(context)
9798
return cc
9899
}
99100

@@ -105,6 +106,16 @@ func (c *LDScopedClient) addIndividualContext(context ldcontext.Context) {
105106
c.contexts[context.Kind()] = context
106107
}
107108

109+
func (c *LDScopedClient) addContext(context ldcontext.Context) {
110+
if context.Multiple() {
111+
for _, individual := range context.GetAllIndividualContexts(nil) {
112+
c.addIndividualContext(individual)
113+
}
114+
return
115+
}
116+
c.addIndividualContext(context)
117+
}
118+
108119
// AddContext adds additional evaluation contexts to the scoped client's current context.
109120
// This affects all future operations on it, like flag evaluations and event tracking.
110121
//
@@ -121,13 +132,8 @@ func (c *LDScopedClient) AddContext(contexts ...ldcontext.Context) {
121132
c.rebuild = true
122133

123134
for _, ctx := range contexts {
124-
if ctx.Multiple() {
125-
for _, individual := range ctx.GetAllIndividualContexts(nil) {
126-
c.addIndividualContext(individual)
127-
}
128-
continue
129-
}
130-
c.addIndividualContext(ctx)
135+
_ = c.client.TrackData("$ld:scoped:usage", ctx, ldvalue.String("add"))
136+
c.addContext(ctx)
131137
}
132138
}
133139

@@ -156,6 +162,7 @@ func (c *LDScopedClient) OverwriteContextByKind(contexts ...ldcontext.Context) {
156162
c.rebuild = true
157163

158164
for _, ctx := range contexts {
165+
_ = c.client.TrackData("$ld:scoped:usage", ctx, ldvalue.String("overwrite"))
159166
if ctx.Multiple() {
160167
for _, individual := range ctx.GetAllIndividualContexts(nil) {
161168
c.overwriteIndividualContextByKind(individual)

ldclient_scoped_test.go

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
89

910
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
1011
"github.com/launchdarkly/go-sdk-common/v3/ldlog"
@@ -65,11 +66,42 @@ func TestScopedClientCollectsContexts(t *testing.T) {
6566

6667
assert.Equal(t, ldcontext.NewMulti(ldctx2, ldctx3, ldctx4, dupeCtx), c.CurrentContext())
6768
})
69+
70+
t.Run("calling scoped client methods sends usage events", func(t *testing.T) {
71+
client := makeTestClient()
72+
c := NewScopedClient(client, ldctx1)
73+
c.AddContext(ldctx2, ldctx3)
74+
c.OverwriteContextByKind(ldctx3, ldctx4)
75+
76+
events := client.eventProcessor.(*mocks.CapturingEventProcessor).Events
77+
expectedEvents := []struct {
78+
Key string
79+
Context ldcontext.Context
80+
DataString string
81+
}{
82+
{"$ld:scoped:usage", ldctx1, "new"},
83+
{"$ld:scoped:usage", ldctx2, "add"},
84+
{"$ld:scoped:usage", ldctx3, "add"},
85+
{"$ld:scoped:usage", ldctx3, "overwrite"},
86+
{"$ld:scoped:usage", ldctx4, "overwrite"},
87+
}
88+
require.Equal(t, len(expectedEvents), len(events))
89+
for i, expected := range expectedEvents {
90+
e := events[i].(ldevents.CustomEventData)
91+
assert.Equal(t, expected.Key, e.Key)
92+
assert.Equal(t, ldevents.Context(expected.Context), e.Context)
93+
assert.Equal(t, ldvalue.String(expected.DataString), e.Data)
94+
}
95+
})
6896
}
6997

7098
// Testing the scoped versions of all the evaluation methods
7199
// Almost the same as the tests in ldclient_evaluation_test.go, but with the scoped client instead
72100

101+
func clearCapturedEvents(client *LDClient) {
102+
client.eventProcessor.(*mocks.CapturingEventProcessor).Events = nil
103+
}
104+
73105
func TestScopedBoolVariation(t *testing.T) {
74106
expected, defaultVal := true, false
75107

@@ -78,6 +110,7 @@ func TestScopedBoolVariation(t *testing.T) {
78110
p.setupSingleValueFlag(evalFlagKey, ldvalue.Bool(true))
79111

80112
scopedClient := NewScopedClient(p.client, evalTestUser)
113+
clearCapturedEvents(p.client)
81114
actual, err := scopedClient.BoolVariation(evalFlagKey, defaultVal)
82115

83116
assert.NoError(t, err)
@@ -91,6 +124,7 @@ func TestScopedBoolVariation(t *testing.T) {
91124
p.setupSingleValueFlag(evalFlagKey, ldvalue.Bool(true))
92125

93126
scopedClient := NewScopedClient(p.client, evalTestUser)
127+
clearCapturedEvents(p.client)
94128
actual, err := scopedClient.BoolVariationCtx(gocontext.TODO(), evalFlagKey, defaultVal)
95129

96130
assert.NoError(t, err)
@@ -104,6 +138,7 @@ func TestScopedBoolVariation(t *testing.T) {
104138
p.setupSingleValueFlag(evalFlagKey, ldvalue.Bool(true))
105139

106140
scopedClient := NewScopedClient(p.client, evalTestUser)
141+
clearCapturedEvents(p.client)
107142
actual, detail, err := scopedClient.BoolVariationDetail(evalFlagKey, defaultVal)
108143

109144
assert.NoError(t, err)
@@ -119,6 +154,7 @@ func TestScopedBoolVariation(t *testing.T) {
119154
p.setupSingleValueFlag(evalFlagKey, ldvalue.Bool(true))
120155

121156
scopedClient := NewScopedClient(p.client, evalTestUser)
157+
clearCapturedEvents(p.client)
122158
actual, detail, err := scopedClient.BoolVariationDetailCtx(gocontext.TODO(), evalFlagKey, defaultVal)
123159

124160
assert.NoError(t, err)
@@ -139,6 +175,7 @@ func TestScopedIntVariation(t *testing.T) {
139175
p.setupSingleValueFlag(evalFlagKey, ldvalue.Int(expected))
140176

141177
scopedClient := NewScopedClient(p.client, evalTestUser)
178+
clearCapturedEvents(p.client)
142179
actual, err := scopedClient.IntVariation(evalFlagKey, defaultVal)
143180

144181
assert.NoError(t, err)
@@ -152,6 +189,7 @@ func TestScopedIntVariation(t *testing.T) {
152189
p.setupSingleValueFlag(evalFlagKey, ldvalue.Int(expected))
153190

154191
scopedClient := NewScopedClient(p.client, evalTestUser)
192+
clearCapturedEvents(p.client)
155193
actual, err := scopedClient.IntVariationCtx(gocontext.TODO(), evalFlagKey, defaultVal)
156194

157195
assert.NoError(t, err)
@@ -165,6 +203,7 @@ func TestScopedIntVariation(t *testing.T) {
165203
p.setupSingleValueFlag(evalFlagKey, ldvalue.Int(expected))
166204

167205
scopedClient := NewScopedClient(p.client, evalTestUser)
206+
clearCapturedEvents(p.client)
168207
actual, detail, err := scopedClient.IntVariationDetail(evalFlagKey, defaultVal)
169208

170209
assert.NoError(t, err)
@@ -180,6 +219,7 @@ func TestScopedIntVariation(t *testing.T) {
180219
p.setupSingleValueFlag(evalFlagKey, ldvalue.Int(expected))
181220

182221
scopedClient := NewScopedClient(p.client, evalTestUser)
222+
clearCapturedEvents(p.client)
183223
actual, detail, err := scopedClient.IntVariationDetailCtx(gocontext.TODO(), evalFlagKey, defaultVal)
184224

185225
assert.NoError(t, err)
@@ -200,6 +240,7 @@ func TestScopedFloat64Variation(t *testing.T) {
200240
p.setupSingleValueFlag(evalFlagKey, ldvalue.Float64(expected))
201241

202242
scopedClient := NewScopedClient(p.client, evalTestUser)
243+
clearCapturedEvents(p.client)
203244
actual, err := scopedClient.Float64Variation(evalFlagKey, defaultVal)
204245

205246
assert.NoError(t, err)
@@ -213,6 +254,7 @@ func TestScopedFloat64Variation(t *testing.T) {
213254
p.setupSingleValueFlag(evalFlagKey, ldvalue.Float64(expected))
214255

215256
scopedClient := NewScopedClient(p.client, evalTestUser)
257+
clearCapturedEvents(p.client)
216258
actual, err := scopedClient.Float64VariationCtx(gocontext.TODO(), evalFlagKey, defaultVal)
217259

218260
assert.NoError(t, err)
@@ -226,6 +268,7 @@ func TestScopedFloat64Variation(t *testing.T) {
226268
p.setupSingleValueFlag(evalFlagKey, ldvalue.Float64(expected))
227269

228270
scopedClient := NewScopedClient(p.client, evalTestUser)
271+
clearCapturedEvents(p.client)
229272
actual, detail, err := scopedClient.Float64VariationDetail(evalFlagKey, defaultVal)
230273

231274
assert.NoError(t, err)
@@ -241,6 +284,7 @@ func TestScopedFloat64Variation(t *testing.T) {
241284
p.setupSingleValueFlag(evalFlagKey, ldvalue.Float64(expected))
242285

243286
scopedClient := NewScopedClient(p.client, evalTestUser)
287+
clearCapturedEvents(p.client)
244288
actual, detail, err := scopedClient.Float64VariationDetailCtx(gocontext.TODO(), evalFlagKey, defaultVal)
245289

246290
assert.NoError(t, err)
@@ -261,6 +305,7 @@ func TestScopedStringVariation(t *testing.T) {
261305
p.setupSingleValueFlag(evalFlagKey, ldvalue.String(expected))
262306

263307
scopedClient := NewScopedClient(p.client, evalTestUser)
308+
clearCapturedEvents(p.client)
264309
actual, err := scopedClient.StringVariation(evalFlagKey, defaultVal)
265310

266311
assert.NoError(t, err)
@@ -274,6 +319,7 @@ func TestScopedStringVariation(t *testing.T) {
274319
p.setupSingleValueFlag(evalFlagKey, ldvalue.String(expected))
275320

276321
scopedClient := NewScopedClient(p.client, evalTestUser)
322+
clearCapturedEvents(p.client)
277323
actual, err := scopedClient.StringVariationCtx(gocontext.TODO(), evalFlagKey, defaultVal)
278324

279325
assert.NoError(t, err)
@@ -287,6 +333,7 @@ func TestScopedStringVariation(t *testing.T) {
287333
p.setupSingleValueFlag(evalFlagKey, ldvalue.String(expected))
288334

289335
scopedClient := NewScopedClient(p.client, evalTestUser)
336+
clearCapturedEvents(p.client)
290337
actual, detail, err := scopedClient.StringVariationDetail(evalFlagKey, defaultVal)
291338

292339
assert.NoError(t, err)
@@ -302,6 +349,7 @@ func TestScopedStringVariation(t *testing.T) {
302349
p.setupSingleValueFlag(evalFlagKey, ldvalue.String(expected))
303350

304351
scopedClient := NewScopedClient(p.client, evalTestUser)
352+
clearCapturedEvents(p.client)
305353
actual, detail, err := scopedClient.StringVariationDetailCtx(gocontext.TODO(), evalFlagKey, defaultVal)
306354

307355
assert.NoError(t, err)
@@ -323,6 +371,7 @@ func TestScopedJSONVariation(t *testing.T) {
323371
p.setupSingleValueFlag(evalFlagKey, expected)
324372

325373
scopedClient := NewScopedClient(p.client, evalTestUser)
374+
clearCapturedEvents(p.client)
326375
actual, err := scopedClient.JSONVariation(evalFlagKey, defaultVal)
327376

328377
assert.NoError(t, err)
@@ -336,6 +385,7 @@ func TestScopedJSONVariation(t *testing.T) {
336385
p.setupSingleValueFlag(evalFlagKey, expected)
337386

338387
scopedClient := NewScopedClient(p.client, evalTestUser)
388+
clearCapturedEvents(p.client)
339389
actual, err := scopedClient.JSONVariationCtx(gocontext.TODO(), evalFlagKey, defaultVal)
340390

341391
assert.NoError(t, err)
@@ -349,6 +399,7 @@ func TestScopedJSONVariation(t *testing.T) {
349399
p.setupSingleValueFlag(evalFlagKey, expected)
350400

351401
scopedClient := NewScopedClient(p.client, evalTestUser)
402+
clearCapturedEvents(p.client)
352403
actual, detail, err := scopedClient.JSONVariationDetail(evalFlagKey, defaultVal)
353404

354405
assert.NoError(t, err)
@@ -364,6 +415,7 @@ func TestScopedJSONVariation(t *testing.T) {
364415
p.setupSingleValueFlag(evalFlagKey, expected)
365416

366417
scopedClient := NewScopedClient(p.client, evalTestUser)
418+
clearCapturedEvents(p.client)
367419
actual, detail, err := scopedClient.JSONVariationDetailCtx(gocontext.TODO(), evalFlagKey, defaultVal)
368420

369421
assert.NoError(t, err)
@@ -416,8 +468,8 @@ func TestScopedTrackCalls(t *testing.T) {
416468
assert.NoError(t, err)
417469

418470
events := client.eventProcessor.(*mocks.CapturingEventProcessor).Events
419-
assert.Equal(t, 1, len(events))
420-
e := events[0].(ldevents.CustomEventData)
471+
assert.Equal(t, 2, len(events))
472+
e := events[1].(ldevents.CustomEventData)
421473
assert.Equal(t, ldevents.Context(evalTestUser), e.Context)
422474
assert.Equal(t, key, e.Key)
423475
})
@@ -431,8 +483,8 @@ func TestScopedTrackCalls(t *testing.T) {
431483
assert.NoError(t, err)
432484

433485
events := client.eventProcessor.(*mocks.CapturingEventProcessor).Events
434-
assert.Equal(t, 1, len(events))
435-
e := events[0].(ldevents.CustomEventData)
486+
assert.Equal(t, 2, len(events))
487+
e := events[1].(ldevents.CustomEventData)
436488
assert.Equal(t, ldevents.Context(evalTestUser), e.Context)
437489
assert.Equal(t, key, e.Key)
438490
})
@@ -447,8 +499,8 @@ func TestScopedTrackCalls(t *testing.T) {
447499
assert.NoError(t, err)
448500

449501
events := client.eventProcessor.(*mocks.CapturingEventProcessor).Events
450-
assert.Equal(t, 1, len(events))
451-
e := events[0].(ldevents.CustomEventData)
502+
assert.Equal(t, 2, len(events))
503+
e := events[1].(ldevents.CustomEventData)
452504
assert.Equal(t, ldevents.Context(evalTestUser), e.Context)
453505
assert.Equal(t, key, e.Key)
454506
assert.Equal(t, data, e.Data)
@@ -464,8 +516,8 @@ func TestScopedTrackCalls(t *testing.T) {
464516
assert.NoError(t, err)
465517

466518
events := client.eventProcessor.(*mocks.CapturingEventProcessor).Events
467-
assert.Equal(t, 1, len(events))
468-
e := events[0].(ldevents.CustomEventData)
519+
assert.Equal(t, 2, len(events))
520+
e := events[1].(ldevents.CustomEventData)
469521
assert.Equal(t, ldevents.Context(evalTestUser), e.Context)
470522
assert.Equal(t, key, e.Key)
471523
assert.Equal(t, data, e.Data)
@@ -482,8 +534,8 @@ func TestScopedTrackCalls(t *testing.T) {
482534
assert.NoError(t, err)
483535

484536
events := client.eventProcessor.(*mocks.CapturingEventProcessor).Events
485-
assert.Equal(t, 1, len(events))
486-
e := events[0].(ldevents.CustomEventData)
537+
assert.Equal(t, 2, len(events))
538+
e := events[1].(ldevents.CustomEventData)
487539
assert.Equal(t, ldevents.Context(evalTestUser), e.Context)
488540
assert.Equal(t, key, e.Key)
489541
assert.Equal(t, data, e.Data)
@@ -501,8 +553,8 @@ func TestScopedTrackCalls(t *testing.T) {
501553
assert.NoError(t, err)
502554

503555
events := client.eventProcessor.(*mocks.CapturingEventProcessor).Events
504-
assert.Equal(t, 1, len(events))
505-
e := events[0].(ldevents.CustomEventData)
556+
assert.Equal(t, 2, len(events))
557+
e := events[1].(ldevents.CustomEventData)
506558
assert.Equal(t, ldevents.Context(evalTestUser), e.Context)
507559
assert.Equal(t, key, e.Key)
508560
assert.Equal(t, data, e.Data)

0 commit comments

Comments
 (0)