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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "launchdarkly-js-sdk-common",
3
- "version": "5.7.0-beta.1",
3
+ "version": "5.7.0-beta.3",
4
4
  "description": "LaunchDarkly SDK for JavaScript - common code",
5
5
  "author": "LaunchDarkly <team@launchdarkly.com>",
6
6
  "license": "Apache-2.0",
@@ -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
- const summarizer = MultiEventSummarizer(contextFilter, () => platform.hasherFactory('sha256'));
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
- // const summary = summarizer.getSummary();
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
@@ -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
- import { hashContext } from './context';
2
- import EventSummarizer from './EventSummarizer';
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',