launchdarkly-js-sdk-common 5.7.0-beta.1 → 5.7.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/EventProcessor.js
CHANGED
|
@@ -5,6 +5,7 @@ const errors = require('./errors');
|
|
|
5
5
|
const messages = require('./messages');
|
|
6
6
|
const utils = require('./utils');
|
|
7
7
|
const { getContextKeys } = require('./context');
|
|
8
|
+
const EventSummarizer = require('./EventSummarizer');
|
|
8
9
|
|
|
9
10
|
function EventProcessor(
|
|
10
11
|
platform,
|
|
@@ -18,7 +19,12 @@ function EventProcessor(
|
|
|
18
19
|
const eventSender = sender || EventSender(platform, environmentId, options);
|
|
19
20
|
const mainEventsUrl = utils.appendUrlPath(options.eventsUrl, '/events/bulk/' + environmentId);
|
|
20
21
|
const contextFilter = ContextFilter(options);
|
|
21
|
-
|
|
22
|
+
// If the platform has a hasherFactory, use the MultiEventSummarizer, otherwise use the EventSummarizer.
|
|
23
|
+
// Generally packages should be pinning a specific version of the common SDK, but this will handle them potentially
|
|
24
|
+
// being mis-matched.
|
|
25
|
+
const summarizer = platform.hasherFactory
|
|
26
|
+
? MultiEventSummarizer(contextFilter, () => platform.hasherFactory('sha256'))
|
|
27
|
+
: new EventSummarizer();
|
|
22
28
|
const samplingInterval = options.samplingInterval;
|
|
23
29
|
const eventCapacity = options.eventCapacity;
|
|
24
30
|
const flushInterval = options.flushInterval;
|
|
@@ -129,12 +135,7 @@ function EventProcessor(
|
|
|
129
135
|
eventsToSend.push(summary);
|
|
130
136
|
}
|
|
131
137
|
});
|
|
132
|
-
|
|
133
|
-
// summarizer.clearSummary();
|
|
134
|
-
// if (summary) {
|
|
135
|
-
// summary.kind = 'summary';
|
|
136
|
-
// eventsToSend.push(summary);
|
|
137
|
-
// }
|
|
138
|
+
|
|
138
139
|
if (diagnosticsAccumulator) {
|
|
139
140
|
// For diagnostic events, we record how many events were in the queue at the last flush (since "how
|
|
140
141
|
// many events happened to be in the queue at the moment we decided to send a diagnostic event" would
|
package/src/EventSummarizer.js
CHANGED
|
@@ -93,6 +93,13 @@ function EventSummarizer() {
|
|
|
93
93
|
};
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
+
es.getSummaries = () => {
|
|
97
|
+
const summary = es.getSummary();
|
|
98
|
+
const summaries = summary ? [summary] : [];
|
|
99
|
+
es.clearSummary();
|
|
100
|
+
return summaries;
|
|
101
|
+
};
|
|
102
|
+
|
|
96
103
|
es.clearSummary = () => {
|
|
97
104
|
startDate = 0;
|
|
98
105
|
endDate = 0;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const { hashContext } = require('./context');
|
|
2
|
+
const EventSummarizer = require('./EventSummarizer');
|
|
3
|
+
|
|
3
4
|
/**
|
|
4
5
|
*
|
|
5
6
|
* @param {{filter: (context: any) => any}} contextFilter
|
|
@@ -525,5 +525,135 @@ describe.each([
|
|
|
525
525
|
expect(diagnosticAccumulator.getProps().droppedEvents).toEqual(2);
|
|
526
526
|
});
|
|
527
527
|
});
|
|
528
|
+
|
|
529
|
+
it('uses EventSummarizer when platform has no hasherFactory', async () => {
|
|
530
|
+
const event = {
|
|
531
|
+
kind: 'feature',
|
|
532
|
+
creationDate: 1000,
|
|
533
|
+
context: eventContext,
|
|
534
|
+
key: 'flagkey',
|
|
535
|
+
version: 11,
|
|
536
|
+
variation: 1,
|
|
537
|
+
value: 'value',
|
|
538
|
+
default: 'default',
|
|
539
|
+
trackEvents: true,
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
const platformWithoutHasher = { ...platform };
|
|
543
|
+
delete platformWithoutHasher.hasherFactory;
|
|
544
|
+
|
|
545
|
+
const sender = MockEventSender();
|
|
546
|
+
const ep = EventProcessor(platformWithoutHasher, defaultConfig, envId, null, null, sender);
|
|
547
|
+
try {
|
|
548
|
+
ep.enqueue(event);
|
|
549
|
+
await ep.flush();
|
|
550
|
+
|
|
551
|
+
expect(sender.calls.length()).toEqual(1);
|
|
552
|
+
const output = (await sender.calls.take()).events;
|
|
553
|
+
expect(output.length).toEqual(2);
|
|
554
|
+
checkFeatureEvent(output[0], event, false, eventContext);
|
|
555
|
+
checkSummaryEvent(output[1]);
|
|
556
|
+
|
|
557
|
+
// Verify the summary event doesn't have a context field when there's no hasherFactory
|
|
558
|
+
const summaryEvent = output[1];
|
|
559
|
+
expect(summaryEvent.context).toBeUndefined();
|
|
560
|
+
expect(summaryEvent.features).toEqual({
|
|
561
|
+
flagkey: {
|
|
562
|
+
contextKinds: ['user'],
|
|
563
|
+
default: 'default',
|
|
564
|
+
counters: [{ version: 11, variation: 1, value: 'value', count: 1 }],
|
|
565
|
+
},
|
|
566
|
+
});
|
|
567
|
+
} finally {
|
|
568
|
+
ep.stop();
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
it('uses MultiEventSummarizer when platform has hasherFactory', async () => {
|
|
573
|
+
const event = {
|
|
574
|
+
kind: 'feature',
|
|
575
|
+
creationDate: 1000,
|
|
576
|
+
context: eventContext,
|
|
577
|
+
key: 'flagkey',
|
|
578
|
+
version: 11,
|
|
579
|
+
variation: 1,
|
|
580
|
+
value: 'value',
|
|
581
|
+
default: 'default',
|
|
582
|
+
trackEvents: true,
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
// Stub platform hash a hasher factory.
|
|
586
|
+
|
|
587
|
+
const sender = MockEventSender();
|
|
588
|
+
const ep = EventProcessor(platform, defaultConfig, envId, null, null, sender);
|
|
589
|
+
try {
|
|
590
|
+
ep.enqueue(event);
|
|
591
|
+
await ep.flush();
|
|
592
|
+
|
|
593
|
+
expect(sender.calls.length()).toEqual(1);
|
|
594
|
+
const output = (await sender.calls.take()).events;
|
|
595
|
+
expect(output.length).toEqual(2);
|
|
596
|
+
checkFeatureEvent(output[0], event, false, eventContext);
|
|
597
|
+
checkSummaryEvent(output[1]);
|
|
598
|
+
|
|
599
|
+
// Verify that when MultiEventSummarizer is used, context is included in the summary
|
|
600
|
+
const summaryEvent = output[1];
|
|
601
|
+
expect(summaryEvent.context).toEqual(eventContext);
|
|
602
|
+
expect(summaryEvent.features).toEqual({
|
|
603
|
+
flagkey: {
|
|
604
|
+
contextKinds: ['user'],
|
|
605
|
+
default: 'default',
|
|
606
|
+
counters: [{ version: 11, variation: 1, value: 'value', count: 1 }],
|
|
607
|
+
},
|
|
608
|
+
});
|
|
609
|
+
} finally {
|
|
610
|
+
ep.stop();
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
it('filters context in summary events when using MultiEventSummarizer', async () => {
|
|
615
|
+
const event = {
|
|
616
|
+
kind: 'feature',
|
|
617
|
+
creationDate: 1000,
|
|
618
|
+
context: eventContext,
|
|
619
|
+
key: 'flagkey',
|
|
620
|
+
version: 11,
|
|
621
|
+
variation: 1,
|
|
622
|
+
value: 'value',
|
|
623
|
+
default: 'default',
|
|
624
|
+
trackEvents: true,
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
// Configure with allAttributesPrivate set to true
|
|
628
|
+
const config = { ...defaultConfig, allAttributesPrivate: true };
|
|
629
|
+
|
|
630
|
+
const sender = MockEventSender();
|
|
631
|
+
const ep = EventProcessor(platform, config, envId, null, null, sender);
|
|
632
|
+
try {
|
|
633
|
+
ep.enqueue(event);
|
|
634
|
+
await ep.flush();
|
|
635
|
+
|
|
636
|
+
expect(sender.calls.length()).toEqual(1);
|
|
637
|
+
const output = (await sender.calls.take()).events;
|
|
638
|
+
expect(output.length).toEqual(2);
|
|
639
|
+
|
|
640
|
+
// Verify the feature event has filtered context
|
|
641
|
+
checkFeatureEvent(output[0], event, false, filteredContext);
|
|
642
|
+
|
|
643
|
+
// Verify the summary event has filtered context
|
|
644
|
+
const summaryEvent = output[1];
|
|
645
|
+
checkSummaryEvent(summaryEvent);
|
|
646
|
+
expect(summaryEvent.context).toEqual(filteredContext);
|
|
647
|
+
expect(summaryEvent.features).toEqual({
|
|
648
|
+
flagkey: {
|
|
649
|
+
contextKinds: ['user'],
|
|
650
|
+
default: 'default',
|
|
651
|
+
counters: [{ version: 11, variation: 1, value: 'value', count: 1 }],
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
} finally {
|
|
655
|
+
ep.stop();
|
|
656
|
+
}
|
|
657
|
+
});
|
|
528
658
|
});
|
|
529
659
|
});
|
|
@@ -33,6 +33,38 @@ describe('EventSummarizer', () => {
|
|
|
33
33
|
expect(data.endDate).toEqual(2000);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
it('returns summaries for feature events', () => {
|
|
37
|
+
// getSummaries returns the single summary from getSummary(), but wrapped in an array.
|
|
38
|
+
const es = EventSummarizer();
|
|
39
|
+
const event1 = { kind: 'feature', creationDate: 2000, key: 'key', user: user };
|
|
40
|
+
const event2 = { kind: 'feature', creationDate: 1000, key: 'key', user: user };
|
|
41
|
+
const event3 = { kind: 'feature', creationDate: 1500, key: 'key', user: user };
|
|
42
|
+
es.summarizeEvent(event1);
|
|
43
|
+
es.summarizeEvent(event2);
|
|
44
|
+
es.summarizeEvent(event3);
|
|
45
|
+
const summaries = es.getSummaries();
|
|
46
|
+
|
|
47
|
+
expect(summaries[0].startDate).toEqual(1000);
|
|
48
|
+
expect(summaries[0].endDate).toEqual(2000);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('clears summaries when getSummaries is called', () => {
|
|
52
|
+
const es = EventSummarizer();
|
|
53
|
+
const event1 = { kind: 'feature', creationDate: 2000, key: 'key', user: user };
|
|
54
|
+
const event2 = { kind: 'feature', creationDate: 1000, key: 'key', user: user };
|
|
55
|
+
es.summarizeEvent(event1);
|
|
56
|
+
es.summarizeEvent(event2);
|
|
57
|
+
const summaries = es.getSummaries();
|
|
58
|
+
expect(summaries[0].startDate).toEqual(1000);
|
|
59
|
+
expect(summaries[0].endDate).toEqual(2000);
|
|
60
|
+
expect(es.getSummaries()).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('returns empty array if no summaries are available', () => {
|
|
64
|
+
const es = EventSummarizer();
|
|
65
|
+
expect(es.getSummaries()).toEqual([]);
|
|
66
|
+
});
|
|
67
|
+
|
|
36
68
|
function makeEvent(key, version, variation, value, defaultVal) {
|
|
37
69
|
return {
|
|
38
70
|
kind: 'feature',
|