Skip to content

Commit 111bb08

Browse files
committed
add entityId
1 parent 2f18c13 commit 111bb08

File tree

5 files changed

+116
-34
lines changed

5 files changed

+116
-34
lines changed

src/assignment-logger.ts

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,22 @@ export type NullableHoldoutVariationType = HoldoutVariationEnum | null;
1313
*/
1414

1515
export interface IAssignmentEvent {
16-
/**
17-
* An Eppo allocation key
18-
*/
16+
/** * An Eppo allocation key */
1917
allocation: string | null;
2018

21-
/**
22-
* An Eppo experiment key
23-
*/
19+
/** * An Eppo experiment key */
2420
experiment: string | null;
2521

26-
/**
27-
* An Eppo feature flag key
28-
*/
22+
/** * An Eppo feature flag key */
2923
featureFlag: string;
3024

31-
/**
32-
* The assigned variation
33-
*/
25+
/** * The assigned variation */
3426
variation: string | null;
3527

36-
/**
37-
* The entity or user that was assigned to a variation
38-
*/
28+
/** * The entity or user that was assigned to a variation */
3929
subject: string;
4030

41-
/**
42-
* The time the subject was exposed to the variation.
43-
*/
31+
/** * The time the subject was exposed to the variation. */
4432
timestamp: string;
4533

4634
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -49,15 +37,14 @@ export interface IAssignmentEvent {
4937

5038
metaData?: Record<string, unknown>;
5139

52-
/**
53-
* The format of the flag.
54-
*/
40+
/** * The format of the flag. */
5541
format: string;
5642

57-
/**
58-
* The flag evaluation details. Null if the flag was precomputed.
59-
*/
43+
/** * The flag evaluation details. Null if the flag was precomputed. */
6044
evaluationDetails: IFlagEvaluationDetails | null;
45+
46+
/** * The entity ID of the subject, if present. */
47+
entityId?: number;
6148
}
6249

6350
/**

src/client/eppo-client.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1288,7 +1288,7 @@ export default class EppoClient {
12881288
});
12891289
}
12901290

1291-
private maybeLogAssignment(result: FlagEvaluation) {
1291+
private maybeLogAssignment(result: FlagEvaluation & { entityId?: number }) {
12921292
const {
12931293
flagKey,
12941294
format,
@@ -1298,6 +1298,7 @@ export default class EppoClient {
12981298
variation,
12991299
flagEvaluationDetails,
13001300
extraLogging = {},
1301+
entityId,
13011302
} = result;
13021303
const event: IAssignmentEvent = {
13031304
...extraLogging,
@@ -1311,6 +1312,7 @@ export default class EppoClient {
13111312
subjectAttributes,
13121313
metaData: this.buildLoggerMetadata(),
13131314
evaluationDetails: flagEvaluationDetails,
1315+
entityId,
13141316
};
13151317

13161318
if (variation && allocationKey) {

src/eppo-assignment-logger.spec.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { IAssignmentEvent } from './assignment-logger';
2+
import EppoClient from './client/eppo-client';
3+
import { IConfigurationStore } from './configuration-store/configuration-store';
4+
import { EppoAssignmentLogger } from './eppo-assignment-logger';
5+
import { Flag } from './interfaces';
6+
7+
jest.mock('./client/eppo-client');
8+
9+
describe('EppoAssignmentLogger', () => {
10+
let mockEppoClient: jest.Mocked<EppoClient>;
11+
let logger: EppoAssignmentLogger;
12+
13+
beforeEach(() => {
14+
jest.clearAllMocks();
15+
mockEppoClient = new EppoClient({
16+
flagConfigurationStore: {} as IConfigurationStore<Flag>,
17+
}) as jest.Mocked<EppoClient>;
18+
mockEppoClient.track = jest.fn();
19+
logger = new EppoAssignmentLogger(mockEppoClient);
20+
});
21+
22+
it('should log assignment events correctly', () => {
23+
// Arrange
24+
const assignmentEvent: IAssignmentEvent = {
25+
subject: 'user-123',
26+
experiment: 'experiment-abc',
27+
variant: 'control',
28+
entityId: 456, // Changed to number
29+
holdoutKey: 'holdout-xyz',
30+
holdoutVariation: 'holdout-variant-1',
31+
// Add required properties based on the IAssignmentEvent interface
32+
allocation: 'allocation-1',
33+
featureFlag: 'feature-flag-1',
34+
variation: 'variation-1',
35+
timestamp: new Date().toISOString(),
36+
subjectAttributes: {},
37+
flagKey: 'flag-key-1',
38+
format: 'json',
39+
evaluationDetails: null,
40+
};
41+
42+
// Act
43+
logger.logAssignment(assignmentEvent);
44+
45+
// Assert
46+
expect(mockEppoClient.track).toHaveBeenCalledTimes(1);
47+
expect(mockEppoClient.track).toHaveBeenCalledWith('__eppo_assignment', {
48+
subject_id: 'user-123',
49+
experiment: 'experiment-abc',
50+
variant: 'control',
51+
entity_id: 456,
52+
holdout: 'holdout-xyz',
53+
holdout_variant: 'holdout-variant-1',
54+
});
55+
});
56+
57+
it('should handle missing optional fields', () => {
58+
// Arrange
59+
const assignmentEvent: IAssignmentEvent = {
60+
subject: 'user-123',
61+
experiment: 'experiment-abc',
62+
variant: 'control',
63+
// Add required properties based on the IAssignmentEvent interface
64+
allocation: 'allocation-1',
65+
featureFlag: 'feature-flag-1',
66+
variation: 'variation-1',
67+
timestamp: new Date().toISOString(),
68+
subjectAttributes: {},
69+
flagKey: 'flag-key-1',
70+
format: 'json',
71+
evaluationDetails: null,
72+
};
73+
74+
// Act
75+
logger.logAssignment(assignmentEvent);
76+
77+
// Assert
78+
expect(mockEppoClient.track).toHaveBeenCalledTimes(1);
79+
expect(mockEppoClient.track).toHaveBeenCalledWith('__eppo_assignment', {
80+
subject_id: 'user-123',
81+
experiment: 'experiment-abc',
82+
variant: 'control',
83+
entity_id: undefined,
84+
holdout: undefined,
85+
holdout_variant: undefined,
86+
});
87+
});
88+
});

src/eppo-assignment-logger.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
import { IAssignmentEvent, IAssignmentLogger } from './assignment-logger';
22
import EppoClient from './client/eppo-client';
33

4-
/** TODO docs */
4+
/**
5+
* Tracks an assignment event by submitting it to the Eppo Ingestion API.
6+
* Events are queued up for delivery according to the EppoClient's `EventDispatcher` implementation.
7+
*/
58
export class EppoAssignmentLogger implements IAssignmentLogger {
69
constructor(private readonly eppoClient: EppoClient) {}
710

811
logAssignment(event: IAssignmentEvent): void {
9-
const entity = event.subjectAttributes.entity;
1012
const {
13+
entityId: entity_id,
14+
experiment,
1115
holdoutKey: holdout,
1216
holdoutVariation: holdout_variant,
1317
subject: subject_id,
14-
experiment,
1518
variant,
1619
} = event;
17-
this.eppoClient.track('__eppo_assignment', {
18-
subject_id,
20+
const payload = {
21+
entity_id,
1922
experiment,
20-
variant,
21-
entity,
22-
holdout,
2323
holdout_variant,
24-
});
24+
holdout,
25+
subject_id,
26+
variant,
27+
};
28+
this.eppoClient.track('__eppo_assignment', payload);
2529
}
2630
}

src/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export interface Flag {
5959
variations: Record<string, Variation>;
6060
allocations: Allocation[];
6161
totalShards: number;
62+
entityId?: number;
6263
}
6364

6465
export interface ObfuscatedFlag {

0 commit comments

Comments
 (0)