Skip to content

Commit de9ae8b

Browse files
authored
feat: Add support for tracking arbitrary events (#136)
* feat: Add support for tracking arbitrary events * fix tests and refactor ctor * cleanup imports
1 parent 8957ebf commit de9ae8b

13 files changed

+277
-120
lines changed

src/application-logger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export const loggerPrefix = '[Eppo SDK]';
44

55
// Create a Pino logger instance
66
export const logger = pino({
7-
level: process.env.NODE_ENV === 'production' ? 'warn' : 'info',
7+
level: process.env.LOG_LEVEL ?? (process.env.NODE_ENV === 'production' ? 'warn' : 'info'),
88
// https://getpino.io/#/docs/browser
99
browser: { disabled: true },
1010
});

src/client/eppo-client-assignment-details.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('EppoClient get*AssignmentDetails', () => {
3333
});
3434

3535
it('should set the details for a matched rule', () => {
36-
const client = new EppoClient(storage);
36+
const client = new EppoClient({ flagConfigurationStore: storage });
3737
client.setIsGracefulFailureMode(false);
3838
const subjectAttributes = { email: '[email protected]', country: 'US' };
3939
const result = client.getIntegerAssignmentDetails(
@@ -85,7 +85,7 @@ describe('EppoClient get*AssignmentDetails', () => {
8585
});
8686

8787
it('should set the details for a matched split', () => {
88-
const client = new EppoClient(storage);
88+
const client = new EppoClient({ flagConfigurationStore: storage });
8989
client.setIsGracefulFailureMode(false);
9090
const subjectAttributes = { email: '[email protected]', country: 'Brazil' };
9191
const result = client.getIntegerAssignmentDetails(
@@ -128,7 +128,7 @@ describe('EppoClient get*AssignmentDetails', () => {
128128
});
129129

130130
it('should handle matching a split allocation with a matched rule', () => {
131-
const client = new EppoClient(storage);
131+
const client = new EppoClient({ flagConfigurationStore: storage });
132132
client.setIsGracefulFailureMode(false);
133133
const subjectAttributes = { id: 'alice', email: '[email protected]', country: 'Brazil' };
134134
const result = client.getStringAssignmentDetails(
@@ -190,7 +190,7 @@ describe('EppoClient get*AssignmentDetails', () => {
190190
});
191191

192192
it('should handle unrecognized flags', () => {
193-
const client = new EppoClient(storage);
193+
const client = new EppoClient({ flagConfigurationStore: storage });
194194
client.setIsGracefulFailureMode(false);
195195
const result = client.getIntegerAssignmentDetails('asdf', 'alice', {}, 0);
196196
expect(result).toEqual({
@@ -215,7 +215,7 @@ describe('EppoClient get*AssignmentDetails', () => {
215215
});
216216

217217
it('should handle type mismatches with graceful failure mode enabled', () => {
218-
const client = new EppoClient(storage);
218+
const client = new EppoClient({ flagConfigurationStore: storage });
219219
client.setIsGracefulFailureMode(true);
220220
const result = client.getBooleanAssignmentDetails('integer-flag', 'alice', {}, true);
221221
expect(result).toEqual({
@@ -252,7 +252,7 @@ describe('EppoClient get*AssignmentDetails', () => {
252252
});
253253

254254
it('should throw an error for type mismatches with graceful failure mode disabled', () => {
255-
const client = new EppoClient(storage);
255+
const client = new EppoClient({ flagConfigurationStore: storage });
256256
client.setIsGracefulFailureMode(false);
257257
expect(() => client.getBooleanAssignmentDetails('integer-flag', 'alice', {}, true)).toThrow();
258258
});
@@ -302,7 +302,7 @@ describe('EppoClient get*AssignmentDetails', () => {
302302
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
303303
const subject = subjects.find((subject) => subject.subjectKey === subjectKey)!;
304304

305-
const client = new EppoClient(storage);
305+
const client = new EppoClient({ flagConfigurationStore: storage });
306306
client.setIsGracefulFailureMode(false);
307307

308308
const focusOn = {

src/client/eppo-client-experiment-container.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe('getExperimentContainerEntry', () => {
3131
beforeEach(async () => {
3232
const storage = new MemoryOnlyConfigurationStore<Flag | ObfuscatedFlag>();
3333
await initConfiguration(storage);
34-
client = new EppoClient(storage);
34+
client = new EppoClient({ flagConfigurationStore: storage });
3535
client.setIsGracefulFailureMode(true);
3636
flagExperiment = {
3737
flagKey: 'my-key',

src/client/eppo-client-with-bandits.spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@ describe('EppoClient Bandits E2E test', () => {
6666
});
6767

6868
beforeEach(() => {
69-
client = new EppoClient(flagStore, banditVariationStore, banditModelStore, undefined, false);
69+
client = new EppoClient({
70+
flagConfigurationStore: flagStore,
71+
banditVariationConfigurationStore: banditVariationStore,
72+
banditModelConfigurationStore: banditModelStore,
73+
isObfuscated: false,
74+
});
7075
client.setIsGracefulFailureMode(false);
7176
client.setAssignmentLogger({ logAssignment: mockLogAssignment });
7277
client.setBanditLogger({ logBanditAction: mockLogBanditAction });

src/client/eppo-client.spec.ts

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('EppoClient E2E test', () => {
7676

7777
beforeAll(() => {
7878
storage.setEntries({ [flagKey]: mockFlag });
79-
client = new EppoClient(storage);
79+
client = new EppoClient({ flagConfigurationStore: storage });
8080

8181
td.replace(EppoClient.prototype, 'getAssignmentDetail', function () {
8282
throw new Error('Mock test error');
@@ -137,7 +137,7 @@ describe('EppoClient E2E test', () => {
137137
it('Invokes logger for queued events', () => {
138138
const mockLogger = td.object<IAssignmentLogger>();
139139

140-
const client = new EppoClient(storage);
140+
const client = new EppoClient({ flagConfigurationStore: storage });
141141
client.getStringAssignment(flagKey, 'subject-to-be-logged', {}, 'default-value');
142142
client.setAssignmentLogger(mockLogger);
143143

@@ -150,7 +150,7 @@ describe('EppoClient E2E test', () => {
150150
it('Does not log same queued event twice', () => {
151151
const mockLogger = td.object<IAssignmentLogger>();
152152

153-
const client = new EppoClient(storage);
153+
const client = new EppoClient({ flagConfigurationStore: storage });
154154

155155
client.getStringAssignment(flagKey, 'subject-to-be-logged', {}, 'default-value');
156156
client.setAssignmentLogger(mockLogger);
@@ -161,7 +161,7 @@ describe('EppoClient E2E test', () => {
161161

162162
it('Does not invoke logger for events that exceed queue size', () => {
163163
const mockLogger = td.object<IAssignmentLogger>();
164-
const client = new EppoClient(storage);
164+
const client = new EppoClient({ flagConfigurationStore: storage });
165165

166166
times(MAX_EVENT_QUEUE_SIZE + 100, (i) =>
167167
client.getStringAssignment(flagKey, `subject-to-be-logged-${i}`, {}, 'default-value'),
@@ -199,7 +199,7 @@ describe('EppoClient E2E test', () => {
199199

200200
it.each(Object.keys(testCases))('test variation assignment splits - %s', async (fileName) => {
201201
const { flag, variationType, defaultValue, subjects } = testCases[fileName];
202-
const client = new EppoClient(storage);
202+
const client = new EppoClient({ flagConfigurationStore: storage });
203203
client.setIsGracefulFailureMode(false);
204204

205205
let assignments: {
@@ -253,7 +253,7 @@ describe('EppoClient E2E test', () => {
253253

254254
it.each(Object.keys(testCases))('test variation assignment splits - %s', async (fileName) => {
255255
const { flag, variationType, defaultValue, subjects } = testCases[fileName];
256-
const client = new EppoClient(storage, undefined, undefined, undefined, true);
256+
const client = new EppoClient({ flagConfigurationStore: storage, isObfuscated: true });
257257
client.setIsGracefulFailureMode(false);
258258

259259
const typeAssignmentFunctions = {
@@ -285,15 +285,17 @@ describe('EppoClient E2E test', () => {
285285
});
286286

287287
it('returns null if getStringAssignment was called for the subject before any UFC was loaded', () => {
288-
const localClient = new EppoClient(new MemoryOnlyConfigurationStore());
288+
const localClient = new EppoClient({
289+
flagConfigurationStore: new MemoryOnlyConfigurationStore(),
290+
});
289291
expect(localClient.getStringAssignment(flagKey, 'subject-1', {}, 'hello world')).toEqual(
290292
'hello world',
291293
);
292294
expect(localClient.isInitialized()).toBe(false);
293295
});
294296

295297
it('returns default value when key does not exist', async () => {
296-
const client = new EppoClient(storage);
298+
const client = new EppoClient({ flagConfigurationStore: storage });
297299

298300
const nonExistentFlag = 'non-existent-flag';
299301

@@ -310,7 +312,7 @@ describe('EppoClient E2E test', () => {
310312
const mockLogger = td.object<IAssignmentLogger>();
311313

312314
storage.setEntries({ [flagKey]: mockFlag });
313-
const client = new EppoClient(storage);
315+
const client = new EppoClient({ flagConfigurationStore: storage });
314316
client.setAssignmentLogger(mockLogger);
315317

316318
const subjectAttributes = { foo: 3 };
@@ -336,7 +338,7 @@ describe('EppoClient E2E test', () => {
336338
td.when(mockLogger.logAssignment(td.matchers.anything())).thenThrow(new Error('logging error'));
337339

338340
storage.setEntries({ [flagKey]: mockFlag });
339-
const client = new EppoClient(storage);
341+
const client = new EppoClient({ flagConfigurationStore: storage });
340342
client.setAssignmentLogger(mockLogger);
341343

342344
const subjectAttributes = { foo: 3 };
@@ -352,7 +354,7 @@ describe('EppoClient E2E test', () => {
352354

353355
it('exports flag configuration', () => {
354356
storage.setEntries({ [flagKey]: mockFlag });
355-
const client = new EppoClient(storage);
357+
const client = new EppoClient({ flagConfigurationStore: storage });
356358
expect(client.getFlagConfigurations()).toEqual({ [flagKey]: mockFlag });
357359
});
358360

@@ -364,7 +366,7 @@ describe('EppoClient E2E test', () => {
364366
mockLogger = td.object<IAssignmentLogger>();
365367

366368
storage.setEntries({ [flagKey]: mockFlag });
367-
client = new EppoClient(storage);
369+
client = new EppoClient({ flagConfigurationStore: storage });
368370
client.setAssignmentLogger(mockLogger);
369371
});
370372

@@ -617,7 +619,10 @@ describe('EppoClient E2E test', () => {
617619
});
618620

619621
it('Fetches initial configuration with parameters in constructor', async () => {
620-
client = new EppoClient(thisFlagStorage, undefined, undefined, requestConfiguration);
622+
client = new EppoClient({
623+
flagConfigurationStore: thisFlagStorage,
624+
configurationRequestParameters: requestConfiguration,
625+
});
621626
client.setIsGracefulFailureMode(false);
622627
// no configuration loaded
623628
let variation = client.getNumericAssignment(flagKey, subject, {}, 123.4);
@@ -629,7 +634,7 @@ describe('EppoClient E2E test', () => {
629634
});
630635

631636
it('Fetches initial configuration with parameters provided later', async () => {
632-
client = new EppoClient(thisFlagStorage);
637+
client = new EppoClient({ flagConfigurationStore: thisFlagStorage });
633638
client.setIsGracefulFailureMode(false);
634639
client.setConfigurationRequestParameters(requestConfiguration);
635640
// no configuration loaded
@@ -651,9 +656,12 @@ describe('EppoClient E2E test', () => {
651656
}
652657
}
653658

654-
client = new EppoClient(new MockStore(), undefined, undefined, {
655-
...requestConfiguration,
656-
pollAfterSuccessfulInitialization: true,
659+
client = new EppoClient({
660+
flagConfigurationStore: new MockStore(),
661+
configurationRequestParameters: {
662+
...requestConfiguration,
663+
pollAfterSuccessfulInitialization: true,
664+
},
657665
});
658666
client.setIsGracefulFailureMode(false);
659667
// no configuration loaded
@@ -680,7 +688,10 @@ describe('EppoClient E2E test', () => {
680688
}
681689
}
682690

683-
client = new EppoClient(new MockStore(), undefined, undefined, requestConfiguration);
691+
client = new EppoClient({
692+
flagConfigurationStore: new MockStore(),
693+
configurationRequestParameters: requestConfiguration,
694+
});
684695
client.setIsGracefulFailureMode(false);
685696
// no configuration loaded
686697
let variation = client.getNumericAssignment(flagKey, subject, {}, 0.0);
@@ -722,7 +733,10 @@ describe('EppoClient E2E test', () => {
722733
...requestConfiguration,
723734
pollAfterSuccessfulInitialization,
724735
};
725-
client = new EppoClient(thisFlagStorage, undefined, undefined, requestConfiguration);
736+
client = new EppoClient({
737+
flagConfigurationStore: thisFlagStorage,
738+
configurationRequestParameters: requestConfiguration,
739+
});
726740
client.setIsGracefulFailureMode(false);
727741
// no configuration loaded
728742
let variation = client.getNumericAssignment(flagKey, subject, {}, 0.0);
@@ -787,7 +801,10 @@ describe('EppoClient E2E test', () => {
787801
throwOnFailedInitialization,
788802
pollAfterFailedInitialization,
789803
};
790-
client = new EppoClient(thisFlagStorage, undefined, undefined, requestConfiguration);
804+
client = new EppoClient({
805+
flagConfigurationStore: thisFlagStorage,
806+
configurationRequestParameters: requestConfiguration,
807+
});
791808
client.setIsGracefulFailureMode(false);
792809
// no configuration loaded
793810
expect(client.getNumericAssignment(flagKey, subject, {}, 0.0)).toBe(0.0);

0 commit comments

Comments
 (0)