Skip to content

Commit 075fc43

Browse files
committed
Updated the javascript client to call the new heartbeats api
1 parent 18a36d0 commit 075fc43

14 files changed

+90
-69
lines changed

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 1.3.{build}
1+
version: 1.4.{build}
22

33
install:
44
- ps: Install-Product node 5

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "exceptionless",
3-
"version": "1.3.2",
3+
"version": "1.4.0",
44
"description": "JavaScript client for Exceptionless",
55
"license": "Apache-2.0",
66
"main": "dist/exceptionless.js",

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "exceptionless",
3-
"version": "1.3.2",
3+
"version": "1.4.0",
44
"description": "JavaScript client for Exceptionless",
55
"license": "Apache-2.0",
66
"main": "dist/exceptionless.node.js",
@@ -29,24 +29,24 @@
2929
"devDependencies": {
3030
"chai": "3.5.0",
3131
"del": "2.2.0",
32-
"es5-shim": "4.5.7",
32+
"es5-shim": "4.5.8",
3333
"es6-shim": "0.35.0",
3434
"gulp": "3.9.1",
3535
"gulp-concat": "2.6.0",
3636
"gulp-exec": "2.1.2",
3737
"gulp-mocha": "2.2.0",
3838
"gulp-replace": "0.5.4",
3939
"gulp-sourcemaps": "1.6.0",
40-
"gulp-tslint": "4.3.4",
40+
"gulp-tslint": "5.0.0",
4141
"gulp-uglify": "1.5.3",
4242
"gulp-wrap-umd": "0.2.1",
4343
"rimraf": "2.5.2",
4444
"source-map-support": "0.4.0",
45-
"mock-fs": "3.8.0",
46-
"tracekit": "0.3.2",
47-
"tslint": "3.6.0",
48-
"tsproject": "1.2.0",
49-
"typescript": "1.8.9",
45+
"mock-fs": "3.9.0",
46+
"tracekit": "0.3.5",
47+
"tslint": "3.8.1",
48+
"tsproject": "1.2.1",
49+
"typescript": "1.8.10",
5050
"typescript-formatter": "2.1.0"
5151
},
5252
"dependencies": {

src/ExceptionlessClient.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,16 @@ export class ExceptionlessClient {
101101
this.createSessionStart().submit(callback);
102102
}
103103

104-
public createSessionEnd(): EventBuilder {
105-
return this.createEvent().setType('sessionend');
106-
}
107-
108-
public submitSessionEnd(callback?: (context: EventPluginContext) => void): void {
109-
this.createSessionEnd().submit(callback);
110-
}
111-
112-
public createSessionHeartbeat(): EventBuilder {
113-
return this.createEvent().setType('heartbeat');
104+
public submitSessionEnd(sessionIdOrUserId: string): void {
105+
if (sessionIdOrUserId) {
106+
this.config.submissionClient.sendHeartbeat(sessionIdOrUserId, true, this.config);
107+
}
114108
}
115109

116-
public submitSessionHeartbeat(callback?: (context: EventPluginContext) => void): void {
117-
this.createSessionHeartbeat().submit(callback);
110+
public submitSessionHeartbeat(sessionIdOrUserId: string): void {
111+
if (sessionIdOrUserId) {
112+
this.config.submissionClient.sendHeartbeat(sessionIdOrUserId, false, this.config);
113+
}
118114
}
119115

120116
public createEvent(pluginContextData?: ContextData): EventBuilder {

src/configuration/Configuration.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export class Configuration implements IConfigurationSettings {
9797
this.log = inject(configSettings.log) || new NullLog();
9898
this.apiKey = configSettings.apiKey;
9999
this.serverUrl = configSettings.serverUrl;
100+
this.heartbeatServerUrl = configSettings.heartbeatServerUrl;
100101

101102
this.environmentInfoCollector = inject(configSettings.environmentInfoCollector);
102103
this.errorParser = inject(configSettings.errorParser);
@@ -167,10 +168,37 @@ export class Configuration implements IConfigurationSettings {
167168
public set serverUrl(value: string) {
168169
if (!!value) {
169170
this._serverUrl = value;
171+
this._heartbeatServerUrl = value;
170172
this.log.info(`serverUrl: ${this._serverUrl}`);
171173
}
172174
}
173175

176+
/**
177+
* The heartbeat server url that all heartbeats will be sent to.
178+
* @type {string}
179+
* @private
180+
*/
181+
private _heartbeatServerUrl: string = 'https://heartbeat.exceptionless.io';
182+
183+
/**
184+
* The heartbeat server url that all heartbeats will be sent to.
185+
* @returns {string}
186+
*/
187+
public get heartbeatServerUrl(): string {
188+
return this._heartbeatServerUrl;
189+
}
190+
191+
/**
192+
* The heartbeat server url that all heartbeats will be sent to.
193+
* @param value
194+
*/
195+
public set heartbeatServerUrl(value: string) {
196+
if (!!value) {
197+
this._heartbeatServerUrl = value;
198+
this.log.info(`heartbeatServerUrl: ${this._heartbeatServerUrl}`);
199+
}
200+
}
201+
174202
/**
175203
* A list of exclusion patterns.
176204
* @type {Array}
@@ -352,9 +380,9 @@ export class Configuration implements IConfigurationSettings {
352380
/**
353381
* Automatically send a heartbeat to keep the session alive.
354382
*/
355-
public useSessions(sendHeartbeats: boolean = true): void {
383+
public useSessions(sendHeartbeats: boolean = true, heartbeatInterval: number = 30000): void {
356384
if (sendHeartbeats) {
357-
this.addPlugin(new HeartbeatPlugin());
385+
this.addPlugin(new HeartbeatPlugin(heartbeatInterval));
358386
}
359387
}
360388

src/configuration/IConfigurationSettings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { ISubmissionClient } from '../submission/ISubmissionClient';
1212
export interface IConfigurationSettings {
1313
apiKey?: string;
1414
serverUrl?: string;
15+
heartbeatServerUrl?: string;
1516
environmentInfoCollector?: IEnvironmentInfoCollector;
1617
errorParser?: IErrorParser;
1718
lastReferenceIdManager?: ILastReferenceIdManager;

src/plugins/default/HeartbeatPlugin.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ export class HeartbeatPlugin implements IEventPlugin {
66
public priority: number = 100;
77
public name: string = 'HeartbeatPlugin';
88

9+
private _heartbeatInterval: number;
910
private _heartbeatIntervalId: any;
10-
private _lastUser: IUserInfo;
11+
12+
constructor (heartbeatInterval: number = 30000) {
13+
this._heartbeatInterval = heartbeatInterval;
14+
}
15+
1116

1217
public run(context: EventPluginContext, next?: () => void): void {
1318
let clearHeartbeatInterval = () => {
@@ -17,24 +22,13 @@ export class HeartbeatPlugin implements IEventPlugin {
1722
}
1823
};
1924

20-
let type = context.event.type;
21-
if (type !== 'heartbeat') {
22-
if (type === 'sessionend') {
23-
clearHeartbeatInterval();
24-
} else {
25-
let user: IUserInfo = context.event.data['@user'];
26-
if (user && user.identity) {
27-
let submitHeartbeatFn = () => context.client.createSessionHeartbeat().setUserIdentity(user).submit();
28-
29-
if (!this._heartbeatIntervalId) {
30-
this._lastUser = user;
31-
} else {
32-
clearHeartbeatInterval();
33-
}
34-
35-
this._heartbeatIntervalId = setInterval(submitHeartbeatFn, 30000);
36-
}
37-
}
25+
if (this._heartbeatIntervalId) {
26+
clearHeartbeatInterval();
27+
}
28+
29+
let user: IUserInfo = context.event.data['@user'];
30+
if (user && user.identity) {
31+
this._heartbeatIntervalId = setInterval(() => context.client.submitSessionHeartbeat(user.identity), this._heartbeatInterval);
3832
}
3933

4034
next && next();

src/submission/DefaultSubmissionAdapter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { SubmissionRequest } from './SubmissionRequest';
55
declare var XDomainRequest: { new (); create(); };
66

77
export class DefaultSubmissionAdapter implements ISubmissionAdapter {
8-
public sendRequest(request: SubmissionRequest, callback: SubmissionCallback, isAppExiting?: boolean) {
8+
public sendRequest(request: SubmissionRequest, callback?: SubmissionCallback, isAppExiting?: boolean) {
99
// TODO: Handle sending events when app is exiting with send beacon.
1010
const TIMEOUT: string = 'timeout'; // optimization for minifier.
1111
const LOADED: string = 'loaded'; // optimization for minifier.
@@ -62,7 +62,7 @@ export class DefaultSubmissionAdapter implements ISubmissionAdapter {
6262
}
6363
}
6464

65-
callback(status || 500, message || '', responseText, parseResponseHeaders(xhr.getAllResponseHeaders && xhr.getAllResponseHeaders()));
65+
callback && callback(status || 500, message || '', responseText, parseResponseHeaders(xhr.getAllResponseHeaders && xhr.getAllResponseHeaders()));
6666
}
6767

6868
function createRequest(userAgent: string, method: string, url: string): XMLHttpRequest {
@@ -89,10 +89,10 @@ export class DefaultSubmissionAdapter implements ISubmissionAdapter {
8989
return xhr;
9090
}
9191

92-
let url = `${request.serverUrl}${request.path}?access_token=${encodeURIComponent(request.apiKey)}`;
92+
let url = `${request.url}?access_token=${encodeURIComponent(request.apiKey)}`;
9393
let xhr = createRequest(request.userAgent, request.method || 'POST', url);
9494
if (!xhr) {
95-
return callback(503, 'CORS not supported.');
95+
return (callback && callback(503, 'CORS not supported.'));
9696
}
9797

9898
if (WITH_CREDENTIALS in xhr) {

src/submission/DefaultSubmissionClient-spec.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class TestAdapter implements ISubmissionAdapter {
3434
return this;
3535
}
3636

37-
public sendRequest(request: SubmissionRequest, callback: SubmissionCallback, isAppExiting?: boolean) {
37+
public sendRequest(request: SubmissionRequest, callback?: SubmissionCallback, isAppExiting?: boolean) {
3838
this.request = request;
3939
this.callback = callback;
4040

@@ -50,7 +50,7 @@ class TestAdapter implements ISubmissionAdapter {
5050
}
5151

5252
this.checks.forEach(c => c(this.request));
53-
this.callback(this.status, this.message, this.data, this.headers);
53+
this.callback && this.callback(this.status, this.message, this.data, this.headers);
5454
}
5555
}
5656

@@ -72,7 +72,6 @@ describe('DefaultSubmissionClient', () => {
7272

7373
adapter = new TestAdapter(r => {
7474
expect(r.apiKey).to.equal(apiKey);
75-
expect(r.serverUrl).to.equal(serverUrl);
7675
});
7776

7877
config.submissionAdapter = adapter;
@@ -84,7 +83,7 @@ describe('DefaultSubmissionClient', () => {
8483
adapter.withCheck(r => {
8584
expect(r.data).to.equal(JSON.stringify(events));
8685
expect(r.method).to.equal('POST');
87-
expect(r.path).to.equal('/api/v2/events');
86+
expect(r.url).to.equal(`${config.serverUrl}/api/v2/events`);
8887
});
8988

9089
submissionClient.postEvents(events, config, () => done());
@@ -103,7 +102,7 @@ describe('DefaultSubmissionClient', () => {
103102
adapter.withCheck(r => {
104103
expect(r.data).to.equal(JSON.stringify(events));
105104
expect(r.method).to.equal('POST');
106-
expect(r.path).to.equal('/api/v2/events');
105+
expect(r.url).to.equal(`${config.serverUrl}/api/v2/events`);
107106
});
108107

109108
submissionClient.postEvents(events, config, () => done());
@@ -120,7 +119,7 @@ describe('DefaultSubmissionClient', () => {
120119
adapter.withCheck(r => {
121120
expect(r.data).to.equal(JSON.stringify(description));
122121
expect(r.method).to.equal('POST');
123-
expect(r.path).to.equal('/api/v2/events/by-ref/123454321/user-description');
122+
expect(r.url).to.equal(`${config.serverUrl}/api/v2/events/by-ref/123454321/user-description`);
124123
});
125124

126125
submissionClient.postUserDescription('123454321', description, config, () => done());
@@ -129,7 +128,6 @@ describe('DefaultSubmissionClient', () => {
129128
});
130129

131130
it('should get project settings', (done) => {
132-
133131
adapter.withResponse(200, null, JSON.stringify({ version: 1 }));
134132

135133
submissionClient.getSettings(config, response => {

src/submission/DefaultSubmissionClient.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ export class DefaultSubmissionClient implements ISubmissionClient {
1515

1616
public postEvents(events: IEvent[], config: Configuration, callback: (response: SubmissionResponse) => void, isAppExiting?: boolean): void {
1717
let data = JSON.stringify(events);
18-
let request = this.createRequest(config, 'POST', '/api/v2/events', data);
18+
let request = this.createRequest(config, 'POST', `${config.serverUrl}/api/v2/events`, data);
1919
let cb = this.createSubmissionCallback(config, callback);
2020

2121
return config.submissionAdapter.sendRequest(request, cb, isAppExiting);
2222
}
2323

2424
public postUserDescription(referenceId: string, description: IUserDescription, config: Configuration, callback: (response: SubmissionResponse) => void): void {
25-
let path = `/api/v2/events/by-ref/${encodeURIComponent(referenceId)}/user-description`;
25+
let path = `${config.serverUrl}/api/v2/events/by-ref/${encodeURIComponent(referenceId)}/user-description`;
2626
let data = JSON.stringify(description);
2727
let request = this.createRequest(config, 'POST', path, data);
2828
let cb = this.createSubmissionCallback(config, callback);
@@ -31,7 +31,7 @@ export class DefaultSubmissionClient implements ISubmissionClient {
3131
}
3232

3333
public getSettings(config: Configuration, callback: (response: SettingsResponse) => void): void {
34-
let request = this.createRequest(config, 'GET', '/api/v2/projects/config');
34+
let request = this.createRequest(config, 'GET', `${config.serverUrl}/api/v2/projects/config`);
3535
let cb = (status, message, data?, headers?) => {
3636
if (status !== 200) {
3737
return callback(new SettingsResponse(false, null, -1, null, message));
@@ -54,12 +54,16 @@ export class DefaultSubmissionClient implements ISubmissionClient {
5454
return config.submissionAdapter.sendRequest(request, cb);
5555
}
5656

57-
private createRequest(config: Configuration, method: string, path: string, data: string = null): SubmissionRequest {
57+
public sendHeartbeat(sessionIdOrUserId: string, closeSession: boolean, config: Configuration): void {
58+
let request = this.createRequest(config, 'GET', `${config.heartbeatServerUrl}/api/v2/events/session/heartbeat?id=${sessionIdOrUserId}&close=${closeSession}`);
59+
config.submissionAdapter.sendRequest(request);
60+
}
61+
62+
private createRequest(config: Configuration, method: string, url: string, data: string = null): SubmissionRequest {
5863
return {
5964
method,
60-
path,
65+
url,
6166
data,
62-
serverUrl: config.serverUrl,
6367
apiKey: config.apiKey,
6468
userAgent: config.userAgent
6569
};

0 commit comments

Comments
 (0)