Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
b5f21bc
fix promise/callback utility: avoid rejecting and returning the promi…
apucacao Mar 26, 2018
c3dcdbb
change EventSerializer to UserFilter
eli-darkly Apr 11, 2018
3689626
Merge branch 'summary-events' into eb/user-filter
eli-darkly Apr 11, 2018
108d3b6
summary events (2): add summary counters
eli-darkly Apr 11, 2018
28e694c
summary events (3): add user deduplication
eli-darkly Apr 11, 2018
2ce74c2
identify events always have an inline user
eli-darkly Apr 11, 2018
a09f98f
summary events (4): break HTTP logic out of event processor, add unit…
eli-darkly Apr 11, 2018
f6d8bea
typo
eli-darkly Apr 11, 2018
43f587e
Merge branch 'eb/ch15917/summary-events-3' into eb/ch15917/summary-ev…
eli-darkly Apr 11, 2018
e424398
summary events (5): implement debug events + misc cleanup, tests
eli-darkly Apr 12, 2018
34f3ab9
added log warning for 401 error
eli-darkly Apr 12, 2018
3cf5f0e
capture all properties from stream patch event
eli-darkly Apr 12, 2018
65fd04c
rm unused
eli-darkly Apr 12, 2018
9c52063
summary events (6): use new schema for eval endpoints and local storage
eli-darkly Apr 12, 2018
6908719
rename file
eli-darkly Apr 12, 2018
79dfe7b
add guard
eli-darkly Apr 12, 2018
93e8805
camelcase config option
eli-darkly Apr 12, 2018
8ac00f4
Merge branch 'eb/ch15917/summary-events-3' into eb/ch15917/summary-ev…
eli-darkly Apr 12, 2018
43e3ff8
camelcase option
eli-darkly Apr 12, 2018
b13cbdb
Merge branch 'eb/ch15917/summary-events-4' into eb/ch15917/summary-ev…
eli-darkly Apr 12, 2018
f3d08f1
Merge branch 'eb/ch15917/summary-events-5' into eb/ch15917/summary-ev…
eli-darkly Apr 12, 2018
fc78d93
misc cleanup
eli-darkly Apr 12, 2018
0ab820f
deprecate snake-cased option names, add camelcased equivalents
eli-darkly Apr 12, 2018
176123f
don't generate index events - so, don't need user keys cache
eli-darkly Apr 16, 2018
5a7f0a3
Merge branch 'eb/ch15917/summary-events-3' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
1d2edd7
Merge branch 'eb/ch15917/summary-events-4' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
0f2be19
Merge branch 'eb/ch15917/summary-events-5' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
22b22dd
options should be last parameter
eli-darkly Apr 16, 2018
5ac8c9e
Merge pull request #46 from launchdarkly/eb/user-filter
eli-darkly Apr 16, 2018
3f2d86b
Merge pull request #52 from launchdarkly/eb/ch11637/camelcase
eli-darkly Apr 16, 2018
e4772a9
Merge branch 'summary-events' into eb/ch15917/summary-events-2
eli-darkly Apr 16, 2018
5f997dc
Merge branch 'eb/ch15917/summary-events-2' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
9c83d6a
rm unused
eli-darkly Apr 16, 2018
297f7c7
Merge branch 'eb/ch15917/summary-events-3' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
5e8d52d
Merge branch 'eb/ch15917/summary-events-4' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
533dc5a
Merge branch 'eb/ch15917/summary-events-5' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
decf215
minor cleanup
eli-darkly Apr 16, 2018
2b3c744
Merge pull request #47 from launchdarkly/eb/ch15917/summary-events-2
eli-darkly Apr 16, 2018
e306d71
Merge branch 'summary-events' into eb/ch15917/summary-events-3
eli-darkly Apr 16, 2018
128ef38
Merge branch 'eb/ch15917/summary-events-3' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
e0cd6b3
Merge branch 'eb/ch15917/summary-events-4' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
4e2677f
Merge branch 'eb/ch15917/summary-events-5' into eb/ch15917/summary-ev…
eli-darkly Apr 16, 2018
c890c5e
Merge pull request #48 from launchdarkly/eb/ch15917/summary-events-3
eli-darkly Apr 17, 2018
54743fc
Merge branch 'summary-events' into ag/ch15352/fix-promise-callback-util
eli-darkly Apr 17, 2018
3f0e4fe
Merge pull request #39 from launchdarkly/ag/ch15352/fix-promise-callb…
eli-darkly Apr 17, 2018
0bbf66f
Merge branch 'summary-events' into eb/ch15917/summary-events-4
eli-darkly Apr 17, 2018
36076d3
Merge branch 'eb/ch15917/summary-events-4' into eb/ch15917/summary-ev…
eli-darkly Apr 17, 2018
90209f4
Merge branch 'eb/ch15917/summary-events-5' into eb/ch15917/summary-ev…
eli-darkly Apr 17, 2018
e1c5267
linter fixes
eli-darkly Apr 18, 2018
f55691c
more linter fixes
eli-darkly Apr 18, 2018
306ba6b
Merge branch 'master' into summary-events
eli-darkly Apr 18, 2018
afd7eab
Merge branch 'summary-events' into eb/ch15917/summary-events-4
eli-darkly Apr 18, 2018
78ea5db
Merge branch 'eb/ch15917/summary-events-4' into eb/ch15917/summary-ev…
eli-darkly Apr 18, 2018
ddab5c0
Merge branch 'eb/ch15917/summary-events-5' into eb/ch15917/summary-ev…
eli-darkly Apr 18, 2018
8161a00
linter fixes
eli-darkly Apr 18, 2018
ced5973
don't create empty request till we're sending something
eli-darkly Apr 19, 2018
fc70169
linter fix
eli-darkly Apr 19, 2018
fb75960
Merge pull request #49 from launchdarkly/eb/ch15917/summary-events-4
eli-darkly Apr 19, 2018
2c13262
Merge branch 'summary-events' into eb/ch15917/summary-events-5
eli-darkly Apr 19, 2018
b0d36e4
Merge branch 'eb/ch15917/summary-events-5' into eb/ch15917/summary-ev…
eli-darkly Apr 19, 2018
cc5e3da
Merge pull request #50 from launchdarkly/eb/ch15917/summary-events-5
eli-darkly Apr 23, 2018
6317376
rename test file
eli-darkly Apr 23, 2018
8e3d23d
Merge pull request #51 from launchdarkly/eb/ch15917/summary-events-6
eli-darkly Apr 23, 2018
1862b73
Merge branch 'master' into summary-events
eli-darkly May 3, 2018
ffcecb5
Merge branch 'master' into summary-events
eli-darkly May 3, 2018
86fc805
Merge branch 'master' into summary-events
eli-darkly May 7, 2018
c570706
Merge branch 'master' into summary-events
eli-darkly May 7, 2018
393132c
Merge branch 'master' into summary-events
eli-darkly May 7, 2018
05d13c3
Merge branch 'master' into summary-events
eli-darkly May 7, 2018
e07ec5d
linter fix
eli-darkly May 7, 2018
d188b6f
Merge branch 'master' into summary-events
eli-darkly May 8, 2018
ec805c3
Merge branch 'master' into summary-events
eli-darkly May 8, 2018
b39b48e
don't suppress variation property in events
eli-darkly May 15, 2018
300216d
fix getTime
eli-darkly May 15, 2018
9cb6182
temporarily disable event caching and extra flag events, to facilitat…
eli-darkly May 15, 2018
6dd749f
comment out more disabled logic
eli-darkly May 15, 2018
269fb50
debugging
eli-darkly May 15, 2018
26b328e
typo
eli-darkly May 15, 2018
39e76b6
linter
eli-darkly May 15, 2018
df27ea6
include variation in summary events
eli-darkly May 15, 2018
6b5af8e
linter
eli-darkly May 15, 2018
8607903
include variation in summary events
eli-darkly May 15, 2018
a22542f
don't generate feature request events for anything other than variati…
eli-darkly May 16, 2018
83720f3
rm debugging
eli-darkly May 16, 2018
e510ca2
Merge pull request #63 from launchdarkly/eb/variation-in-summary
eli-darkly May 16, 2018
2d85869
Merge branch 'summary-events' into integration-testing
eli-darkly May 16, 2018
7aacee4
add config options for suppressing unwanted event behavior
eli-darkly May 16, 2018
81fcf01
change option from suppress to allow
eli-darkly May 16, 2018
c68b0d8
linter
eli-darkly May 16, 2018
e6c9f1f
Merge pull request #64 from launchdarkly/integration-testing
eli-darkly May 16, 2018
d70eefb
tolerate nulls in flags map
eli-darkly May 17, 2018
0ad5864
more null-toleration
eli-darkly May 17, 2018
1382a8f
better handling of null/invalid user
eli-darkly May 17, 2018
b30304b
linter
eli-darkly May 17, 2018
2fa24a0
comment
eli-darkly May 17, 2018
db5ca98
restore hasOwnProperty
eli-darkly May 17, 2018
2c3f894
Merge pull request #65 from launchdarkly/eb/ch17651/tolerate-null-flags
eli-darkly May 18, 2018
0425fa6
use new flagVersion property for events
eli-darkly May 18, 2018
2d987a2
linter
eli-darkly May 18, 2018
9d49db2
Merge pull request #69 from launchdarkly/eb/flag-version
eli-darkly May 18, 2018
85be9eb
if CORS is available, post events to "bulk" endpoint, not to GIF endp…
eli-darkly May 18, 2018
868394d
revise null user logic to be consistent with mobile SDKs
eli-darkly May 22, 2018
0330a5b
Merge pull request #72 from launchdarkly/eb/post-events
eli-darkly May 23, 2018
782210c
Merge branch 'master' into summary-events
eli-darkly May 23, 2018
1f8bd39
rm unnecessary onNextTick
eli-darkly May 23, 2018
24e4ad5
Merge pull request #66 from launchdarkly/eb/ch3948/null-user
eli-darkly May 23, 2018
523a296
add custom user-agent (again) and event schema to headers
eli-darkly May 24, 2018
a3e9cb7
prepare 2.0.0 release
eli-darkly May 26, 2018
1e03708
Merge branch 'master' of https://github.com/launchdarkly/js-client
apucacao May 29, 2018
a935eb4
Merge branch 'master' into eb/ch16913/user-agent-2
eli-darkly May 29, 2018
1898209
Merge pull request #74 from launchdarkly/eb/ch16913/user-agent-2
eli-darkly May 30, 2018
80b3c4a
fix summary key computation
eli-darkly May 31, 2018
844a5ef
Merge pull request #75 from launchdarkly/eb/ch18014/summary-counters
eli-darkly May 31, 2018
5ec4093
version 2.1.0
eli-darkly May 31, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
All notable changes to the LaunchDarkly client-side JavaScript SDK will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org).

## [2.1.0] - 2018-05-31
### Added:
- The client now sends the current SDK version to LaunchDarkly in an HTTP header. This information will be visible in a future version of the LaunchDarkly UI.

### Fixed:
- Fixed a bug that caused summary events to combine the counts for flag evaluations that produced the flag's first variation (variation index 0) with the counts for flag evaluations that fell through to the default value.

## [2.0.0] - 2018-05-25
### Changed
- To reduce the network bandwidth used for analytics events, feature request events are now sent as counters rather than individual events, and user details are now sent only at intervals rather than in each event. These behaviors can be modified through the LaunchDarkly UI and with the new configuration option `inlineUsersInEvents`. For more details, see [Analytics Data Stream Reference](https://docs.launchdarkly.com/v2.0/docs/analytics-data-stream-reference).
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ldclient-js",
"version": "2.0.0",
"version": "2.1.0",
"description": "LaunchDarkly SDK for JavaScript",
"author": "LaunchDarkly <team@launchdarkly.com>",
"license": "Apache-2.0",
Expand Down
2 changes: 2 additions & 0 deletions src/EventSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export default function EventSender(eventsUrl, environmentId, forceHasCors, imag
if (usePost) {
const xhr = new XMLHttpRequest();
xhr.open('POST', postUrl, !sync);
utils.addLDHeaders(xhr);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('X-LaunchDarkly-Event-Schema', '3');

if (!sync) {
xhr.addEventListener('load', () => {
Expand Down
7 changes: 6 additions & 1 deletion src/EventSummarizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ export default function EventSummarizer() {

es.summarizeEvent = function(event) {
if (event.kind === 'feature') {
const counterKey = event.key + ':' + (event.variation || '') + (event.version || '');
const counterKey =
event.key +
':' +
(event.variation !== null && event.variation !== undefined ? event.variation : '') +
':' +
(event.version !== null && event.version !== undefined ? event.version : '');
const counterVal = counters[counterKey];
if (counterVal) {
counterVal.count = counterVal.count + 1;
Expand Down
2 changes: 2 additions & 0 deletions src/Requestor.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ function fetchJSON(endpoint, body, callback) {
if (body) {
xhr.open('REPORT', endpoint);
xhr.setRequestHeader('Content-Type', 'application/json');
utils.addLDHeaders(xhr);
xhr.send(JSON.stringify(body));
} else {
xhr.open('GET', endpoint);
utils.addLDHeaders(xhr);
xhr.send();
}

Expand Down
9 changes: 9 additions & 0 deletions src/__tests__/EventSender-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Base64 from 'Base64';
import sinon from 'sinon';

import EventSender from '../EventSender';
import * as utils from '../utils';

describe('EventSender', () => {
let sandbox;
Expand Down Expand Up @@ -127,5 +128,13 @@ describe('EventSender', () => {
expect(r.method).toEqual('POST');
expect(JSON.parse(r.requestBody)).toEqual(events);
});

it('should send custom user-agent header', () => {
const sender = EventSender(eventsUrl, envId, true);
const event = { kind: 'identify', key: 'userKey' };
sender.sendEvents([event], true);
lastRequest().respond();
expect(lastRequest().requestHeaders['X-LaunchDarkly-User-Agent']).toEqual(utils.getLDUserAgentString());
});
});
});
45 changes: 33 additions & 12 deletions src/__tests__/EventSummarizer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,21 @@ describe('EventSummarizer', () => {
expect(data.endDate).toEqual(2000);
});

function makeEvent(key, version, variation, value, defaultVal) {
return {
kind: 'feature',
creationDate: 1000,
key: key,
version: version,
user: user,
variation: variation,
value: value,
default: defaultVal,
};
}

it('increments counters for feature events', () => {
const es = EventSummarizer();
function makeEvent(key, version, variation, value, defaultVal) {
return {
kind: 'feature',
creationDate: 1000,
key: key,
version: version,
user: user,
variation: variation,
value: value,
default: defaultVal,
};
}
const event1 = makeEvent('key1', 11, 1, 100, 111);
const event2 = makeEvent('key1', 11, 2, 200, 111);
const event3 = makeEvent('key2', 22, 1, 999, 222);
Expand Down Expand Up @@ -77,4 +78,24 @@ describe('EventSummarizer', () => {
};
expect(data.features).toEqual(expectedFeatures);
});

it('distinguishes between zero and null/undefined in feature variation', () => {
const es = EventSummarizer();
const event1 = makeEvent('key1', 11, 0, 100, 111);
const event2 = makeEvent('key1', 11, null, 111, 111);
const event3 = makeEvent('key1', 11, undefined, 111, 111);
es.summarizeEvent(event1);
es.summarizeEvent(event2);
es.summarizeEvent(event3);
const data = es.getSummary();

data.features.key1.counters.sort((a, b) => a.value - b.value);
const expectedFeatures = {
key1: {
default: 111,
counters: [{ variation: 0, value: 100, version: 11, count: 1 }, { value: 111, version: 11, count: 2 }],
},
};
expect(data.features).toEqual(expectedFeatures);
});
});
19 changes: 19 additions & 0 deletions src/__tests__/Requestor-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sinon from 'sinon';
import Requestor from '../Requestor';
import * as utils from '../utils';

describe('Requestor', () => {
let server;
Expand Down Expand Up @@ -83,4 +84,22 @@ describe('Requestor', () => {
expect(handleFour.calledOnce).toEqual(true);
expect(handleFive.calledOnce).toEqual(true);
});

it('should send custom user-agent header in GET mode', () => {
const requestor = Requestor('http://requestee', 'FAKE_ENV', false);
const user = { key: 'foo' };
requestor.fetchFlagSettings(user, 'hash1', sinon.spy());

expect(server.requests.length).toEqual(1);
expect(server.requests[0].requestHeaders['X-LaunchDarkly-User-Agent']).toEqual(utils.getLDUserAgentString());
});

it('should send custom user-agent header in REPORT mode', () => {
const requestor = Requestor('http://requestee', 'FAKE_ENV', true);
const user = { key: 'foo' };
requestor.fetchFlagSettings(user, 'hash1', sinon.spy());

expect(server.requests.length).toEqual(1);
expect(server.requests[0].requestHeaders['X-LaunchDarkly-User-Agent']).toEqual(utils.getLDUserAgentString());
});
});
8 changes: 8 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,11 @@ export function chunkUserEventsForUrl(maxLength, events) {

return allChunks;
}

export function getLDUserAgentString() {
return 'JSClient/' + VERSION;
}

export function addLDHeaders(xhr) {
xhr.setRequestHeader('X-LaunchDarkly-User-Agent', getLDUserAgentString());
}