@webex/plugin-logger 2.59.1 → 2.59.3-next.1
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/.eslintrc.js +6 -6
- package/README.md +82 -82
- package/babel.config.js +3 -3
- package/dist/config.js +13 -13
- package/dist/config.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/logger.js +75 -75
- package/dist/logger.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +17 -16
- package/process +1 -1
- package/src/config.js +23 -23
- package/src/index.js +15 -15
- package/src/logger.js +427 -427
- package/test/unit/spec/logger.js +805 -805
package/test/unit/spec/logger.js
CHANGED
|
@@ -1,805 +1,805 @@
|
|
|
1
|
-
/* eslint-disable no-await-in-loop */
|
|
2
|
-
/*!
|
|
3
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {assert} from '@webex/test-helper-chai';
|
|
7
|
-
import MockWebex from '@webex/test-helper-mock-webex';
|
|
8
|
-
import sinon from 'sinon';
|
|
9
|
-
import {browserOnly, nodeOnly} from '@webex/test-helper-mocha';
|
|
10
|
-
import Logger, {levels} from '@webex/plugin-logger';
|
|
11
|
-
import {WebexHttpError} from '@webex/webex-core';
|
|
12
|
-
|
|
13
|
-
describe('plugin-logger', () => {
|
|
14
|
-
const logSpies = [];
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
levels.forEach((level) => {
|
|
18
|
-
if (console[level]) {
|
|
19
|
-
logSpies[level] = sinon.spy(console, level);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
levels.forEach((level) => {
|
|
26
|
-
if (console[level] && console[level].restore) {
|
|
27
|
-
console[level].restore();
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
let nodeEnv;
|
|
33
|
-
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
nodeEnv = process.env.NODE_ENV;
|
|
36
|
-
process.env.NODE_ENV = '';
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
afterEach(() => {
|
|
40
|
-
process.env.NODE_ENV = nodeEnv;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
let webex;
|
|
44
|
-
|
|
45
|
-
beforeEach(() => {
|
|
46
|
-
webex = new MockWebex({
|
|
47
|
-
children: {
|
|
48
|
-
logger: Logger,
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const fallbacks = {
|
|
54
|
-
error: ['log'],
|
|
55
|
-
warn: ['error', 'log'],
|
|
56
|
-
info: ['log'],
|
|
57
|
-
debug: ['info', 'log'],
|
|
58
|
-
trace: ['debug', 'info', 'log'],
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
function impl(level) {
|
|
62
|
-
let impls = fallbacks[level];
|
|
63
|
-
let i = level;
|
|
64
|
-
|
|
65
|
-
if (impls) {
|
|
66
|
-
impls = impls.slice();
|
|
67
|
-
while (!console[i]) {
|
|
68
|
-
i = impls.pop();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return i;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
describe('#log()', () => {
|
|
76
|
-
it('prints the specified message to the console', () => {
|
|
77
|
-
webex.config.logger.level = 'trace';
|
|
78
|
-
webex.logger.log('test');
|
|
79
|
-
assert.calledWith(console.log, 'wx-js-sdk', 'test');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('stores the specified message in the log buffer', () => {
|
|
83
|
-
webex.logger.log('test');
|
|
84
|
-
assert.lengthOf(webex.logger.buffer, 1);
|
|
85
|
-
assert.match(webex.logger.buffer[0][3], /test/);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('adds the date to the beggining of the buffer entry', () => {
|
|
89
|
-
webex.logger.log('test date');
|
|
90
|
-
|
|
91
|
-
// Convert string back to date object
|
|
92
|
-
const logDate = new Date(webex.logger.buffer[0][1]);
|
|
93
|
-
|
|
94
|
-
// eslint-disable-next-line no-restricted-globals
|
|
95
|
-
assert.isTrue(logDate instanceof Date && isNaN(webex.logger.buffer[0][1]));
|
|
96
|
-
assert.isString(webex.logger.buffer[0][0]);
|
|
97
|
-
assert.isString(webex.logger.buffer[0][1]);
|
|
98
|
-
assert.match(webex.logger.buffer[0][3], /test date/);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('stores the specified message in the client and sdk log buffer', () => {
|
|
102
|
-
webex.config.logger.separateLogBuffers = true;
|
|
103
|
-
webex.config.logger.clientName = 'someclient';
|
|
104
|
-
webex.logger.log('testsdk');
|
|
105
|
-
webex.logger.client_log('testclient');
|
|
106
|
-
assert.lengthOf(webex.logger.sdkBuffer, 1);
|
|
107
|
-
assert.isString(webex.logger.sdkBuffer[0][0]);
|
|
108
|
-
assert.isString(webex.logger.sdkBuffer[0][1]);
|
|
109
|
-
assert.match(webex.logger.sdkBuffer[0][2], /wx-js-sdk/);
|
|
110
|
-
assert.match(webex.logger.sdkBuffer[0][3], /testsdk/);
|
|
111
|
-
assert.lengthOf(webex.logger.clientBuffer, 1);
|
|
112
|
-
assert.isString(webex.logger.clientBuffer[0][0]);
|
|
113
|
-
assert.isString(webex.logger.clientBuffer[0][1]);
|
|
114
|
-
assert.match(webex.logger.clientBuffer[0][2], /someclient/);
|
|
115
|
-
assert.match(webex.logger.clientBuffer[0][3], /testclient/);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('prevents the buffer from overflowing', () => {
|
|
119
|
-
webex.config.logger.historyLength = 2;
|
|
120
|
-
webex.logger.log(1);
|
|
121
|
-
assert.lengthOf(webex.logger.buffer, 1);
|
|
122
|
-
webex.logger.log(2);
|
|
123
|
-
assert.lengthOf(webex.logger.buffer, 2);
|
|
124
|
-
webex.logger.log(3);
|
|
125
|
-
assert.lengthOf(webex.logger.buffer, 2);
|
|
126
|
-
assert.equal(webex.logger.buffer[0][3], 2);
|
|
127
|
-
assert.equal(webex.logger.buffer[1][3], 3);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('prevents the client and sdk buffer from overflowing', () => {
|
|
131
|
-
webex.config.logger.historyLength = 2;
|
|
132
|
-
webex.config.logger.separateLogBuffers = true;
|
|
133
|
-
webex.logger.log(1);
|
|
134
|
-
webex.logger.client_log(3);
|
|
135
|
-
assert.lengthOf(webex.logger.sdkBuffer, 1);
|
|
136
|
-
assert.lengthOf(webex.logger.clientBuffer, 1);
|
|
137
|
-
webex.logger.log(2);
|
|
138
|
-
webex.logger.client_log(2);
|
|
139
|
-
assert.lengthOf(webex.logger.sdkBuffer, 2);
|
|
140
|
-
assert.lengthOf(webex.logger.clientBuffer, 2);
|
|
141
|
-
webex.logger.log(3);
|
|
142
|
-
webex.logger.client_log(1);
|
|
143
|
-
assert.lengthOf(webex.logger.sdkBuffer, 2);
|
|
144
|
-
assert.lengthOf(webex.logger.clientBuffer, 2);
|
|
145
|
-
assert.equal(webex.logger.sdkBuffer[0][3], 2);
|
|
146
|
-
assert.equal(webex.logger.sdkBuffer[1][3], 3);
|
|
147
|
-
assert.equal(webex.logger.sdkBuffer[0][3], 2);
|
|
148
|
-
assert.equal(webex.logger.clientBuffer[1][3], 1);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// Node handles custom errors correctly, so this test is browser specific
|
|
152
|
-
browserOnly(it)('prints custom errors in a readable fashion', () => {
|
|
153
|
-
webex.config.logger.level = 'trace';
|
|
154
|
-
const error = new WebexHttpError({
|
|
155
|
-
statusCode: 500,
|
|
156
|
-
body: {
|
|
157
|
-
error: 'Internal Error',
|
|
158
|
-
},
|
|
159
|
-
options: {
|
|
160
|
-
service: '',
|
|
161
|
-
headers: {},
|
|
162
|
-
},
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
webex.logger.log(error);
|
|
166
|
-
assert.lengthOf(webex.logger.buffer, 1);
|
|
167
|
-
assert.match(console.log.args[0][1], /WebexHttpError/);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it('buffers custom errors in a readable fashion', () => {
|
|
171
|
-
webex.config.logger.level = 'trace';
|
|
172
|
-
const error = new WebexHttpError({
|
|
173
|
-
statusCode: 500,
|
|
174
|
-
body: {
|
|
175
|
-
error: 'Internal Error',
|
|
176
|
-
},
|
|
177
|
-
options: {
|
|
178
|
-
service: '',
|
|
179
|
-
headers: {},
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
webex.logger.log(error);
|
|
184
|
-
assert.lengthOf(webex.logger.buffer, 1);
|
|
185
|
-
assert.match(webex.logger.buffer[0][3], /WebexHttpError/g);
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
// We can't manipulate NODE_ENV in karma, tests, so run this chunk only in
|
|
190
|
-
// node
|
|
191
|
-
describe('#shouldPrint()', () => {
|
|
192
|
-
nodeOnly(afterEach)(() => {
|
|
193
|
-
process.env.WEBEX_LOG_LEVEL = undefined;
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
function testLevels(logType, logConfigSetting) {
|
|
197
|
-
/* eslint max-statements: [0] */
|
|
198
|
-
webex.logger.config[logConfigSetting] = 'trace';
|
|
199
|
-
assert.isTrue(
|
|
200
|
-
webex.logger.shouldPrint('error', logType),
|
|
201
|
-
'it prints `error` logs when the level is `trace`'
|
|
202
|
-
);
|
|
203
|
-
assert.isTrue(
|
|
204
|
-
webex.logger.shouldPrint('warn', logType),
|
|
205
|
-
'it prints `warn` logs when the level is `trace`'
|
|
206
|
-
);
|
|
207
|
-
assert.isTrue(
|
|
208
|
-
webex.logger.shouldPrint('log', logType),
|
|
209
|
-
'it prints `log` logs when the level is `trace`'
|
|
210
|
-
);
|
|
211
|
-
assert.isTrue(
|
|
212
|
-
webex.logger.shouldPrint('info', logType),
|
|
213
|
-
'it prints `info` logs when the level is `trace`'
|
|
214
|
-
);
|
|
215
|
-
assert.isTrue(
|
|
216
|
-
webex.logger.shouldPrint('debug', logType),
|
|
217
|
-
'it prints `debug` logs when the level is `trace`'
|
|
218
|
-
);
|
|
219
|
-
assert.isTrue(
|
|
220
|
-
webex.logger.shouldPrint('trace', logType),
|
|
221
|
-
'it prints `trace` logs when the level is `trace`'
|
|
222
|
-
);
|
|
223
|
-
|
|
224
|
-
webex.logger.config[logConfigSetting] = 'debug';
|
|
225
|
-
assert.isTrue(
|
|
226
|
-
webex.logger.shouldPrint('error', logType),
|
|
227
|
-
'it prints `error` logs when the level is `debug`'
|
|
228
|
-
);
|
|
229
|
-
assert.isTrue(
|
|
230
|
-
webex.logger.shouldPrint('warn', logType),
|
|
231
|
-
'it prints `warn` logs when the level is `debug`'
|
|
232
|
-
);
|
|
233
|
-
assert.isTrue(
|
|
234
|
-
webex.logger.shouldPrint('log', logType),
|
|
235
|
-
'it prints `log` logs when the level is `debug`'
|
|
236
|
-
);
|
|
237
|
-
assert.isTrue(
|
|
238
|
-
webex.logger.shouldPrint('info', logType),
|
|
239
|
-
'it prints `info` logs when the level is `debug`'
|
|
240
|
-
);
|
|
241
|
-
assert.isTrue(
|
|
242
|
-
webex.logger.shouldPrint('debug', logType),
|
|
243
|
-
'it prints `debug` logs when the level is `debug`'
|
|
244
|
-
);
|
|
245
|
-
assert.isFalse(
|
|
246
|
-
webex.logger.shouldPrint('trace', logType),
|
|
247
|
-
'it does not print `trace` logs when the level is `debug`'
|
|
248
|
-
);
|
|
249
|
-
|
|
250
|
-
webex.logger.config[logConfigSetting] = 'info';
|
|
251
|
-
assert.isTrue(
|
|
252
|
-
webex.logger.shouldPrint('error', logType),
|
|
253
|
-
'it prints `error` logs when the level is `info`'
|
|
254
|
-
);
|
|
255
|
-
assert.isTrue(
|
|
256
|
-
webex.logger.shouldPrint('warn', logType),
|
|
257
|
-
'it prints `warn` logs when the level is `info`'
|
|
258
|
-
);
|
|
259
|
-
assert.isTrue(
|
|
260
|
-
webex.logger.shouldPrint('log', logType),
|
|
261
|
-
'it prints `log` logs when the level is `info`'
|
|
262
|
-
);
|
|
263
|
-
assert.isTrue(
|
|
264
|
-
webex.logger.shouldPrint('info', logType),
|
|
265
|
-
'it prints `info` logs when the level is `info`'
|
|
266
|
-
);
|
|
267
|
-
assert.isFalse(
|
|
268
|
-
webex.logger.shouldPrint('debug', logType),
|
|
269
|
-
'it does not print `debug` logs when the level is `info`'
|
|
270
|
-
);
|
|
271
|
-
assert.isFalse(
|
|
272
|
-
webex.logger.shouldPrint('trace', logType),
|
|
273
|
-
'it does not print `trace` logs when the level is `info`'
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
webex.logger.config[logConfigSetting] = 'log';
|
|
277
|
-
assert.isTrue(
|
|
278
|
-
webex.logger.shouldPrint('error', logType),
|
|
279
|
-
'it prints `error` logs when the level is `log`'
|
|
280
|
-
);
|
|
281
|
-
assert.isTrue(
|
|
282
|
-
webex.logger.shouldPrint('warn', logType),
|
|
283
|
-
'it prints `warn` logs when the level is `log`'
|
|
284
|
-
);
|
|
285
|
-
assert.isTrue(
|
|
286
|
-
webex.logger.shouldPrint('log', logType),
|
|
287
|
-
'it prints `log` logs when the level is `log`'
|
|
288
|
-
);
|
|
289
|
-
assert.isFalse(
|
|
290
|
-
webex.logger.shouldPrint('info', logType),
|
|
291
|
-
'it does not print `info` logs when the level is `log`'
|
|
292
|
-
);
|
|
293
|
-
assert.isFalse(
|
|
294
|
-
webex.logger.shouldPrint('debug', logType),
|
|
295
|
-
'it does not print `debug` logs when the level is `log`'
|
|
296
|
-
);
|
|
297
|
-
assert.isFalse(
|
|
298
|
-
webex.logger.shouldPrint('trace', logType),
|
|
299
|
-
'it does not print `trace` logs when the level is `log`'
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
webex.logger.config[logConfigSetting] = 'warn';
|
|
303
|
-
assert.isTrue(
|
|
304
|
-
webex.logger.shouldPrint('error', logType),
|
|
305
|
-
'it prints `error` logs when the level is `warn`'
|
|
306
|
-
);
|
|
307
|
-
assert.isTrue(
|
|
308
|
-
webex.logger.shouldPrint('warn', logType),
|
|
309
|
-
'it prints `warn` logs when the level is `warn`'
|
|
310
|
-
);
|
|
311
|
-
assert.isFalse(
|
|
312
|
-
webex.logger.shouldPrint('log', logType),
|
|
313
|
-
'it does not print `log` logs when the level is `warn`'
|
|
314
|
-
);
|
|
315
|
-
assert.isFalse(
|
|
316
|
-
webex.logger.shouldPrint('info', logType),
|
|
317
|
-
'it does not print `info` logs when the level is `warn`'
|
|
318
|
-
);
|
|
319
|
-
assert.isFalse(
|
|
320
|
-
webex.logger.shouldPrint('debug', logType),
|
|
321
|
-
'it does not print `debug` logs when the level is `warn`'
|
|
322
|
-
);
|
|
323
|
-
assert.isFalse(
|
|
324
|
-
webex.logger.shouldPrint('trace', logType),
|
|
325
|
-
'it does not print `trace` logs when the level is `warn`'
|
|
326
|
-
);
|
|
327
|
-
|
|
328
|
-
webex.logger.config[logConfigSetting] = 'error';
|
|
329
|
-
assert.isTrue(
|
|
330
|
-
webex.logger.shouldPrint('error', logType),
|
|
331
|
-
'it prints `error` logs when the level is `error`'
|
|
332
|
-
);
|
|
333
|
-
assert.isFalse(
|
|
334
|
-
webex.logger.shouldPrint('warn', logType),
|
|
335
|
-
'it does not print `warn` logs when the level `error` is '
|
|
336
|
-
);
|
|
337
|
-
assert.isFalse(
|
|
338
|
-
webex.logger.shouldPrint('log', logType),
|
|
339
|
-
'it does not print `log` logs when the level is `error`'
|
|
340
|
-
);
|
|
341
|
-
assert.isFalse(
|
|
342
|
-
webex.logger.shouldPrint('info', logType),
|
|
343
|
-
'it does not print `info` logs when the level is `error`'
|
|
344
|
-
);
|
|
345
|
-
assert.isFalse(
|
|
346
|
-
webex.logger.shouldPrint('debug', logType),
|
|
347
|
-
'it does not print `debug` logs when the level is `error`'
|
|
348
|
-
);
|
|
349
|
-
assert.isFalse(
|
|
350
|
-
webex.logger.shouldPrint('trace', logType),
|
|
351
|
-
'it does not print `trace` logs when the level is `error`'
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
webex.logger.config[logConfigSetting] = 'silent';
|
|
355
|
-
assert.isFalse(
|
|
356
|
-
webex.logger.shouldPrint('error', logType),
|
|
357
|
-
'it does not print `error` logs when the level is `silent`'
|
|
358
|
-
);
|
|
359
|
-
assert.isFalse(
|
|
360
|
-
webex.logger.shouldPrint('warn', logType),
|
|
361
|
-
'it does not print `warn` logs when the level is `silent`'
|
|
362
|
-
);
|
|
363
|
-
assert.isFalse(
|
|
364
|
-
webex.logger.shouldPrint('log', logType),
|
|
365
|
-
'it does not print `log` logs when the level is `silent`'
|
|
366
|
-
);
|
|
367
|
-
assert.isFalse(
|
|
368
|
-
webex.logger.shouldPrint('info', logType),
|
|
369
|
-
'it does not print `info` logs when the level is `silent`'
|
|
370
|
-
);
|
|
371
|
-
assert.isFalse(
|
|
372
|
-
webex.logger.shouldPrint('debug', logType),
|
|
373
|
-
'it does not print `debug` logs when the level is `silent`'
|
|
374
|
-
);
|
|
375
|
-
assert.isFalse(
|
|
376
|
-
webex.logger.shouldPrint('trace', logType),
|
|
377
|
-
'it does not print `trace` logs when the level is `silent`'
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
it('indicates whether or not the desired log should be printed at the current log level', () => {
|
|
382
|
-
// test independence from client log level
|
|
383
|
-
['trace', 'debug', 'info', 'log', 'warn', 'error', 'silent'].forEach((clientLevel) => {
|
|
384
|
-
webex.logger.config.clientLevel = clientLevel;
|
|
385
|
-
testLevels(undefined, 'level');
|
|
386
|
-
testLevels('sdk', 'level');
|
|
387
|
-
});
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
it('factors in log type when passed in as client', () => {
|
|
391
|
-
// test independence from sdk log level
|
|
392
|
-
['trace', 'debug', 'info', 'log', 'warn', 'error', 'silent'].forEach((sdkLevel) => {
|
|
393
|
-
webex.logger.config.level = sdkLevel;
|
|
394
|
-
testLevels('client', 'clientLevel');
|
|
395
|
-
});
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
nodeOnly(it)('uses the WEBEX_LOG_LEVEL environment varable to control log level', () => {
|
|
399
|
-
levels.forEach((level) => {
|
|
400
|
-
process.env.WEBEX_LOG_LEVEL = level;
|
|
401
|
-
console[impl(level)].resetHistory();
|
|
402
|
-
webex.logger[level](`test: ${level}`);
|
|
403
|
-
assert.calledOnce(console[impl(level)]);
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
it('prefers the config specified logger.level', () => {
|
|
408
|
-
levels.forEach((level) => {
|
|
409
|
-
webex.logger.config.level = level;
|
|
410
|
-
console[impl(level)].resetHistory();
|
|
411
|
-
webex.logger[level](`test: ${level}`);
|
|
412
|
-
assert.calledOnce(console[impl(level)]);
|
|
413
|
-
});
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
nodeOnly(it)('logs at TRACE in test environments', () => {
|
|
417
|
-
console.trace.restore();
|
|
418
|
-
sinon.stub(console, 'trace');
|
|
419
|
-
process.env.NODE_ENV = undefined;
|
|
420
|
-
assert.notCalled(console.trace);
|
|
421
|
-
webex.logger.trace('test');
|
|
422
|
-
assert.notCalled(console.trace);
|
|
423
|
-
|
|
424
|
-
process.env.NODE_ENV = 'test';
|
|
425
|
-
webex.logger.trace('test');
|
|
426
|
-
assert.called(console.trace);
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
nodeOnly(it)('checks the developer feature toggle "log-level" when available', () => {
|
|
430
|
-
assert.notCalled(console.info);
|
|
431
|
-
webex.logger.info('test');
|
|
432
|
-
assert.notCalled(console.info);
|
|
433
|
-
|
|
434
|
-
webex.internal.device = {
|
|
435
|
-
features: {
|
|
436
|
-
developer: {
|
|
437
|
-
get() {
|
|
438
|
-
return 'info';
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
entitlement: {
|
|
442
|
-
get() {
|
|
443
|
-
return false;
|
|
444
|
-
},
|
|
445
|
-
},
|
|
446
|
-
},
|
|
447
|
-
};
|
|
448
|
-
webex.logger.info('test');
|
|
449
|
-
assert.called(console.info);
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
nodeOnly(it)("doesn't break if the feature toggle is set to an incorrect value", () => {
|
|
453
|
-
assert.doesNotThrow(() => {
|
|
454
|
-
assert.notCalled(console.info);
|
|
455
|
-
webex.logger.info('test');
|
|
456
|
-
assert.notCalled(console.info);
|
|
457
|
-
|
|
458
|
-
webex.internal.device = {
|
|
459
|
-
features: {
|
|
460
|
-
developer: {
|
|
461
|
-
get() {
|
|
462
|
-
return 'not-a-log-method';
|
|
463
|
-
},
|
|
464
|
-
},
|
|
465
|
-
entitlement: {
|
|
466
|
-
get() {
|
|
467
|
-
return false;
|
|
468
|
-
},
|
|
469
|
-
},
|
|
470
|
-
},
|
|
471
|
-
};
|
|
472
|
-
webex.logger.info('test');
|
|
473
|
-
assert.notCalled(console.info);
|
|
474
|
-
});
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
nodeOnly(it)('defaults to "error" for all other users', () => {
|
|
478
|
-
webex.logger.error('test');
|
|
479
|
-
assert.called(console.error);
|
|
480
|
-
|
|
481
|
-
webex.logger.warn('test');
|
|
482
|
-
assert.notCalled(console.warn);
|
|
483
|
-
});
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
describe('#shouldBuffer()', () => {
|
|
487
|
-
it('logs info level to buffer by default', () => {
|
|
488
|
-
const shouldBuffer = webex.logger.shouldBuffer('info');
|
|
489
|
-
|
|
490
|
-
assert.isTrue(shouldBuffer);
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
it('does not log debug level to buffer by default', () => {
|
|
494
|
-
const shouldBuffer = webex.logger.shouldBuffer('debug');
|
|
495
|
-
|
|
496
|
-
assert.isFalse(shouldBuffer);
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
it('logs debug level to buffer if level configured', () => {
|
|
500
|
-
webex.logger.config.bufferLogLevel = 'debug';
|
|
501
|
-
const shouldBuffer = webex.logger.shouldBuffer('debug');
|
|
502
|
-
|
|
503
|
-
assert.isTrue(shouldBuffer);
|
|
504
|
-
});
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
describe('#filter', () => {
|
|
508
|
-
it('redacts email addresses', () => {
|
|
509
|
-
const message = {
|
|
510
|
-
blarg: 'test@example.com',
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
assert.deepEqual(webex.logger.filter(message), [
|
|
514
|
-
{
|
|
515
|
-
blarg: '[REDACTED]',
|
|
516
|
-
},
|
|
517
|
-
]);
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
it('strips auth headers from log output', () => {
|
|
521
|
-
const msg = {
|
|
522
|
-
headers: {
|
|
523
|
-
authorization: 'Bearer',
|
|
524
|
-
},
|
|
525
|
-
options: {
|
|
526
|
-
headers: {
|
|
527
|
-
trackingid: '123',
|
|
528
|
-
authorization: 'Bearer',
|
|
529
|
-
},
|
|
530
|
-
},
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
assert.doesNotThrow(() => {
|
|
534
|
-
webex.logger.filter({});
|
|
535
|
-
webex.logger.filter({headers: {}});
|
|
536
|
-
webex.logger.filter({headers: {authorization: ''}});
|
|
537
|
-
webex.logger.filter({options: {}});
|
|
538
|
-
webex.logger.filter({options: {headers: {}}});
|
|
539
|
-
webex.logger.filter({options: {headers: {authorization: ''}}});
|
|
540
|
-
webex.logger.filter([{options: {headers: {authorization: ''}}}]);
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
const [filtered] = webex.logger.filter(msg);
|
|
544
|
-
|
|
545
|
-
assert.nestedProperty(msg, 'headers.authorization', 'it does not alter the original message');
|
|
546
|
-
assert.nestedProperty(
|
|
547
|
-
msg,
|
|
548
|
-
'options.headers.authorization',
|
|
549
|
-
'it does not alter the original message'
|
|
550
|
-
);
|
|
551
|
-
|
|
552
|
-
assert.notNestedProperty(
|
|
553
|
-
filtered,
|
|
554
|
-
'headers.authorization',
|
|
555
|
-
'it removes headers.authorization'
|
|
556
|
-
);
|
|
557
|
-
assert.notNestedProperty(
|
|
558
|
-
filtered,
|
|
559
|
-
'options.headers.authorization',
|
|
560
|
-
'it removes options.headers.authorization'
|
|
561
|
-
);
|
|
562
|
-
assert.nestedProperty(
|
|
563
|
-
msg,
|
|
564
|
-
'options.headers.trackingid',
|
|
565
|
-
'it does not remove other header values'
|
|
566
|
-
);
|
|
567
|
-
assert.nestedProperty(
|
|
568
|
-
filtered,
|
|
569
|
-
'options.headers.trackingid',
|
|
570
|
-
'it does not remove other header values'
|
|
571
|
-
);
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
['error', 'warn', 'log', 'info', 'debug', 'trace'].forEach((level) => {
|
|
576
|
-
describe(`#${level}()`, () => {
|
|
577
|
-
it(`proxies console.${level}`, () => {
|
|
578
|
-
webex.logger.config.level = level;
|
|
579
|
-
assert.notCalled(console[impl(level)]);
|
|
580
|
-
webex.logger[level]('a log statement');
|
|
581
|
-
assert.called(console[impl(level)]);
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
it('removes authorization data', () => {
|
|
585
|
-
webex.logger.config.level = level;
|
|
586
|
-
webex.logger[level]({
|
|
587
|
-
headers: {
|
|
588
|
-
authorization: 'Bearer',
|
|
589
|
-
trackingid: '123',
|
|
590
|
-
},
|
|
591
|
-
});
|
|
592
|
-
assert.calledWith(console[impl(level)], 'wx-js-sdk', {
|
|
593
|
-
headers: {
|
|
594
|
-
trackingid: '123',
|
|
595
|
-
},
|
|
596
|
-
});
|
|
597
|
-
});
|
|
598
|
-
});
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
describe('#walkAndFilter', () => {
|
|
602
|
-
it('redact Authorization', () => {
|
|
603
|
-
webex.config.logger.level = 'trace';
|
|
604
|
-
webex.logger.log({
|
|
605
|
-
Authorization: 'XXXXXXX',
|
|
606
|
-
Key: 'myKey',
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
// Assert auth was filtered
|
|
610
|
-
assert.calledWith(console.log, 'wx-js-sdk', {Key: 'myKey'});
|
|
611
|
-
|
|
612
|
-
webex.logger.log({
|
|
613
|
-
authorization: 'XXXXXXX',
|
|
614
|
-
Key: 'myKey',
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
assert.calledWith(console.log, 'wx-js-sdk', {Key: 'myKey'});
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
it('redact emails', () => {
|
|
621
|
-
webex.config.logger.level = 'trace';
|
|
622
|
-
|
|
623
|
-
webex.logger.log('my email address is test@cisco.com');
|
|
624
|
-
assert.calledWith(console.log, 'wx-js-sdk', 'my email address is [REDACTED]');
|
|
625
|
-
|
|
626
|
-
webex.logger.log('test@cisco.com');
|
|
627
|
-
assert.calledWith(console.log, 'wx-js-sdk', '[REDACTED]');
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
it('handle circular references', () => {
|
|
631
|
-
webex.config.logger.level = 'trace';
|
|
632
|
-
|
|
633
|
-
const object = {
|
|
634
|
-
authorization: 'XXXXXXX',
|
|
635
|
-
string: 'test@cisco.com',
|
|
636
|
-
Key: 'myKey',
|
|
637
|
-
};
|
|
638
|
-
|
|
639
|
-
// Add a circular reference to the object
|
|
640
|
-
object.selfReference = object;
|
|
641
|
-
|
|
642
|
-
webex.logger.log(object);
|
|
643
|
-
|
|
644
|
-
const expected = {
|
|
645
|
-
string: '[REDACTED]',
|
|
646
|
-
Key: 'myKey',
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
expected.selfReference = expected;
|
|
650
|
-
|
|
651
|
-
assert.calledWith(console.log, 'wx-js-sdk', expected);
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
it('handle circular references in complex objects', () => {
|
|
655
|
-
webex.config.logger.level = 'trace';
|
|
656
|
-
|
|
657
|
-
const func = () => true;
|
|
658
|
-
const sym = Symbol('foo');
|
|
659
|
-
|
|
660
|
-
const object = {
|
|
661
|
-
primativeString: 'justastring',
|
|
662
|
-
primativeNum: 5,
|
|
663
|
-
primativeBool: true,
|
|
664
|
-
primativeSymbol: sym,
|
|
665
|
-
myFunction: func,
|
|
666
|
-
subObject: {
|
|
667
|
-
subPrimativeString: 'justastring',
|
|
668
|
-
otherPrimativeString: 'otherstring',
|
|
669
|
-
subPrimativeNum: 5,
|
|
670
|
-
otherPrimativeNum: 6,
|
|
671
|
-
subPrimativeBool: true,
|
|
672
|
-
otherPrimativeBool: false,
|
|
673
|
-
subPrimativeSymbol: sym,
|
|
674
|
-
},
|
|
675
|
-
};
|
|
676
|
-
|
|
677
|
-
object.subObject.circularObjectRef = object;
|
|
678
|
-
object.subObject.circularFunctionRef = func;
|
|
679
|
-
object.subObject.circularFunctionRef.cat = func;
|
|
680
|
-
|
|
681
|
-
webex.logger.log(object);
|
|
682
|
-
|
|
683
|
-
assert.calledWith(console.log, 'wx-js-sdk', {
|
|
684
|
-
primativeString: 'justastring',
|
|
685
|
-
primativeNum: 5,
|
|
686
|
-
primativeBool: true,
|
|
687
|
-
primativeSymbol: sym,
|
|
688
|
-
myFunction: func,
|
|
689
|
-
subObject: {
|
|
690
|
-
subPrimativeString: 'justastring',
|
|
691
|
-
otherPrimativeString: 'otherstring',
|
|
692
|
-
subPrimativeNum: 5,
|
|
693
|
-
otherPrimativeNum: 6,
|
|
694
|
-
subPrimativeBool: true,
|
|
695
|
-
otherPrimativeBool: false,
|
|
696
|
-
subPrimativeSymbol: sym,
|
|
697
|
-
circularObjectRef: object,
|
|
698
|
-
circularFunctionRef: func,
|
|
699
|
-
},
|
|
700
|
-
});
|
|
701
|
-
});
|
|
702
|
-
});
|
|
703
|
-
|
|
704
|
-
describe('#formatLogs()', () => {
|
|
705
|
-
function sendRandomLog(log) {
|
|
706
|
-
const logMethod = Math.round(Math.random()) ? 'log' : 'client_log';
|
|
707
|
-
|
|
708
|
-
webex.logger[logMethod](log);
|
|
709
|
-
}
|
|
710
|
-
function sleep(ms) {
|
|
711
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
712
|
-
}
|
|
713
|
-
function checkAscending(logs) {
|
|
714
|
-
const logLines = logs.split('\n');
|
|
715
|
-
|
|
716
|
-
let lastvalue;
|
|
717
|
-
|
|
718
|
-
for (let i = 0; i < logLines.length; i += 1) {
|
|
719
|
-
const fields = logLines[i].split(',');
|
|
720
|
-
|
|
721
|
-
if (lastvalue) {
|
|
722
|
-
assert.isTrue(lastvalue < fields[3]);
|
|
723
|
-
}
|
|
724
|
-
lastvalue = fields[3];
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
it('formats mixed log types in order by default', async () => {
|
|
729
|
-
for (let i = 0; i < 10; i += 1) {
|
|
730
|
-
sendRandomLog(i);
|
|
731
|
-
await sleep(i);
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
const logs = webex.logger.formatLogs();
|
|
735
|
-
|
|
736
|
-
checkAscending(logs);
|
|
737
|
-
});
|
|
738
|
-
|
|
739
|
-
it('formats mixed log types in order with separate buffers', async () => {
|
|
740
|
-
webex.config.logger.separateLogBuffers = true;
|
|
741
|
-
webex.config.logger.clientName = 'someclient';
|
|
742
|
-
for (let i = 0; i < 10; i += 1) {
|
|
743
|
-
sendRandomLog(i);
|
|
744
|
-
await sleep(i);
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
const logs = webex.logger.formatLogs();
|
|
748
|
-
|
|
749
|
-
checkAscending(logs);
|
|
750
|
-
});
|
|
751
|
-
|
|
752
|
-
it('handles only sdk logs with separate buffers', async () => {
|
|
753
|
-
webex.config.logger.separateLogBuffers = true;
|
|
754
|
-
webex.config.logger.clientName = 'someclient';
|
|
755
|
-
for (let i = 0; i < 10; i += 1) {
|
|
756
|
-
webex.logger.log(i);
|
|
757
|
-
await sleep(i);
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
const logs = webex.logger.formatLogs();
|
|
761
|
-
|
|
762
|
-
checkAscending(logs);
|
|
763
|
-
});
|
|
764
|
-
|
|
765
|
-
it('handles only client logs with separate buffers', async () => {
|
|
766
|
-
webex.config.logger.separateLogBuffers = true;
|
|
767
|
-
webex.config.logger.clientName = 'someclient';
|
|
768
|
-
for (let i = 0; i < 10; i += 1) {
|
|
769
|
-
webex.logger.client_log(i);
|
|
770
|
-
await sleep(i);
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
const logs = webex.logger.formatLogs();
|
|
774
|
-
|
|
775
|
-
checkAscending(logs);
|
|
776
|
-
});
|
|
777
|
-
});
|
|
778
|
-
|
|
779
|
-
describe('#logToBuffer()', () => {
|
|
780
|
-
it('logs only to buffer by default', () => {
|
|
781
|
-
webex.logger.logToBuffer('sdklog');
|
|
782
|
-
webex.logger.client_logToBuffer('clientlog');
|
|
783
|
-
|
|
784
|
-
assert.lengthOf(webex.logger.buffer, 2);
|
|
785
|
-
|
|
786
|
-
logSpies.forEach((logSpy) => {
|
|
787
|
-
assert.notCalled(logSpy);
|
|
788
|
-
});
|
|
789
|
-
});
|
|
790
|
-
it('logs only to buffer with separate buffers', () => {
|
|
791
|
-
webex.config.logger.separateLogBuffers = true;
|
|
792
|
-
webex.config.logger.clientName = 'someclient';
|
|
793
|
-
|
|
794
|
-
webex.logger.logToBuffer('sdklog');
|
|
795
|
-
webex.logger.client_logToBuffer('clientlog');
|
|
796
|
-
|
|
797
|
-
assert.lengthOf(webex.logger.sdkBuffer, 1);
|
|
798
|
-
assert.lengthOf(webex.logger.clientBuffer, 1);
|
|
799
|
-
|
|
800
|
-
logSpies.forEach((logSpy) => {
|
|
801
|
-
assert.notCalled(logSpy);
|
|
802
|
-
});
|
|
803
|
-
});
|
|
804
|
-
});
|
|
805
|
-
});
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {assert} from '@webex/test-helper-chai';
|
|
7
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
8
|
+
import sinon from 'sinon';
|
|
9
|
+
import {browserOnly, nodeOnly} from '@webex/test-helper-mocha';
|
|
10
|
+
import Logger, {levels} from '@webex/plugin-logger';
|
|
11
|
+
import {WebexHttpError} from '@webex/webex-core';
|
|
12
|
+
|
|
13
|
+
describe('plugin-logger', () => {
|
|
14
|
+
const logSpies = [];
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
levels.forEach((level) => {
|
|
18
|
+
if (console[level]) {
|
|
19
|
+
logSpies[level] = sinon.spy(console, level);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
levels.forEach((level) => {
|
|
26
|
+
if (console[level] && console[level].restore) {
|
|
27
|
+
console[level].restore();
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
let nodeEnv;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
nodeEnv = process.env.NODE_ENV;
|
|
36
|
+
process.env.NODE_ENV = '';
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
process.env.NODE_ENV = nodeEnv;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
let webex;
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
webex = new MockWebex({
|
|
47
|
+
children: {
|
|
48
|
+
logger: Logger,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const fallbacks = {
|
|
54
|
+
error: ['log'],
|
|
55
|
+
warn: ['error', 'log'],
|
|
56
|
+
info: ['log'],
|
|
57
|
+
debug: ['info', 'log'],
|
|
58
|
+
trace: ['debug', 'info', 'log'],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
function impl(level) {
|
|
62
|
+
let impls = fallbacks[level];
|
|
63
|
+
let i = level;
|
|
64
|
+
|
|
65
|
+
if (impls) {
|
|
66
|
+
impls = impls.slice();
|
|
67
|
+
while (!console[i]) {
|
|
68
|
+
i = impls.pop();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return i;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
describe('#log()', () => {
|
|
76
|
+
it('prints the specified message to the console', () => {
|
|
77
|
+
webex.config.logger.level = 'trace';
|
|
78
|
+
webex.logger.log('test');
|
|
79
|
+
assert.calledWith(console.log, 'wx-js-sdk', 'test');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('stores the specified message in the log buffer', () => {
|
|
83
|
+
webex.logger.log('test');
|
|
84
|
+
assert.lengthOf(webex.logger.buffer, 1);
|
|
85
|
+
assert.match(webex.logger.buffer[0][3], /test/);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('adds the date to the beggining of the buffer entry', () => {
|
|
89
|
+
webex.logger.log('test date');
|
|
90
|
+
|
|
91
|
+
// Convert string back to date object
|
|
92
|
+
const logDate = new Date(webex.logger.buffer[0][1]);
|
|
93
|
+
|
|
94
|
+
// eslint-disable-next-line no-restricted-globals
|
|
95
|
+
assert.isTrue(logDate instanceof Date && isNaN(webex.logger.buffer[0][1]));
|
|
96
|
+
assert.isString(webex.logger.buffer[0][0]);
|
|
97
|
+
assert.isString(webex.logger.buffer[0][1]);
|
|
98
|
+
assert.match(webex.logger.buffer[0][3], /test date/);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('stores the specified message in the client and sdk log buffer', () => {
|
|
102
|
+
webex.config.logger.separateLogBuffers = true;
|
|
103
|
+
webex.config.logger.clientName = 'someclient';
|
|
104
|
+
webex.logger.log('testsdk');
|
|
105
|
+
webex.logger.client_log('testclient');
|
|
106
|
+
assert.lengthOf(webex.logger.sdkBuffer, 1);
|
|
107
|
+
assert.isString(webex.logger.sdkBuffer[0][0]);
|
|
108
|
+
assert.isString(webex.logger.sdkBuffer[0][1]);
|
|
109
|
+
assert.match(webex.logger.sdkBuffer[0][2], /wx-js-sdk/);
|
|
110
|
+
assert.match(webex.logger.sdkBuffer[0][3], /testsdk/);
|
|
111
|
+
assert.lengthOf(webex.logger.clientBuffer, 1);
|
|
112
|
+
assert.isString(webex.logger.clientBuffer[0][0]);
|
|
113
|
+
assert.isString(webex.logger.clientBuffer[0][1]);
|
|
114
|
+
assert.match(webex.logger.clientBuffer[0][2], /someclient/);
|
|
115
|
+
assert.match(webex.logger.clientBuffer[0][3], /testclient/);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('prevents the buffer from overflowing', () => {
|
|
119
|
+
webex.config.logger.historyLength = 2;
|
|
120
|
+
webex.logger.log(1);
|
|
121
|
+
assert.lengthOf(webex.logger.buffer, 1);
|
|
122
|
+
webex.logger.log(2);
|
|
123
|
+
assert.lengthOf(webex.logger.buffer, 2);
|
|
124
|
+
webex.logger.log(3);
|
|
125
|
+
assert.lengthOf(webex.logger.buffer, 2);
|
|
126
|
+
assert.equal(webex.logger.buffer[0][3], 2);
|
|
127
|
+
assert.equal(webex.logger.buffer[1][3], 3);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('prevents the client and sdk buffer from overflowing', () => {
|
|
131
|
+
webex.config.logger.historyLength = 2;
|
|
132
|
+
webex.config.logger.separateLogBuffers = true;
|
|
133
|
+
webex.logger.log(1);
|
|
134
|
+
webex.logger.client_log(3);
|
|
135
|
+
assert.lengthOf(webex.logger.sdkBuffer, 1);
|
|
136
|
+
assert.lengthOf(webex.logger.clientBuffer, 1);
|
|
137
|
+
webex.logger.log(2);
|
|
138
|
+
webex.logger.client_log(2);
|
|
139
|
+
assert.lengthOf(webex.logger.sdkBuffer, 2);
|
|
140
|
+
assert.lengthOf(webex.logger.clientBuffer, 2);
|
|
141
|
+
webex.logger.log(3);
|
|
142
|
+
webex.logger.client_log(1);
|
|
143
|
+
assert.lengthOf(webex.logger.sdkBuffer, 2);
|
|
144
|
+
assert.lengthOf(webex.logger.clientBuffer, 2);
|
|
145
|
+
assert.equal(webex.logger.sdkBuffer[0][3], 2);
|
|
146
|
+
assert.equal(webex.logger.sdkBuffer[1][3], 3);
|
|
147
|
+
assert.equal(webex.logger.sdkBuffer[0][3], 2);
|
|
148
|
+
assert.equal(webex.logger.clientBuffer[1][3], 1);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Node handles custom errors correctly, so this test is browser specific
|
|
152
|
+
browserOnly(it)('prints custom errors in a readable fashion', () => {
|
|
153
|
+
webex.config.logger.level = 'trace';
|
|
154
|
+
const error = new WebexHttpError({
|
|
155
|
+
statusCode: 500,
|
|
156
|
+
body: {
|
|
157
|
+
error: 'Internal Error',
|
|
158
|
+
},
|
|
159
|
+
options: {
|
|
160
|
+
service: '',
|
|
161
|
+
headers: {},
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
webex.logger.log(error);
|
|
166
|
+
assert.lengthOf(webex.logger.buffer, 1);
|
|
167
|
+
assert.match(console.log.args[0][1], /WebexHttpError/);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('buffers custom errors in a readable fashion', () => {
|
|
171
|
+
webex.config.logger.level = 'trace';
|
|
172
|
+
const error = new WebexHttpError({
|
|
173
|
+
statusCode: 500,
|
|
174
|
+
body: {
|
|
175
|
+
error: 'Internal Error',
|
|
176
|
+
},
|
|
177
|
+
options: {
|
|
178
|
+
service: '',
|
|
179
|
+
headers: {},
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
webex.logger.log(error);
|
|
184
|
+
assert.lengthOf(webex.logger.buffer, 1);
|
|
185
|
+
assert.match(webex.logger.buffer[0][3], /WebexHttpError/g);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// We can't manipulate NODE_ENV in karma, tests, so run this chunk only in
|
|
190
|
+
// node
|
|
191
|
+
describe('#shouldPrint()', () => {
|
|
192
|
+
nodeOnly(afterEach)(() => {
|
|
193
|
+
process.env.WEBEX_LOG_LEVEL = undefined;
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
function testLevels(logType, logConfigSetting) {
|
|
197
|
+
/* eslint max-statements: [0] */
|
|
198
|
+
webex.logger.config[logConfigSetting] = 'trace';
|
|
199
|
+
assert.isTrue(
|
|
200
|
+
webex.logger.shouldPrint('error', logType),
|
|
201
|
+
'it prints `error` logs when the level is `trace`'
|
|
202
|
+
);
|
|
203
|
+
assert.isTrue(
|
|
204
|
+
webex.logger.shouldPrint('warn', logType),
|
|
205
|
+
'it prints `warn` logs when the level is `trace`'
|
|
206
|
+
);
|
|
207
|
+
assert.isTrue(
|
|
208
|
+
webex.logger.shouldPrint('log', logType),
|
|
209
|
+
'it prints `log` logs when the level is `trace`'
|
|
210
|
+
);
|
|
211
|
+
assert.isTrue(
|
|
212
|
+
webex.logger.shouldPrint('info', logType),
|
|
213
|
+
'it prints `info` logs when the level is `trace`'
|
|
214
|
+
);
|
|
215
|
+
assert.isTrue(
|
|
216
|
+
webex.logger.shouldPrint('debug', logType),
|
|
217
|
+
'it prints `debug` logs when the level is `trace`'
|
|
218
|
+
);
|
|
219
|
+
assert.isTrue(
|
|
220
|
+
webex.logger.shouldPrint('trace', logType),
|
|
221
|
+
'it prints `trace` logs when the level is `trace`'
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
webex.logger.config[logConfigSetting] = 'debug';
|
|
225
|
+
assert.isTrue(
|
|
226
|
+
webex.logger.shouldPrint('error', logType),
|
|
227
|
+
'it prints `error` logs when the level is `debug`'
|
|
228
|
+
);
|
|
229
|
+
assert.isTrue(
|
|
230
|
+
webex.logger.shouldPrint('warn', logType),
|
|
231
|
+
'it prints `warn` logs when the level is `debug`'
|
|
232
|
+
);
|
|
233
|
+
assert.isTrue(
|
|
234
|
+
webex.logger.shouldPrint('log', logType),
|
|
235
|
+
'it prints `log` logs when the level is `debug`'
|
|
236
|
+
);
|
|
237
|
+
assert.isTrue(
|
|
238
|
+
webex.logger.shouldPrint('info', logType),
|
|
239
|
+
'it prints `info` logs when the level is `debug`'
|
|
240
|
+
);
|
|
241
|
+
assert.isTrue(
|
|
242
|
+
webex.logger.shouldPrint('debug', logType),
|
|
243
|
+
'it prints `debug` logs when the level is `debug`'
|
|
244
|
+
);
|
|
245
|
+
assert.isFalse(
|
|
246
|
+
webex.logger.shouldPrint('trace', logType),
|
|
247
|
+
'it does not print `trace` logs when the level is `debug`'
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
webex.logger.config[logConfigSetting] = 'info';
|
|
251
|
+
assert.isTrue(
|
|
252
|
+
webex.logger.shouldPrint('error', logType),
|
|
253
|
+
'it prints `error` logs when the level is `info`'
|
|
254
|
+
);
|
|
255
|
+
assert.isTrue(
|
|
256
|
+
webex.logger.shouldPrint('warn', logType),
|
|
257
|
+
'it prints `warn` logs when the level is `info`'
|
|
258
|
+
);
|
|
259
|
+
assert.isTrue(
|
|
260
|
+
webex.logger.shouldPrint('log', logType),
|
|
261
|
+
'it prints `log` logs when the level is `info`'
|
|
262
|
+
);
|
|
263
|
+
assert.isTrue(
|
|
264
|
+
webex.logger.shouldPrint('info', logType),
|
|
265
|
+
'it prints `info` logs when the level is `info`'
|
|
266
|
+
);
|
|
267
|
+
assert.isFalse(
|
|
268
|
+
webex.logger.shouldPrint('debug', logType),
|
|
269
|
+
'it does not print `debug` logs when the level is `info`'
|
|
270
|
+
);
|
|
271
|
+
assert.isFalse(
|
|
272
|
+
webex.logger.shouldPrint('trace', logType),
|
|
273
|
+
'it does not print `trace` logs when the level is `info`'
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
webex.logger.config[logConfigSetting] = 'log';
|
|
277
|
+
assert.isTrue(
|
|
278
|
+
webex.logger.shouldPrint('error', logType),
|
|
279
|
+
'it prints `error` logs when the level is `log`'
|
|
280
|
+
);
|
|
281
|
+
assert.isTrue(
|
|
282
|
+
webex.logger.shouldPrint('warn', logType),
|
|
283
|
+
'it prints `warn` logs when the level is `log`'
|
|
284
|
+
);
|
|
285
|
+
assert.isTrue(
|
|
286
|
+
webex.logger.shouldPrint('log', logType),
|
|
287
|
+
'it prints `log` logs when the level is `log`'
|
|
288
|
+
);
|
|
289
|
+
assert.isFalse(
|
|
290
|
+
webex.logger.shouldPrint('info', logType),
|
|
291
|
+
'it does not print `info` logs when the level is `log`'
|
|
292
|
+
);
|
|
293
|
+
assert.isFalse(
|
|
294
|
+
webex.logger.shouldPrint('debug', logType),
|
|
295
|
+
'it does not print `debug` logs when the level is `log`'
|
|
296
|
+
);
|
|
297
|
+
assert.isFalse(
|
|
298
|
+
webex.logger.shouldPrint('trace', logType),
|
|
299
|
+
'it does not print `trace` logs when the level is `log`'
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
webex.logger.config[logConfigSetting] = 'warn';
|
|
303
|
+
assert.isTrue(
|
|
304
|
+
webex.logger.shouldPrint('error', logType),
|
|
305
|
+
'it prints `error` logs when the level is `warn`'
|
|
306
|
+
);
|
|
307
|
+
assert.isTrue(
|
|
308
|
+
webex.logger.shouldPrint('warn', logType),
|
|
309
|
+
'it prints `warn` logs when the level is `warn`'
|
|
310
|
+
);
|
|
311
|
+
assert.isFalse(
|
|
312
|
+
webex.logger.shouldPrint('log', logType),
|
|
313
|
+
'it does not print `log` logs when the level is `warn`'
|
|
314
|
+
);
|
|
315
|
+
assert.isFalse(
|
|
316
|
+
webex.logger.shouldPrint('info', logType),
|
|
317
|
+
'it does not print `info` logs when the level is `warn`'
|
|
318
|
+
);
|
|
319
|
+
assert.isFalse(
|
|
320
|
+
webex.logger.shouldPrint('debug', logType),
|
|
321
|
+
'it does not print `debug` logs when the level is `warn`'
|
|
322
|
+
);
|
|
323
|
+
assert.isFalse(
|
|
324
|
+
webex.logger.shouldPrint('trace', logType),
|
|
325
|
+
'it does not print `trace` logs when the level is `warn`'
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
webex.logger.config[logConfigSetting] = 'error';
|
|
329
|
+
assert.isTrue(
|
|
330
|
+
webex.logger.shouldPrint('error', logType),
|
|
331
|
+
'it prints `error` logs when the level is `error`'
|
|
332
|
+
);
|
|
333
|
+
assert.isFalse(
|
|
334
|
+
webex.logger.shouldPrint('warn', logType),
|
|
335
|
+
'it does not print `warn` logs when the level `error` is '
|
|
336
|
+
);
|
|
337
|
+
assert.isFalse(
|
|
338
|
+
webex.logger.shouldPrint('log', logType),
|
|
339
|
+
'it does not print `log` logs when the level is `error`'
|
|
340
|
+
);
|
|
341
|
+
assert.isFalse(
|
|
342
|
+
webex.logger.shouldPrint('info', logType),
|
|
343
|
+
'it does not print `info` logs when the level is `error`'
|
|
344
|
+
);
|
|
345
|
+
assert.isFalse(
|
|
346
|
+
webex.logger.shouldPrint('debug', logType),
|
|
347
|
+
'it does not print `debug` logs when the level is `error`'
|
|
348
|
+
);
|
|
349
|
+
assert.isFalse(
|
|
350
|
+
webex.logger.shouldPrint('trace', logType),
|
|
351
|
+
'it does not print `trace` logs when the level is `error`'
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
webex.logger.config[logConfigSetting] = 'silent';
|
|
355
|
+
assert.isFalse(
|
|
356
|
+
webex.logger.shouldPrint('error', logType),
|
|
357
|
+
'it does not print `error` logs when the level is `silent`'
|
|
358
|
+
);
|
|
359
|
+
assert.isFalse(
|
|
360
|
+
webex.logger.shouldPrint('warn', logType),
|
|
361
|
+
'it does not print `warn` logs when the level is `silent`'
|
|
362
|
+
);
|
|
363
|
+
assert.isFalse(
|
|
364
|
+
webex.logger.shouldPrint('log', logType),
|
|
365
|
+
'it does not print `log` logs when the level is `silent`'
|
|
366
|
+
);
|
|
367
|
+
assert.isFalse(
|
|
368
|
+
webex.logger.shouldPrint('info', logType),
|
|
369
|
+
'it does not print `info` logs when the level is `silent`'
|
|
370
|
+
);
|
|
371
|
+
assert.isFalse(
|
|
372
|
+
webex.logger.shouldPrint('debug', logType),
|
|
373
|
+
'it does not print `debug` logs when the level is `silent`'
|
|
374
|
+
);
|
|
375
|
+
assert.isFalse(
|
|
376
|
+
webex.logger.shouldPrint('trace', logType),
|
|
377
|
+
'it does not print `trace` logs when the level is `silent`'
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
it('indicates whether or not the desired log should be printed at the current log level', () => {
|
|
382
|
+
// test independence from client log level
|
|
383
|
+
['trace', 'debug', 'info', 'log', 'warn', 'error', 'silent'].forEach((clientLevel) => {
|
|
384
|
+
webex.logger.config.clientLevel = clientLevel;
|
|
385
|
+
testLevels(undefined, 'level');
|
|
386
|
+
testLevels('sdk', 'level');
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('factors in log type when passed in as client', () => {
|
|
391
|
+
// test independence from sdk log level
|
|
392
|
+
['trace', 'debug', 'info', 'log', 'warn', 'error', 'silent'].forEach((sdkLevel) => {
|
|
393
|
+
webex.logger.config.level = sdkLevel;
|
|
394
|
+
testLevels('client', 'clientLevel');
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
nodeOnly(it)('uses the WEBEX_LOG_LEVEL environment varable to control log level', () => {
|
|
399
|
+
levels.forEach((level) => {
|
|
400
|
+
process.env.WEBEX_LOG_LEVEL = level;
|
|
401
|
+
console[impl(level)].resetHistory();
|
|
402
|
+
webex.logger[level](`test: ${level}`);
|
|
403
|
+
assert.calledOnce(console[impl(level)]);
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('prefers the config specified logger.level', () => {
|
|
408
|
+
levels.forEach((level) => {
|
|
409
|
+
webex.logger.config.level = level;
|
|
410
|
+
console[impl(level)].resetHistory();
|
|
411
|
+
webex.logger[level](`test: ${level}`);
|
|
412
|
+
assert.calledOnce(console[impl(level)]);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
nodeOnly(it)('logs at TRACE in test environments', () => {
|
|
417
|
+
console.trace.restore();
|
|
418
|
+
sinon.stub(console, 'trace');
|
|
419
|
+
process.env.NODE_ENV = undefined;
|
|
420
|
+
assert.notCalled(console.trace);
|
|
421
|
+
webex.logger.trace('test');
|
|
422
|
+
assert.notCalled(console.trace);
|
|
423
|
+
|
|
424
|
+
process.env.NODE_ENV = 'test';
|
|
425
|
+
webex.logger.trace('test');
|
|
426
|
+
assert.called(console.trace);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
nodeOnly(it)('checks the developer feature toggle "log-level" when available', () => {
|
|
430
|
+
assert.notCalled(console.info);
|
|
431
|
+
webex.logger.info('test');
|
|
432
|
+
assert.notCalled(console.info);
|
|
433
|
+
|
|
434
|
+
webex.internal.device = {
|
|
435
|
+
features: {
|
|
436
|
+
developer: {
|
|
437
|
+
get() {
|
|
438
|
+
return 'info';
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
entitlement: {
|
|
442
|
+
get() {
|
|
443
|
+
return false;
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
};
|
|
448
|
+
webex.logger.info('test');
|
|
449
|
+
assert.called(console.info);
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
nodeOnly(it)("doesn't break if the feature toggle is set to an incorrect value", () => {
|
|
453
|
+
assert.doesNotThrow(() => {
|
|
454
|
+
assert.notCalled(console.info);
|
|
455
|
+
webex.logger.info('test');
|
|
456
|
+
assert.notCalled(console.info);
|
|
457
|
+
|
|
458
|
+
webex.internal.device = {
|
|
459
|
+
features: {
|
|
460
|
+
developer: {
|
|
461
|
+
get() {
|
|
462
|
+
return 'not-a-log-method';
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
entitlement: {
|
|
466
|
+
get() {
|
|
467
|
+
return false;
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
webex.logger.info('test');
|
|
473
|
+
assert.notCalled(console.info);
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
nodeOnly(it)('defaults to "error" for all other users', () => {
|
|
478
|
+
webex.logger.error('test');
|
|
479
|
+
assert.called(console.error);
|
|
480
|
+
|
|
481
|
+
webex.logger.warn('test');
|
|
482
|
+
assert.notCalled(console.warn);
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
describe('#shouldBuffer()', () => {
|
|
487
|
+
it('logs info level to buffer by default', () => {
|
|
488
|
+
const shouldBuffer = webex.logger.shouldBuffer('info');
|
|
489
|
+
|
|
490
|
+
assert.isTrue(shouldBuffer);
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it('does not log debug level to buffer by default', () => {
|
|
494
|
+
const shouldBuffer = webex.logger.shouldBuffer('debug');
|
|
495
|
+
|
|
496
|
+
assert.isFalse(shouldBuffer);
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it('logs debug level to buffer if level configured', () => {
|
|
500
|
+
webex.logger.config.bufferLogLevel = 'debug';
|
|
501
|
+
const shouldBuffer = webex.logger.shouldBuffer('debug');
|
|
502
|
+
|
|
503
|
+
assert.isTrue(shouldBuffer);
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
describe('#filter', () => {
|
|
508
|
+
it('redacts email addresses', () => {
|
|
509
|
+
const message = {
|
|
510
|
+
blarg: 'test@example.com',
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
assert.deepEqual(webex.logger.filter(message), [
|
|
514
|
+
{
|
|
515
|
+
blarg: '[REDACTED]',
|
|
516
|
+
},
|
|
517
|
+
]);
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
it('strips auth headers from log output', () => {
|
|
521
|
+
const msg = {
|
|
522
|
+
headers: {
|
|
523
|
+
authorization: 'Bearer',
|
|
524
|
+
},
|
|
525
|
+
options: {
|
|
526
|
+
headers: {
|
|
527
|
+
trackingid: '123',
|
|
528
|
+
authorization: 'Bearer',
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
assert.doesNotThrow(() => {
|
|
534
|
+
webex.logger.filter({});
|
|
535
|
+
webex.logger.filter({headers: {}});
|
|
536
|
+
webex.logger.filter({headers: {authorization: ''}});
|
|
537
|
+
webex.logger.filter({options: {}});
|
|
538
|
+
webex.logger.filter({options: {headers: {}}});
|
|
539
|
+
webex.logger.filter({options: {headers: {authorization: ''}}});
|
|
540
|
+
webex.logger.filter([{options: {headers: {authorization: ''}}}]);
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
const [filtered] = webex.logger.filter(msg);
|
|
544
|
+
|
|
545
|
+
assert.nestedProperty(msg, 'headers.authorization', 'it does not alter the original message');
|
|
546
|
+
assert.nestedProperty(
|
|
547
|
+
msg,
|
|
548
|
+
'options.headers.authorization',
|
|
549
|
+
'it does not alter the original message'
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
assert.notNestedProperty(
|
|
553
|
+
filtered,
|
|
554
|
+
'headers.authorization',
|
|
555
|
+
'it removes headers.authorization'
|
|
556
|
+
);
|
|
557
|
+
assert.notNestedProperty(
|
|
558
|
+
filtered,
|
|
559
|
+
'options.headers.authorization',
|
|
560
|
+
'it removes options.headers.authorization'
|
|
561
|
+
);
|
|
562
|
+
assert.nestedProperty(
|
|
563
|
+
msg,
|
|
564
|
+
'options.headers.trackingid',
|
|
565
|
+
'it does not remove other header values'
|
|
566
|
+
);
|
|
567
|
+
assert.nestedProperty(
|
|
568
|
+
filtered,
|
|
569
|
+
'options.headers.trackingid',
|
|
570
|
+
'it does not remove other header values'
|
|
571
|
+
);
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
['error', 'warn', 'log', 'info', 'debug', 'trace'].forEach((level) => {
|
|
576
|
+
describe(`#${level}()`, () => {
|
|
577
|
+
it(`proxies console.${level}`, () => {
|
|
578
|
+
webex.logger.config.level = level;
|
|
579
|
+
assert.notCalled(console[impl(level)]);
|
|
580
|
+
webex.logger[level]('a log statement');
|
|
581
|
+
assert.called(console[impl(level)]);
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it('removes authorization data', () => {
|
|
585
|
+
webex.logger.config.level = level;
|
|
586
|
+
webex.logger[level]({
|
|
587
|
+
headers: {
|
|
588
|
+
authorization: 'Bearer',
|
|
589
|
+
trackingid: '123',
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
assert.calledWith(console[impl(level)], 'wx-js-sdk', {
|
|
593
|
+
headers: {
|
|
594
|
+
trackingid: '123',
|
|
595
|
+
},
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
describe('#walkAndFilter', () => {
|
|
602
|
+
it('redact Authorization', () => {
|
|
603
|
+
webex.config.logger.level = 'trace';
|
|
604
|
+
webex.logger.log({
|
|
605
|
+
Authorization: 'XXXXXXX',
|
|
606
|
+
Key: 'myKey',
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
// Assert auth was filtered
|
|
610
|
+
assert.calledWith(console.log, 'wx-js-sdk', {Key: 'myKey'});
|
|
611
|
+
|
|
612
|
+
webex.logger.log({
|
|
613
|
+
authorization: 'XXXXXXX',
|
|
614
|
+
Key: 'myKey',
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
assert.calledWith(console.log, 'wx-js-sdk', {Key: 'myKey'});
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
it('redact emails', () => {
|
|
621
|
+
webex.config.logger.level = 'trace';
|
|
622
|
+
|
|
623
|
+
webex.logger.log('my email address is test@cisco.com');
|
|
624
|
+
assert.calledWith(console.log, 'wx-js-sdk', 'my email address is [REDACTED]');
|
|
625
|
+
|
|
626
|
+
webex.logger.log('test@cisco.com');
|
|
627
|
+
assert.calledWith(console.log, 'wx-js-sdk', '[REDACTED]');
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('handle circular references', () => {
|
|
631
|
+
webex.config.logger.level = 'trace';
|
|
632
|
+
|
|
633
|
+
const object = {
|
|
634
|
+
authorization: 'XXXXXXX',
|
|
635
|
+
string: 'test@cisco.com',
|
|
636
|
+
Key: 'myKey',
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
// Add a circular reference to the object
|
|
640
|
+
object.selfReference = object;
|
|
641
|
+
|
|
642
|
+
webex.logger.log(object);
|
|
643
|
+
|
|
644
|
+
const expected = {
|
|
645
|
+
string: '[REDACTED]',
|
|
646
|
+
Key: 'myKey',
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
expected.selfReference = expected;
|
|
650
|
+
|
|
651
|
+
assert.calledWith(console.log, 'wx-js-sdk', expected);
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
it('handle circular references in complex objects', () => {
|
|
655
|
+
webex.config.logger.level = 'trace';
|
|
656
|
+
|
|
657
|
+
const func = () => true;
|
|
658
|
+
const sym = Symbol('foo');
|
|
659
|
+
|
|
660
|
+
const object = {
|
|
661
|
+
primativeString: 'justastring',
|
|
662
|
+
primativeNum: 5,
|
|
663
|
+
primativeBool: true,
|
|
664
|
+
primativeSymbol: sym,
|
|
665
|
+
myFunction: func,
|
|
666
|
+
subObject: {
|
|
667
|
+
subPrimativeString: 'justastring',
|
|
668
|
+
otherPrimativeString: 'otherstring',
|
|
669
|
+
subPrimativeNum: 5,
|
|
670
|
+
otherPrimativeNum: 6,
|
|
671
|
+
subPrimativeBool: true,
|
|
672
|
+
otherPrimativeBool: false,
|
|
673
|
+
subPrimativeSymbol: sym,
|
|
674
|
+
},
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
object.subObject.circularObjectRef = object;
|
|
678
|
+
object.subObject.circularFunctionRef = func;
|
|
679
|
+
object.subObject.circularFunctionRef.cat = func;
|
|
680
|
+
|
|
681
|
+
webex.logger.log(object);
|
|
682
|
+
|
|
683
|
+
assert.calledWith(console.log, 'wx-js-sdk', {
|
|
684
|
+
primativeString: 'justastring',
|
|
685
|
+
primativeNum: 5,
|
|
686
|
+
primativeBool: true,
|
|
687
|
+
primativeSymbol: sym,
|
|
688
|
+
myFunction: func,
|
|
689
|
+
subObject: {
|
|
690
|
+
subPrimativeString: 'justastring',
|
|
691
|
+
otherPrimativeString: 'otherstring',
|
|
692
|
+
subPrimativeNum: 5,
|
|
693
|
+
otherPrimativeNum: 6,
|
|
694
|
+
subPrimativeBool: true,
|
|
695
|
+
otherPrimativeBool: false,
|
|
696
|
+
subPrimativeSymbol: sym,
|
|
697
|
+
circularObjectRef: object,
|
|
698
|
+
circularFunctionRef: func,
|
|
699
|
+
},
|
|
700
|
+
});
|
|
701
|
+
});
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
describe('#formatLogs()', () => {
|
|
705
|
+
function sendRandomLog(log) {
|
|
706
|
+
const logMethod = Math.round(Math.random()) ? 'log' : 'client_log';
|
|
707
|
+
|
|
708
|
+
webex.logger[logMethod](log);
|
|
709
|
+
}
|
|
710
|
+
function sleep(ms) {
|
|
711
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
712
|
+
}
|
|
713
|
+
function checkAscending(logs) {
|
|
714
|
+
const logLines = logs.split('\n');
|
|
715
|
+
|
|
716
|
+
let lastvalue;
|
|
717
|
+
|
|
718
|
+
for (let i = 0; i < logLines.length; i += 1) {
|
|
719
|
+
const fields = logLines[i].split(',');
|
|
720
|
+
|
|
721
|
+
if (lastvalue) {
|
|
722
|
+
assert.isTrue(lastvalue < fields[3]);
|
|
723
|
+
}
|
|
724
|
+
lastvalue = fields[3];
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
it('formats mixed log types in order by default', async () => {
|
|
729
|
+
for (let i = 0; i < 10; i += 1) {
|
|
730
|
+
sendRandomLog(i);
|
|
731
|
+
await sleep(i);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
const logs = webex.logger.formatLogs();
|
|
735
|
+
|
|
736
|
+
checkAscending(logs);
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
it('formats mixed log types in order with separate buffers', async () => {
|
|
740
|
+
webex.config.logger.separateLogBuffers = true;
|
|
741
|
+
webex.config.logger.clientName = 'someclient';
|
|
742
|
+
for (let i = 0; i < 10; i += 1) {
|
|
743
|
+
sendRandomLog(i);
|
|
744
|
+
await sleep(i);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const logs = webex.logger.formatLogs();
|
|
748
|
+
|
|
749
|
+
checkAscending(logs);
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
it('handles only sdk logs with separate buffers', async () => {
|
|
753
|
+
webex.config.logger.separateLogBuffers = true;
|
|
754
|
+
webex.config.logger.clientName = 'someclient';
|
|
755
|
+
for (let i = 0; i < 10; i += 1) {
|
|
756
|
+
webex.logger.log(i);
|
|
757
|
+
await sleep(i);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const logs = webex.logger.formatLogs();
|
|
761
|
+
|
|
762
|
+
checkAscending(logs);
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
it('handles only client logs with separate buffers', async () => {
|
|
766
|
+
webex.config.logger.separateLogBuffers = true;
|
|
767
|
+
webex.config.logger.clientName = 'someclient';
|
|
768
|
+
for (let i = 0; i < 10; i += 1) {
|
|
769
|
+
webex.logger.client_log(i);
|
|
770
|
+
await sleep(i);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
const logs = webex.logger.formatLogs();
|
|
774
|
+
|
|
775
|
+
checkAscending(logs);
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
describe('#logToBuffer()', () => {
|
|
780
|
+
it('logs only to buffer by default', () => {
|
|
781
|
+
webex.logger.logToBuffer('sdklog');
|
|
782
|
+
webex.logger.client_logToBuffer('clientlog');
|
|
783
|
+
|
|
784
|
+
assert.lengthOf(webex.logger.buffer, 2);
|
|
785
|
+
|
|
786
|
+
logSpies.forEach((logSpy) => {
|
|
787
|
+
assert.notCalled(logSpy);
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
it('logs only to buffer with separate buffers', () => {
|
|
791
|
+
webex.config.logger.separateLogBuffers = true;
|
|
792
|
+
webex.config.logger.clientName = 'someclient';
|
|
793
|
+
|
|
794
|
+
webex.logger.logToBuffer('sdklog');
|
|
795
|
+
webex.logger.client_logToBuffer('clientlog');
|
|
796
|
+
|
|
797
|
+
assert.lengthOf(webex.logger.sdkBuffer, 1);
|
|
798
|
+
assert.lengthOf(webex.logger.clientBuffer, 1);
|
|
799
|
+
|
|
800
|
+
logSpies.forEach((logSpy) => {
|
|
801
|
+
assert.notCalled(logSpy);
|
|
802
|
+
});
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
});
|