@webex/internal-plugin-metrics 3.0.0-beta.31 → 3.0.0-beta.310
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/dist/batcher.js +2 -1
- package/dist/batcher.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +66 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +456 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js +830 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +337 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
- package/dist/call-diagnostic/config.js +610 -0
- package/dist/call-diagnostic/config.js.map +1 -0
- package/dist/client-metrics-batcher.js +2 -1
- package/dist/client-metrics-batcher.js.map +1 -1
- package/dist/config.js +22 -2
- package/dist/config.js.map +1 -1
- package/dist/index.js +30 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +30 -30
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js +7 -0
- package/dist/metrics.types.js.map +1 -0
- package/dist/new-metrics.js +333 -0
- package/dist/new-metrics.js.map +1 -0
- package/dist/types/batcher.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +194 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +411 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +96 -0
- package/dist/types/call-diagnostic/config.d.ts +172 -0
- package/dist/types/client-metrics-batcher.d.ts +2 -0
- package/dist/types/config.d.ts +36 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/metrics.d.ts +3 -0
- package/dist/types/metrics.types.d.ts +104 -0
- package/dist/types/new-metrics.d.ts +139 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/utils.js +27 -0
- package/dist/utils.js.map +1 -0
- package/package.json +13 -8
- package/src/batcher.js +1 -0
- package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +83 -0
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +414 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +896 -0
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +362 -0
- package/src/call-diagnostic/config.ts +666 -0
- package/src/client-metrics-batcher.js +1 -0
- package/src/config.js +20 -0
- package/src/index.ts +43 -0
- package/src/metrics.js +25 -27
- package/src/metrics.types.ts +160 -0
- package/src/new-metrics.ts +317 -0
- package/src/utils.ts +17 -0
- package/test/unit/spec/batcher.js +2 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +465 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +477 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +2012 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +565 -0
- package/test/unit/spec/client-metrics-batcher.js +2 -0
- package/test/unit/spec/metrics.js +66 -97
- package/test/unit/spec/new-metrics.ts +269 -0
- package/test/unit/spec/utils.ts +22 -0
- package/tsconfig.json +6 -0
- package/dist/call-diagnostic-events-batcher.js +0 -60
- package/dist/call-diagnostic-events-batcher.js.map +0 -1
- package/src/call-diagnostic-events-batcher.js +0 -62
- package/src/index.js +0 -17
- package/test/unit/spec/call-diagnostic-events-batcher.js +0 -195
|
@@ -8,6 +8,9 @@ import {Token, Credentials} from '@webex/webex-core';
|
|
|
8
8
|
import FakeTimers from '@sinonjs/fake-timers';
|
|
9
9
|
import sinon from 'sinon';
|
|
10
10
|
import Metrics, {config} from '@webex/internal-plugin-metrics';
|
|
11
|
+
import {BrowserDetection} from '@webex/common';
|
|
12
|
+
|
|
13
|
+
const {getOSVersion} = BrowserDetection();
|
|
11
14
|
|
|
12
15
|
function promiseTick(count) {
|
|
13
16
|
let promise = Promise.resolve();
|
|
@@ -82,6 +85,7 @@ describe('plugin-metrics', () => {
|
|
|
82
85
|
return Promise.resolve({
|
|
83
86
|
statusCode: 204,
|
|
84
87
|
body: undefined,
|
|
88
|
+
waitForServiceTimeout: 15,
|
|
85
89
|
options,
|
|
86
90
|
});
|
|
87
91
|
};
|
|
@@ -102,7 +106,6 @@ describe('plugin-metrics', () => {
|
|
|
102
106
|
sinon.spy(webex, 'request');
|
|
103
107
|
sinon.spy(metrics, 'postPreLoginMetric');
|
|
104
108
|
sinon.spy(metrics, 'aliasUser');
|
|
105
|
-
sinon.spy(metrics, 'submitCallDiagnosticEvents');
|
|
106
109
|
});
|
|
107
110
|
|
|
108
111
|
describe('#submit()', () => {
|
|
@@ -131,6 +134,67 @@ describe('plugin-metrics', () => {
|
|
|
131
134
|
});
|
|
132
135
|
});
|
|
133
136
|
|
|
137
|
+
describe('#getClientMetricsPayload()', () => {
|
|
138
|
+
it('returns the expected payload', () => {
|
|
139
|
+
webex.credentials.supertoken = new Token(
|
|
140
|
+
{
|
|
141
|
+
access_token: 'a_b_orgid',
|
|
142
|
+
},
|
|
143
|
+
{parent: webex}
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const testPayload = {
|
|
147
|
+
tags: {success: true},
|
|
148
|
+
fields: {perceivedDurationInMillis: 314},
|
|
149
|
+
context: {},
|
|
150
|
+
eventPayload: {value: 'splunk business metric payload'},
|
|
151
|
+
};
|
|
152
|
+
const date = clock.now;
|
|
153
|
+
|
|
154
|
+
const result = metrics.getClientMetricsPayload('test', testPayload);
|
|
155
|
+
|
|
156
|
+
assert.deepEqual(result, {
|
|
157
|
+
context: {
|
|
158
|
+
app: {
|
|
159
|
+
version: undefined,
|
|
160
|
+
},
|
|
161
|
+
locale: 'en-US',
|
|
162
|
+
os: {
|
|
163
|
+
name: 'other',
|
|
164
|
+
version: getOSVersion(),
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
eventPayload: {
|
|
168
|
+
value: 'splunk business metric payload',
|
|
169
|
+
},
|
|
170
|
+
fields: {
|
|
171
|
+
browser_version: '',
|
|
172
|
+
client_id: 'fake',
|
|
173
|
+
os_version: getOSVersion(),
|
|
174
|
+
perceivedDurationInMillis: 314,
|
|
175
|
+
platform: 'Web',
|
|
176
|
+
sdk_version: undefined,
|
|
177
|
+
spark_user_agent: 'webex-js-sdk appName/appVersion appPlatform',
|
|
178
|
+
},
|
|
179
|
+
metricName: 'test',
|
|
180
|
+
tags: {
|
|
181
|
+
browser: '',
|
|
182
|
+
domain: 'whatever',
|
|
183
|
+
os: 'other',
|
|
184
|
+
success: true,
|
|
185
|
+
},
|
|
186
|
+
timestamp: 0,
|
|
187
|
+
type: ['operational'],
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('throws when no event name is specified', () => {
|
|
192
|
+
assert.throws(() => {
|
|
193
|
+
metrics.getClientMetricsPayload();
|
|
194
|
+
}, 'Missing behavioral metric name. Please provide one');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
134
198
|
describe('#submitClientMetrics()', () => {
|
|
135
199
|
describe('before login', () => {
|
|
136
200
|
it('posts pre-login metric', () => {
|
|
@@ -199,17 +263,15 @@ describe('plugin-metrics', () => {
|
|
|
199
263
|
assert.property(metric, 'eventPayload');
|
|
200
264
|
|
|
201
265
|
assert.property(metric.tags, 'browser');
|
|
202
|
-
assert.property(metric.tags, 'org_id');
|
|
203
266
|
assert.property(metric.tags, 'os');
|
|
204
267
|
assert.property(metric.tags, 'domain');
|
|
205
|
-
assert.property(metric.tags, 'client_id');
|
|
206
|
-
assert.property(metric.tags, 'user_id');
|
|
207
268
|
|
|
208
269
|
assert.property(metric.fields, 'browser_version');
|
|
209
270
|
assert.property(metric.fields, 'os_version');
|
|
210
271
|
assert.property(metric.fields, 'sdk_version');
|
|
211
272
|
assert.property(metric.fields, 'platform');
|
|
212
273
|
assert.property(metric.fields, 'spark_user_agent');
|
|
274
|
+
assert.property(metric.fields, 'client_id');
|
|
213
275
|
|
|
214
276
|
assert.property(metric.context, 'app');
|
|
215
277
|
assert.property(metric.context, 'locale');
|
|
@@ -269,98 +331,5 @@ describe('plugin-metrics', () => {
|
|
|
269
331
|
assert.match(params, {alias: true});
|
|
270
332
|
}));
|
|
271
333
|
});
|
|
272
|
-
|
|
273
|
-
describe('#submitCallDiagnosticEvents()', () => {
|
|
274
|
-
it('submits a call diagnostic event', () => {
|
|
275
|
-
const promise = metrics.submitCallDiagnosticEvents(mockCallDiagnosticEvent);
|
|
276
|
-
|
|
277
|
-
return promiseTick(50)
|
|
278
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
279
|
-
.then(() => promise)
|
|
280
|
-
.then(() => {
|
|
281
|
-
assert.calledOnce(webex.request);
|
|
282
|
-
const req = webex.request.args[0][0];
|
|
283
|
-
const metric = req.body.metrics[0];
|
|
284
|
-
|
|
285
|
-
assert.property(metric.eventPayload, 'origin');
|
|
286
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
287
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
288
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
289
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
290
|
-
assert.equal(metric.eventPayload.origin.buildType, 'test');
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('submits a call diagnostic event with buildType set in the payload', () => {
|
|
295
|
-
const promise = metrics.submitCallDiagnosticEvents({
|
|
296
|
-
...mockCallDiagnosticEvent,
|
|
297
|
-
origin: {
|
|
298
|
-
buildType: 'prod',
|
|
299
|
-
},
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
return promiseTick(50)
|
|
303
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
304
|
-
.then(() => promise)
|
|
305
|
-
.then(() => {
|
|
306
|
-
assert.calledOnce(webex.request);
|
|
307
|
-
const req = webex.request.args[0][0];
|
|
308
|
-
const metric = req.body.metrics[0];
|
|
309
|
-
|
|
310
|
-
assert.property(metric.eventPayload, 'origin');
|
|
311
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
312
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
313
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
314
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
315
|
-
assert.equal(metric.eventPayload.origin.buildType, 'prod');
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
xit('submits a call diagnostic event with a test domain', () => {
|
|
320
|
-
global.window.location.hostname = 'test.webex.com';
|
|
321
|
-
|
|
322
|
-
const promise = metrics.submitCallDiagnosticEvents(mockCallDiagnosticEvent);
|
|
323
|
-
|
|
324
|
-
return promiseTick(50)
|
|
325
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
326
|
-
.then(() => promise)
|
|
327
|
-
.then(() => {
|
|
328
|
-
assert.calledOnce(webex.request);
|
|
329
|
-
const req = webex.request.args[0][0];
|
|
330
|
-
const metric = req.body.metrics[0];
|
|
331
|
-
|
|
332
|
-
assert.property(metric.eventPayload, 'origin');
|
|
333
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
334
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
335
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
336
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
337
|
-
assert.equal(metric.eventPayload.origin.buildType, 'test');
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
// Skip because it's current unable to overwrite NODE_ENV
|
|
342
|
-
// However doing `NODE_ENV=test npm run test ...` will get this test case to pass
|
|
343
|
-
xit('submits a call diagnostic event with a NODE_ENV=production', () => {
|
|
344
|
-
process.env.NODE_ENV = 'production';
|
|
345
|
-
|
|
346
|
-
const promise = metrics.submitCallDiagnosticEvents(mockCallDiagnosticEvent);
|
|
347
|
-
|
|
348
|
-
return promiseTick(50)
|
|
349
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
350
|
-
.then(() => promise)
|
|
351
|
-
.then(() => {
|
|
352
|
-
assert.calledOnce(webex.request);
|
|
353
|
-
const req = webex.request.args[0][0];
|
|
354
|
-
const metric = req.body.metrics[0];
|
|
355
|
-
|
|
356
|
-
assert.property(metric.eventPayload, 'origin');
|
|
357
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
358
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
359
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
360
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
361
|
-
assert.equal(metric.eventPayload.origin.buildType, 'prod');
|
|
362
|
-
});
|
|
363
|
-
});
|
|
364
|
-
});
|
|
365
334
|
});
|
|
366
335
|
});
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import {assert} from '@webex/test-helper-chai';
|
|
2
|
+
import {NewMetrics} from '@webex/internal-plugin-metrics';
|
|
3
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
4
|
+
import sinon from 'sinon';
|
|
5
|
+
import {Utils} from '@webex/internal-plugin-metrics';
|
|
6
|
+
|
|
7
|
+
describe('internal-plugin-metrics', () => {
|
|
8
|
+
|
|
9
|
+
describe('check submitClientEvent when webex is not ready', () => {
|
|
10
|
+
let webex;
|
|
11
|
+
//@ts-ignore
|
|
12
|
+
webex = new MockWebex({
|
|
13
|
+
children: {
|
|
14
|
+
newMetrics: NewMetrics,
|
|
15
|
+
},
|
|
16
|
+
meetings: {
|
|
17
|
+
meetingCollection: {
|
|
18
|
+
get: sinon.stub(),
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
request: sinon.stub().resolves({}),
|
|
22
|
+
logger: {
|
|
23
|
+
log: sinon.stub(),
|
|
24
|
+
error: sinon.stub(),
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('checks the log', () => {
|
|
29
|
+
webex.internal.newMetrics.submitClientEvent({
|
|
30
|
+
name: 'client.alert.displayed',
|
|
31
|
+
options: {
|
|
32
|
+
meetingId: '123',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
assert.calledWith(
|
|
36
|
+
webex.logger.log,
|
|
37
|
+
'NewMetrics: @submitClientEvent. Attempted to submit before webex.ready. Event name: client.alert.displayed'
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('new-metrics', () => {
|
|
43
|
+
let webex;
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
//@ts-ignore
|
|
47
|
+
webex = new MockWebex({
|
|
48
|
+
children: {
|
|
49
|
+
newMetrics: NewMetrics,
|
|
50
|
+
},
|
|
51
|
+
meetings: {
|
|
52
|
+
meetingCollection: {
|
|
53
|
+
get: sinon.stub(),
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
request: sinon.stub().resolves({}),
|
|
57
|
+
logger: {
|
|
58
|
+
log: sinon.stub(),
|
|
59
|
+
error: sinon.stub(),
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
webex.emit('ready');
|
|
64
|
+
|
|
65
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
|
66
|
+
webex.internal.newMetrics.callDiagnosticLatencies.clearTimestamps = sinon.stub();
|
|
67
|
+
webex.internal.newMetrics.callDiagnosticMetrics.submitClientEvent = sinon.stub();
|
|
68
|
+
webex.internal.newMetrics.callDiagnosticMetrics.submitMQE = sinon.stub();
|
|
69
|
+
webex.internal.newMetrics.callDiagnosticMetrics.clientMetricsAliasUser = sinon.stub();
|
|
70
|
+
webex.internal.newMetrics.callDiagnosticMetrics.postPreLoginMetric = sinon.stub();
|
|
71
|
+
webex.internal.newMetrics.callDiagnosticMetrics.buildClientEventFetchRequestOptions =
|
|
72
|
+
sinon.stub();
|
|
73
|
+
webex.setTimingsAndFetch = sinon.stub();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
afterEach(() => {
|
|
77
|
+
sinon.restore();
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('submits Client Event successfully', () => {
|
|
81
|
+
webex.internal.newMetrics.submitClientEvent({
|
|
82
|
+
name: 'client.alert.displayed',
|
|
83
|
+
options: {
|
|
84
|
+
meetingId: '123',
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
|
89
|
+
key: 'client.alert.displayed',
|
|
90
|
+
options: {meetingId: '123'},
|
|
91
|
+
});
|
|
92
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticMetrics.submitClientEvent, {
|
|
93
|
+
name: 'client.alert.displayed',
|
|
94
|
+
payload: undefined,
|
|
95
|
+
options: {meetingId: '123'},
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
it('submits MQE successfully', () => {
|
|
101
|
+
webex.internal.newMetrics.submitMQE({
|
|
102
|
+
name: 'client.mediaquality.event',
|
|
103
|
+
//@ts-ignore
|
|
104
|
+
payload: {intervals: [{}]},
|
|
105
|
+
options: {
|
|
106
|
+
meetingId: '123',
|
|
107
|
+
networkType: 'wifi',
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
|
112
|
+
key: 'client.mediaquality.event',
|
|
113
|
+
});
|
|
114
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticMetrics.submitMQE, {
|
|
115
|
+
name: 'client.mediaquality.event',
|
|
116
|
+
//@ts-ignore
|
|
117
|
+
payload: {intervals: [{}]},
|
|
118
|
+
options: {
|
|
119
|
+
meetingId: '123',
|
|
120
|
+
networkType: 'wifi',
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('submits Internal Event successfully', () => {
|
|
126
|
+
webex.internal.newMetrics.submitInternalEvent({
|
|
127
|
+
name: 'client.mediaquality.event',
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
|
131
|
+
key: 'client.mediaquality.event',
|
|
132
|
+
});
|
|
133
|
+
assert.notCalled(webex.internal.newMetrics.callDiagnosticLatencies.clearTimestamps);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('submits Internal Event successfully for clearing the join latencies', () => {
|
|
137
|
+
webex.internal.newMetrics.submitInternalEvent({
|
|
138
|
+
name: 'internal.reset.join.latencies',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
assert.notCalled(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp);
|
|
142
|
+
assert.calledOnce(webex.internal.newMetrics.callDiagnosticLatencies.clearTimestamps);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe('#clientMetricsAliasUser', () => {
|
|
146
|
+
it('aliases the user correctly', async () => {
|
|
147
|
+
webex.request.resolves({response: 'abc'});
|
|
148
|
+
await webex.internal.newMetrics.clientMetricsAliasUser('my-id');
|
|
149
|
+
assert.calledWith(webex.request, {
|
|
150
|
+
method: 'POST',
|
|
151
|
+
api: 'metrics',
|
|
152
|
+
resource: 'clientmetrics',
|
|
153
|
+
headers: { 'x-prelogin-userid': 'my-id' },
|
|
154
|
+
body: {},
|
|
155
|
+
qs: { alias: true },
|
|
156
|
+
});
|
|
157
|
+
assert.calledWith(
|
|
158
|
+
webex.logger.log,
|
|
159
|
+
'NewMetrics: @clientMetricsAliasUser. Request successful:',
|
|
160
|
+
{ response: 'abc' }
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('handles failed request correctly', async () => {
|
|
165
|
+
webex.request.rejects(new Error("test error"));
|
|
166
|
+
sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError')
|
|
167
|
+
try {
|
|
168
|
+
await webex.internal.newMetrics.clientMetricsAliasUser({event: 'test'}, 'my-id');
|
|
169
|
+
} catch (err) {
|
|
170
|
+
assert.calledWith(
|
|
171
|
+
webex.logger.error,
|
|
172
|
+
'NewMetrics: @clientMetricsAliasUser. Request failed:',
|
|
173
|
+
`err: formattedError`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('#postPreLoginMetric', () => {
|
|
180
|
+
it('sends the request correctly', async () => {
|
|
181
|
+
webex.request.resolves({response: 'abc'});
|
|
182
|
+
await webex.internal.newMetrics.postPreLoginMetric({event: 'test'}, 'my-id');
|
|
183
|
+
assert.calledWith(webex.request, {
|
|
184
|
+
method: 'POST',
|
|
185
|
+
api: 'metrics',
|
|
186
|
+
resource: 'clientmetrics-prelogin',
|
|
187
|
+
headers: { 'x-prelogin-userid': 'my-id', authorization: false },
|
|
188
|
+
body: {metrics: [{event: 'test'}]},
|
|
189
|
+
});
|
|
190
|
+
assert.calledWith(
|
|
191
|
+
webex.logger.log,
|
|
192
|
+
'NewMetrics: @postPreLoginMetric. Request successful:',
|
|
193
|
+
{ response: 'abc' }
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('handles failed request correctly', async () => {
|
|
198
|
+
webex.request.rejects(new Error("test error"));
|
|
199
|
+
sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError')
|
|
200
|
+
try {
|
|
201
|
+
await webex.internal.newMetrics.postPreLoginMetric({event: 'test'}, 'my-id');
|
|
202
|
+
} catch (err) {
|
|
203
|
+
assert.calledWith(
|
|
204
|
+
webex.logger.error,
|
|
205
|
+
'NewMetrics: @postPreLoginMetric. Request failed:',
|
|
206
|
+
`err: formattedError`
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
describe('#buildClientEventFetchRequestOptions', () => {
|
|
213
|
+
it('builds client event fetch options successfully', () => {
|
|
214
|
+
webex.internal.newMetrics.buildClientEventFetchRequestOptions({
|
|
215
|
+
name: 'client.alert.displayed',
|
|
216
|
+
options: {
|
|
217
|
+
meetingId: '123',
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
assert.calledWith(
|
|
222
|
+
webex.internal.newMetrics.callDiagnosticMetrics.buildClientEventFetchRequestOptions,
|
|
223
|
+
{
|
|
224
|
+
name: 'client.alert.displayed',
|
|
225
|
+
payload: undefined,
|
|
226
|
+
options: {meetingId: '123'},
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('#setMetricTimingsAndFetch', () => {
|
|
233
|
+
beforeEach(() => {
|
|
234
|
+
global.fetch = sinon.stub();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('calls fetch with the expected options', () => {
|
|
238
|
+
const now = new Date();
|
|
239
|
+
sinon.useFakeTimers(now.getTime());
|
|
240
|
+
|
|
241
|
+
webex.internal.newMetrics.setMetricTimingsAndFetch({
|
|
242
|
+
json: true,
|
|
243
|
+
body: JSON.stringify({metrics: [{eventPayload: {}}]}),
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const expected = {
|
|
247
|
+
json: true,
|
|
248
|
+
body: JSON.stringify({
|
|
249
|
+
metrics: [
|
|
250
|
+
{
|
|
251
|
+
eventPayload: {
|
|
252
|
+
originTime: {
|
|
253
|
+
triggered: now.toISOString(),
|
|
254
|
+
sent: now.toISOString(),
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
}),
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
sinon.assert.calledOnce(webex.setTimingsAndFetch);
|
|
263
|
+
sinon.assert.calledWith(webex.setTimingsAndFetch, expected);
|
|
264
|
+
|
|
265
|
+
sinon.restore();
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {assert} from '@webex/test-helper-chai';
|
|
2
|
+
import {Utils} from '@webex/internal-plugin-metrics';
|
|
3
|
+
|
|
4
|
+
describe('internal-plugin-metrics', () => {
|
|
5
|
+
describe('generateCommonErrorMetadata', () => {
|
|
6
|
+
it('should return JSON stringified error object', () => {
|
|
7
|
+
const error = new Error('test error');
|
|
8
|
+
const result = Utils.generateCommonErrorMetadata(error);
|
|
9
|
+
assert.deepEqual(result, JSON.stringify({
|
|
10
|
+
message: 'test error',
|
|
11
|
+
name: 'Error',
|
|
12
|
+
stack: error.stack
|
|
13
|
+
}))
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should return error if not instanceof Error', () => {
|
|
17
|
+
const error = 'test error';
|
|
18
|
+
const result = Utils.generateCommonErrorMetadata(error);
|
|
19
|
+
assert.deepEqual(result, 'test error')
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
})
|
package/tsconfig.json
ADDED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
|
|
4
|
-
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
|
|
5
|
-
_Object$defineProperty(exports, "__esModule", {
|
|
6
|
-
value: true
|
|
7
|
-
});
|
|
8
|
-
exports.default = void 0;
|
|
9
|
-
var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
|
|
10
|
-
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
11
|
-
var _batcher = _interopRequireDefault(require("./batcher"));
|
|
12
|
-
/*!
|
|
13
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
var CallDiagnosticEventsBatcher = _batcher.default.extend({
|
|
17
|
-
namespace: 'Metrics',
|
|
18
|
-
/**
|
|
19
|
-
* @param {string} webClientDomain
|
|
20
|
-
* @returns {string}
|
|
21
|
-
*/
|
|
22
|
-
getBuildType: function getBuildType(webClientDomain) {
|
|
23
|
-
if (webClientDomain !== null && webClientDomain !== void 0 && webClientDomain.includes('teams.webex.com') || webClientDomain !== null && webClientDomain !== void 0 && webClientDomain.includes('localhost') || webClientDomain !== null && webClientDomain !== void 0 && webClientDomain.includes('127.0.0.1') || process.env.NODE_ENV !== 'production') {
|
|
24
|
-
return 'test';
|
|
25
|
-
}
|
|
26
|
-
return process.env.NODE_ENV === 'production' ? 'prod' : 'test';
|
|
27
|
-
},
|
|
28
|
-
prepareItem: function prepareItem(item) {
|
|
29
|
-
var _item$event, _item$event$eventData;
|
|
30
|
-
// networkType should be a enum value: `wifi`, `ethernet`, `cellular`, or `unknown`.
|
|
31
|
-
// Browsers cannot provide such information right now. However, it is a required field.
|
|
32
|
-
var origin = {
|
|
33
|
-
buildType: this.getBuildType((_item$event = item.event) === null || _item$event === void 0 ? void 0 : (_item$event$eventData = _item$event.eventData) === null || _item$event$eventData === void 0 ? void 0 : _item$event$eventData.webClientDomain),
|
|
34
|
-
networkType: 'unknown'
|
|
35
|
-
};
|
|
36
|
-
item.eventPayload.origin = (0, _assign.default)(origin, item.eventPayload.origin);
|
|
37
|
-
return _promise.default.resolve(item);
|
|
38
|
-
},
|
|
39
|
-
prepareRequest: function prepareRequest(queue) {
|
|
40
|
-
// Add sent timestamp
|
|
41
|
-
queue.forEach(function (item) {
|
|
42
|
-
item.eventPayload.originTime = item.eventPayload.originTime || {};
|
|
43
|
-
item.eventPayload.originTime.sent = new Date().toISOString();
|
|
44
|
-
});
|
|
45
|
-
return _promise.default.resolve(queue);
|
|
46
|
-
},
|
|
47
|
-
submitHttpRequest: function submitHttpRequest(payload) {
|
|
48
|
-
return this.webex.request({
|
|
49
|
-
method: 'POST',
|
|
50
|
-
service: 'metrics',
|
|
51
|
-
resource: 'clientmetrics',
|
|
52
|
-
body: {
|
|
53
|
-
metrics: payload
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
var _default = CallDiagnosticEventsBatcher;
|
|
59
|
-
exports.default = _default;
|
|
60
|
-
//# sourceMappingURL=call-diagnostic-events-batcher.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["CallDiagnosticEventsBatcher","Batcher","extend","namespace","getBuildType","webClientDomain","includes","process","env","NODE_ENV","prepareItem","item","origin","buildType","event","eventData","networkType","eventPayload","resolve","prepareRequest","queue","forEach","originTime","sent","Date","toISOString","submitHttpRequest","payload","webex","request","method","service","resource","body","metrics"],"sources":["call-diagnostic-events-batcher.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport Batcher from './batcher';\n\nconst CallDiagnosticEventsBatcher = Batcher.extend({\n namespace: 'Metrics',\n\n /**\n * @param {string} webClientDomain\n * @returns {string}\n */\n getBuildType(webClientDomain) {\n if (\n webClientDomain?.includes('teams.webex.com') ||\n webClientDomain?.includes('localhost') ||\n webClientDomain?.includes('127.0.0.1') ||\n process.env.NODE_ENV !== 'production'\n ) {\n return 'test';\n }\n\n return process.env.NODE_ENV === 'production' ? 'prod' : 'test';\n },\n\n prepareItem(item) {\n // networkType should be a enum value: `wifi`, `ethernet`, `cellular`, or `unknown`.\n // Browsers cannot provide such information right now. However, it is a required field.\n const origin = {\n buildType: this.getBuildType(item.event?.eventData?.webClientDomain),\n networkType: 'unknown',\n };\n\n item.eventPayload.origin = Object.assign(origin, item.eventPayload.origin);\n\n return Promise.resolve(item);\n },\n\n prepareRequest(queue) {\n // Add sent timestamp\n queue.forEach((item) => {\n item.eventPayload.originTime = item.eventPayload.originTime || {};\n item.eventPayload.originTime.sent = new Date().toISOString();\n });\n\n return Promise.resolve(queue);\n },\n\n submitHttpRequest(payload) {\n return this.webex.request({\n method: 'POST',\n service: 'metrics',\n resource: 'clientmetrics',\n body: {\n metrics: payload,\n },\n });\n },\n});\n\nexport default CallDiagnosticEventsBatcher;\n"],"mappings":";;;;;;;;;;AAIA;AAJA;AACA;AACA;;AAIA,IAAMA,2BAA2B,GAAGC,gBAAO,CAACC,MAAM,CAAC;EACjDC,SAAS,EAAE,SAAS;EAEpB;AACF;AACA;AACA;EACEC,YAAY,wBAACC,eAAe,EAAE;IAC5B,IACEA,eAAe,aAAfA,eAAe,eAAfA,eAAe,CAAEC,QAAQ,CAAC,iBAAiB,CAAC,IAC5CD,eAAe,aAAfA,eAAe,eAAfA,eAAe,CAAEC,QAAQ,CAAC,WAAW,CAAC,IACtCD,eAAe,aAAfA,eAAe,eAAfA,eAAe,CAAEC,QAAQ,CAAC,WAAW,CAAC,IACtCC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EACrC;MACA,OAAO,MAAM;IACf;IAEA,OAAOF,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAAG,MAAM,GAAG,MAAM;EAChE,CAAC;EAEDC,WAAW,uBAACC,IAAI,EAAE;IAAA;IAChB;IACA;IACA,IAAMC,MAAM,GAAG;MACbC,SAAS,EAAE,IAAI,CAACT,YAAY,gBAACO,IAAI,CAACG,KAAK,yEAAV,YAAYC,SAAS,0DAArB,sBAAuBV,eAAe,CAAC;MACpEW,WAAW,EAAE;IACf,CAAC;IAEDL,IAAI,CAACM,YAAY,CAACL,MAAM,GAAG,qBAAcA,MAAM,EAAED,IAAI,CAACM,YAAY,CAACL,MAAM,CAAC;IAE1E,OAAO,iBAAQM,OAAO,CAACP,IAAI,CAAC;EAC9B,CAAC;EAEDQ,cAAc,0BAACC,KAAK,EAAE;IACpB;IACAA,KAAK,CAACC,OAAO,CAAC,UAACV,IAAI,EAAK;MACtBA,IAAI,CAACM,YAAY,CAACK,UAAU,GAAGX,IAAI,CAACM,YAAY,CAACK,UAAU,IAAI,CAAC,CAAC;MACjEX,IAAI,CAACM,YAAY,CAACK,UAAU,CAACC,IAAI,GAAG,IAAIC,IAAI,EAAE,CAACC,WAAW,EAAE;IAC9D,CAAC,CAAC;IAEF,OAAO,iBAAQP,OAAO,CAACE,KAAK,CAAC;EAC/B,CAAC;EAEDM,iBAAiB,6BAACC,OAAO,EAAE;IACzB,OAAO,IAAI,CAACC,KAAK,CAACC,OAAO,CAAC;MACxBC,MAAM,EAAE,MAAM;MACdC,OAAO,EAAE,SAAS;MAClBC,QAAQ,EAAE,eAAe;MACzBC,IAAI,EAAE;QACJC,OAAO,EAAEP;MACX;IACF,CAAC,CAAC;EACJ;AACF,CAAC,CAAC;AAAC,eAEY3B,2BAA2B;AAAA"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import Batcher from './batcher';
|
|
6
|
-
|
|
7
|
-
const CallDiagnosticEventsBatcher = Batcher.extend({
|
|
8
|
-
namespace: 'Metrics',
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @param {string} webClientDomain
|
|
12
|
-
* @returns {string}
|
|
13
|
-
*/
|
|
14
|
-
getBuildType(webClientDomain) {
|
|
15
|
-
if (
|
|
16
|
-
webClientDomain?.includes('teams.webex.com') ||
|
|
17
|
-
webClientDomain?.includes('localhost') ||
|
|
18
|
-
webClientDomain?.includes('127.0.0.1') ||
|
|
19
|
-
process.env.NODE_ENV !== 'production'
|
|
20
|
-
) {
|
|
21
|
-
return 'test';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return process.env.NODE_ENV === 'production' ? 'prod' : 'test';
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
prepareItem(item) {
|
|
28
|
-
// networkType should be a enum value: `wifi`, `ethernet`, `cellular`, or `unknown`.
|
|
29
|
-
// Browsers cannot provide such information right now. However, it is a required field.
|
|
30
|
-
const origin = {
|
|
31
|
-
buildType: this.getBuildType(item.event?.eventData?.webClientDomain),
|
|
32
|
-
networkType: 'unknown',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
item.eventPayload.origin = Object.assign(origin, item.eventPayload.origin);
|
|
36
|
-
|
|
37
|
-
return Promise.resolve(item);
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
prepareRequest(queue) {
|
|
41
|
-
// Add sent timestamp
|
|
42
|
-
queue.forEach((item) => {
|
|
43
|
-
item.eventPayload.originTime = item.eventPayload.originTime || {};
|
|
44
|
-
item.eventPayload.originTime.sent = new Date().toISOString();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return Promise.resolve(queue);
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
submitHttpRequest(payload) {
|
|
51
|
-
return this.webex.request({
|
|
52
|
-
method: 'POST',
|
|
53
|
-
service: 'metrics',
|
|
54
|
-
resource: 'clientmetrics',
|
|
55
|
-
body: {
|
|
56
|
-
metrics: payload,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
export default CallDiagnosticEventsBatcher;
|
package/src/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import '@webex/internal-plugin-device';
|
|
6
|
-
|
|
7
|
-
import {registerInternalPlugin} from '@webex/webex-core';
|
|
8
|
-
|
|
9
|
-
import Metrics from './metrics';
|
|
10
|
-
import config from './config';
|
|
11
|
-
|
|
12
|
-
registerInternalPlugin('metrics', Metrics, {
|
|
13
|
-
config,
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export {default} from './metrics';
|
|
17
|
-
export {config};
|