@microsoft/applicationinsights-analytics-js 2.7.2-nightly.2111-05 → 2.7.2-nightly.2111-09
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/Tests/Unit/src/AnalyticsExtensionSize.tests.ts +58 -0
- package/Tests/Unit/src/ApplicationInsights.tests.ts +1647 -0
- package/Tests/Unit/src/TelemetryItemCreator.tests.ts +304 -0
- package/Tests/Unit/src/appinsights-analytics.tests.ts +9 -0
- package/Tests/UnitTests.html +62 -0
- package/Tests/tsconfig.json +13 -0
- package/api-extractor.json +361 -0
- package/applicationinsights-analytics-js.build.error.log +80 -0
- package/applicationinsights-analytics-js.build.log +309 -0
- package/browser/applicationinsights-analytics-js.integrity.json +9 -9
- package/browser/applicationinsights-analytics-js.js +2 -2
- package/browser/applicationinsights-analytics-js.js.map +1 -1
- package/browser/applicationinsights-analytics-js.min.js +2 -2
- package/browser/applicationinsights-analytics-js.min.js.map +1 -1
- package/dist/applicationinsights-analytics-js.api.json +1 -1
- package/dist/applicationinsights-analytics-js.d.ts +1 -1
- package/dist/applicationinsights-analytics-js.js +2 -2
- package/dist/applicationinsights-analytics-js.js.map +1 -1
- package/dist/applicationinsights-analytics-js.min.js +2 -2
- package/dist/applicationinsights-analytics-js.min.js.map +1 -1
- package/dist/applicationinsights-analytics-js.rollup.d.ts +1 -1
- package/dist-esm/JavaScriptSDK/ApplicationInsights.js +2 -2
- package/dist-esm/JavaScriptSDK/ApplicationInsights.js.map +1 -1
- package/dist-esm/JavaScriptSDK/Telemetry/PageViewManager.js +1 -1
- package/dist-esm/JavaScriptSDK/Telemetry/PageViewPerformanceManager.js +1 -1
- package/dist-esm/JavaScriptSDK/Telemetry/PageVisitTimeManager.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryConfig.js +1 -1
- package/dist-esm/applicationinsights-analytics-js.js +1 -1
- package/microsoft-applicationinsights-analytics-js-2.7.2-nightly.2111-09.tgz +0 -0
- package/package.json +5 -5
- package/rollup.config.js +139 -0
- package/src/JavaScriptSDK/ApplicationInsights.ts +1 -1
- package/temp/applicationinsights-analytics-js.api.md +114 -0
- package/tslint.json +5 -0
- package/types/tsdoc-metadata.json +1 -1
|
@@ -0,0 +1,1647 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Assert, AITestClass, PollingAssert, EventValidator, TraceValidator, ExceptionValidator,
|
|
3
|
+
MetricValidator, PageViewPerformanceValidator, PageViewValidator, RemoteDepdencyValidator
|
|
4
|
+
} from "@microsoft/ai-test-framework";
|
|
5
|
+
import { SinonStub, SinonSpy } from 'sinon';
|
|
6
|
+
import {
|
|
7
|
+
Exception, SeverityLevel, Event, Trace, PageViewPerformance, IConfig, IExceptionInternal,
|
|
8
|
+
AnalyticsPluginIdentifier, Util, IAppInsights, Metric, PageView, RemoteDependencyData
|
|
9
|
+
} from "@microsoft/applicationinsights-common";
|
|
10
|
+
import { ITelemetryItem, AppInsightsCore, IPlugin, IConfiguration, IAppInsightsCore, setEnableEnvMocks, getLocation, dumpObj } from "@microsoft/applicationinsights-core-js";
|
|
11
|
+
import { Sender } from "@microsoft/applicationinsights-channel-js"
|
|
12
|
+
import { PropertiesPlugin } from "@microsoft/applicationinsights-properties-js";
|
|
13
|
+
import { ApplicationInsights } from "../../../src/JavaScriptSDK/ApplicationInsights";
|
|
14
|
+
|
|
15
|
+
declare class ExceptionHelper {
|
|
16
|
+
capture: (appInsights:IAppInsights) => void;
|
|
17
|
+
captureStrict: (appInsights:IAppInsights) => void;
|
|
18
|
+
throw: (value:any) => void;
|
|
19
|
+
throwCors: () => void;
|
|
20
|
+
throwStrict: (value:any) => void;
|
|
21
|
+
throwRuntimeException: (timeoutFunc: VoidFunction) => void;
|
|
22
|
+
throwStrictRuntimeException: (timeoutFunc: VoidFunction) => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export class ApplicationInsightsTests extends AITestClass {
|
|
26
|
+
private _onerror:any = null;
|
|
27
|
+
private trackSpy:SinonSpy;
|
|
28
|
+
private throwInternalSpy:SinonSpy;
|
|
29
|
+
private exceptionHelper: any = new ExceptionHelper();
|
|
30
|
+
|
|
31
|
+
public testInitialize() {
|
|
32
|
+
this._onerror = window.onerror;
|
|
33
|
+
setEnableEnvMocks(false);
|
|
34
|
+
super.testInitialize();
|
|
35
|
+
Util.setCookie(undefined, 'ai_session', "");
|
|
36
|
+
Util.setCookie(undefined, 'ai_user', "");
|
|
37
|
+
if (Util.canUseLocalStorage()) {
|
|
38
|
+
window.localStorage.clear();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public testCleanup() {
|
|
43
|
+
super.testCleanup();
|
|
44
|
+
Util.setCookie(undefined, 'ai_session', "");
|
|
45
|
+
Util.setCookie(undefined, 'ai_user', "");
|
|
46
|
+
if (Util.canUseLocalStorage()) {
|
|
47
|
+
window.localStorage.clear();
|
|
48
|
+
}
|
|
49
|
+
window.onerror = this._onerror;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public causeException(cb:Function) {
|
|
53
|
+
AITestClass.orgSetTimeout(() => {
|
|
54
|
+
cb();
|
|
55
|
+
}, 0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public registerTests() {
|
|
59
|
+
|
|
60
|
+
this.testCase({
|
|
61
|
+
name: 'enableAutoRouteTracking: event listener is added to the popstate event',
|
|
62
|
+
test: () => {
|
|
63
|
+
// Setup
|
|
64
|
+
const appInsights = new ApplicationInsights();
|
|
65
|
+
const core = new AppInsightsCore();
|
|
66
|
+
const channel = new ChannelPlugin();
|
|
67
|
+
const eventListenerStub = this.sandbox.stub(window, 'addEventListener');
|
|
68
|
+
|
|
69
|
+
// Act
|
|
70
|
+
core.initialize({
|
|
71
|
+
instrumentationKey: '',
|
|
72
|
+
enableAutoRouteTracking: true
|
|
73
|
+
} as IConfig & IConfiguration, [appInsights, channel]);
|
|
74
|
+
|
|
75
|
+
// Assert
|
|
76
|
+
Assert.ok(eventListenerStub.calledTwice);
|
|
77
|
+
Assert.equal(eventListenerStub.args[0][0], "popstate");
|
|
78
|
+
Assert.equal(eventListenerStub.args[1][0], "locationchange");
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
this.testCase({
|
|
83
|
+
name: 'enableAutoRouteTracking: route changes trigger a new pageview',
|
|
84
|
+
useFakeTimers: true,
|
|
85
|
+
test: () => {
|
|
86
|
+
// Current URL will be the test page
|
|
87
|
+
setEnableEnvMocks(true);
|
|
88
|
+
this.setLocationHref("firstUri");
|
|
89
|
+
|
|
90
|
+
// Setup
|
|
91
|
+
const appInsights = new ApplicationInsights();
|
|
92
|
+
appInsights.autoRoutePVDelay = 500;
|
|
93
|
+
const core = new AppInsightsCore();
|
|
94
|
+
const channel = new ChannelPlugin();
|
|
95
|
+
const properties = new PropertiesPlugin();
|
|
96
|
+
properties.context = { telemetryTrace: { traceID: 'not set', name: 'name not set' } } as any;
|
|
97
|
+
const trackPageViewStub = this.sandbox.stub(appInsights, 'trackPageView');
|
|
98
|
+
|
|
99
|
+
// Act
|
|
100
|
+
core.initialize({
|
|
101
|
+
instrumentationKey: '',
|
|
102
|
+
enableAutoRouteTracking: true
|
|
103
|
+
} as IConfig & IConfiguration, [appInsights, channel, properties]);
|
|
104
|
+
this.setLocationHref("secondUri");
|
|
105
|
+
window.dispatchEvent(Util.createDomEvent('locationchange'));
|
|
106
|
+
this.clock.tick(500);
|
|
107
|
+
|
|
108
|
+
this.setLocationHref("thirdUri");
|
|
109
|
+
window.dispatchEvent(Util.createDomEvent('locationchange'));
|
|
110
|
+
this.clock.tick(500);
|
|
111
|
+
|
|
112
|
+
// Assert
|
|
113
|
+
Assert.equal(2, trackPageViewStub.callCount);
|
|
114
|
+
Assert.ok(properties.context.telemetryTrace.traceID);
|
|
115
|
+
Assert.ok(properties.context.telemetryTrace.name);
|
|
116
|
+
Assert.notEqual(properties.context.telemetryTrace.traceID, 'not set', 'current operation id is updated after route change');
|
|
117
|
+
Assert.notEqual(properties.context.telemetryTrace.name, 'name not set', 'current operation name is updated after route change');
|
|
118
|
+
// Assert.equal(appInsights['_prevUri'], 'secondUri', "the previous uri is stored on variable _prevUri");
|
|
119
|
+
// Assert.equal(appInsights['_currUri'], window.location.href, "the current uri is stored on variable _currUri");
|
|
120
|
+
|
|
121
|
+
Assert.equal("firstUri", trackPageViewStub.args[0][0].refUri, "previous uri is assigned to refUri as firstUri, and send as an argument of trackPageview method");
|
|
122
|
+
Assert.equal("secondUri", trackPageViewStub.args[1][0].refUri, "previous uri is assigned to refUri as secondUri and send as an argument of trackPageview method");
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
this.testCase({
|
|
127
|
+
name: 'enableAutoRouteTracking: route changes trigger a new pageview with correct refUri when route changes happening before the timer autoRoutePVDelay stops',
|
|
128
|
+
useFakeTimers: true,
|
|
129
|
+
test: () => {
|
|
130
|
+
// Setup
|
|
131
|
+
setEnableEnvMocks(true);
|
|
132
|
+
this.setLocationHref("firstUri");
|
|
133
|
+
|
|
134
|
+
const appInsights = new ApplicationInsights();
|
|
135
|
+
appInsights.autoRoutePVDelay = 500;
|
|
136
|
+
const core = new AppInsightsCore();
|
|
137
|
+
const channel = new ChannelPlugin();
|
|
138
|
+
const properties = new PropertiesPlugin();
|
|
139
|
+
properties.context = { telemetryTrace: { traceID: 'not set', name: 'name not set' } } as any;
|
|
140
|
+
appInsights['_prevUri'] = "firstUri";
|
|
141
|
+
const trackPageViewStub = this.sandbox.stub(appInsights, 'trackPageView');
|
|
142
|
+
|
|
143
|
+
// Act
|
|
144
|
+
core.initialize({
|
|
145
|
+
instrumentationKey: '',
|
|
146
|
+
enableAutoRouteTracking: true
|
|
147
|
+
} as IConfig & IConfiguration, [appInsights, channel, properties]);
|
|
148
|
+
window.dispatchEvent(Util.createDomEvent('locationchange'));
|
|
149
|
+
this.clock.tick(200);
|
|
150
|
+
|
|
151
|
+
// set up second dispatch
|
|
152
|
+
window.dispatchEvent(Util.createDomEvent('locationchange'));
|
|
153
|
+
this.clock.tick(500);
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
// Assert
|
|
157
|
+
Assert.equal(2, trackPageViewStub.callCount);
|
|
158
|
+
Assert.ok(properties.context.telemetryTrace.traceID);
|
|
159
|
+
Assert.ok(properties.context.telemetryTrace.name);
|
|
160
|
+
Assert.notEqual(properties.context.telemetryTrace.traceID, 'not set', 'current operation id is updated after route change');
|
|
161
|
+
Assert.notEqual(properties.context.telemetryTrace.name, 'name not set', 'current operation name is updated after route change');
|
|
162
|
+
// first trackPageView event
|
|
163
|
+
Assert.equal(trackPageViewStub.args[0][0].refUri, 'firstUri', "first trackPageview event: refUri grabs the value of existing _prevUri");
|
|
164
|
+
// Assert.equal(appInsights['_currUri'], getLocation(true).href, "first trackPageview event: the current uri is stored on variable _currUri");
|
|
165
|
+
// second trackPageView event
|
|
166
|
+
Assert.equal(trackPageViewStub.args[1][0].refUri, getLocation(true).href, "second trackPageview event: refUri grabs the value of updated _prevUri, which is the first pageView event's _currUri");
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
this.testCase({
|
|
171
|
+
name: 'enableAutoRouteTracking: (IE9) app does not crash if history.pushState does not exist',
|
|
172
|
+
test: () => {
|
|
173
|
+
// Setup
|
|
174
|
+
const originalPushState = history.pushState;
|
|
175
|
+
const originalReplaceState = history.replaceState;
|
|
176
|
+
history.pushState = null;
|
|
177
|
+
history.replaceState = null;
|
|
178
|
+
const appInsights = new ApplicationInsights();
|
|
179
|
+
const core = new AppInsightsCore();
|
|
180
|
+
const channel = new ChannelPlugin();
|
|
181
|
+
const properties = new PropertiesPlugin();
|
|
182
|
+
properties.context = { telemetryTrace: { traceID: 'not set', parentID: undefined} } as any;
|
|
183
|
+
this.sandbox.stub(appInsights, 'trackPageView');
|
|
184
|
+
|
|
185
|
+
// Act
|
|
186
|
+
core.initialize({
|
|
187
|
+
instrumentationKey: '',
|
|
188
|
+
enableAutoRouteTracking: true
|
|
189
|
+
} as IConfig & IConfiguration, [appInsights, channel]);
|
|
190
|
+
window.dispatchEvent(Util.createDomEvent('locationchange'));
|
|
191
|
+
|
|
192
|
+
// Assert
|
|
193
|
+
Assert.ok(true, 'App does not crash when history object is incomplete');
|
|
194
|
+
|
|
195
|
+
// Cleanup
|
|
196
|
+
history.pushState = originalPushState;
|
|
197
|
+
history.replaceState = originalReplaceState;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
this.testCase({
|
|
202
|
+
name: 'AppInsightsTests: PageVisitTimeManager is constructed when analytics plugin is initialized',
|
|
203
|
+
test: () => {
|
|
204
|
+
// Setup
|
|
205
|
+
const channel = new ChannelPlugin();
|
|
206
|
+
const core = new AppInsightsCore();
|
|
207
|
+
const appInsights: ApplicationInsights = new ApplicationInsights();
|
|
208
|
+
|
|
209
|
+
// Act
|
|
210
|
+
const config = {
|
|
211
|
+
instrumentationKey: 'ikey'
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
core.initialize(
|
|
215
|
+
config,
|
|
216
|
+
[appInsights, channel]
|
|
217
|
+
);
|
|
218
|
+
const pvtm = appInsights['_pageVisitTimeManager'];
|
|
219
|
+
|
|
220
|
+
// Assert
|
|
221
|
+
Assert.ok(pvtm)
|
|
222
|
+
Assert.ok(pvtm['_logger']);
|
|
223
|
+
Assert.ok(pvtm['pageVisitTimeTrackingHandler']);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
this.testCase({
|
|
228
|
+
name: 'AppInsightsTests: PageVisitTimeManager is available when config.autoTrackPageVisitTime is true and trackPageView is called',
|
|
229
|
+
test: () => {
|
|
230
|
+
// Setup
|
|
231
|
+
const channel = new ChannelPlugin();
|
|
232
|
+
const core = new AppInsightsCore();
|
|
233
|
+
const appInsights: ApplicationInsights = new ApplicationInsights();
|
|
234
|
+
|
|
235
|
+
const config = {
|
|
236
|
+
instrumentationKey: 'ikey',
|
|
237
|
+
autoTrackPageVisitTime: true
|
|
238
|
+
};
|
|
239
|
+
core.initialize(
|
|
240
|
+
config,
|
|
241
|
+
[appInsights, channel]
|
|
242
|
+
);
|
|
243
|
+
const pvtm = appInsights['_pageVisitTimeManager'];
|
|
244
|
+
const pvtmSpy = this.sandbox.spy(pvtm, 'trackPreviousPageVisit');
|
|
245
|
+
|
|
246
|
+
Assert.ok(pvtm)
|
|
247
|
+
Assert.ok(pvtmSpy.notCalled);
|
|
248
|
+
|
|
249
|
+
// Act
|
|
250
|
+
appInsights.trackPageView();
|
|
251
|
+
|
|
252
|
+
// Assert
|
|
253
|
+
Assert.ok(pvtmSpy.calledOnce);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
this.testCase({
|
|
258
|
+
name: 'AppInsightsTests: config can be set from root',
|
|
259
|
+
test: () => {
|
|
260
|
+
// Setup
|
|
261
|
+
const appInsights = new ApplicationInsights();
|
|
262
|
+
const core = new AppInsightsCore();
|
|
263
|
+
const channel = new ChannelPlugin();
|
|
264
|
+
const properties = new PropertiesPlugin();
|
|
265
|
+
|
|
266
|
+
// Act
|
|
267
|
+
const config = {
|
|
268
|
+
instrumentationKey: 'instrumentation_key',
|
|
269
|
+
samplingPercentage: 12,
|
|
270
|
+
accountId: 'aaa',
|
|
271
|
+
extensionConfig: {
|
|
272
|
+
[appInsights.identifier]: {
|
|
273
|
+
accountId: 'def'
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// Initialize
|
|
279
|
+
core.initialize(config, [appInsights, channel, properties]);
|
|
280
|
+
|
|
281
|
+
// Assert
|
|
282
|
+
Assert.equal(12, appInsights.config.samplingPercentage);
|
|
283
|
+
Assert.notEqual('aaa', appInsights.config.accountId);
|
|
284
|
+
Assert.equal('def', appInsights.config.accountId);
|
|
285
|
+
Assert.equal('instrumentation_key', (appInsights['config'] as IConfiguration).instrumentationKey);
|
|
286
|
+
Assert.equal(30 * 60 * 1000, appInsights.config.sessionRenewalMs);
|
|
287
|
+
Assert.equal(24 * 60 * 60 * 1000, appInsights.config.sessionExpirationMs);
|
|
288
|
+
|
|
289
|
+
let extConfig = (core.config as IConfiguration).extensionConfig[AnalyticsPluginIdentifier] as IConfig;
|
|
290
|
+
Assert.equal('instrumentation_key', core.config.instrumentationKey);
|
|
291
|
+
Assert.equal(12, extConfig.samplingPercentage);
|
|
292
|
+
Assert.notEqual('aaa', extConfig.accountId);
|
|
293
|
+
Assert.equal('def', extConfig.accountId);
|
|
294
|
+
Assert.equal('instrumentation_key', (extConfig as any).instrumentationKey);
|
|
295
|
+
Assert.equal(30 * 60 * 1000, extConfig.sessionRenewalMs);
|
|
296
|
+
Assert.equal(24 * 60 * 60 * 1000, extConfig.sessionExpirationMs);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
this.testCase({
|
|
301
|
+
name: "AppInsightsTests: public members are correct",
|
|
302
|
+
test: () => {
|
|
303
|
+
// setup
|
|
304
|
+
const appInsights = new ApplicationInsights();
|
|
305
|
+
// the assert test will only see config as part of an object member if it has been initialized. Not sure how it worked before
|
|
306
|
+
appInsights.config = {};
|
|
307
|
+
const leTest = (name) => {
|
|
308
|
+
// assert
|
|
309
|
+
Assert.ok(name in appInsights, name + " exists");
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// act
|
|
313
|
+
const members = [
|
|
314
|
+
"config",
|
|
315
|
+
"trackException",
|
|
316
|
+
"_onerror",
|
|
317
|
+
"trackEvent",
|
|
318
|
+
"trackTrace",
|
|
319
|
+
"trackMetric",
|
|
320
|
+
"trackPageView",
|
|
321
|
+
"trackPageViewPerformance",
|
|
322
|
+
"startTrackPage",
|
|
323
|
+
"stopTrackPage"
|
|
324
|
+
];
|
|
325
|
+
while (members.length) {
|
|
326
|
+
leTest(members.pop());
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
this.addGenericTests();
|
|
332
|
+
this.addStartStopTrackPageTests();
|
|
333
|
+
this.addTrackExceptionTests();
|
|
334
|
+
this.addOnErrorTests();
|
|
335
|
+
this.addTrackMetricTests();
|
|
336
|
+
this.addTelemetryInitializerTests();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private addGenericTests(): void {
|
|
340
|
+
this.testCase({
|
|
341
|
+
name: 'AppInsightsGenericTests: envelope type, data type, and ikey are correct',
|
|
342
|
+
test: () => {
|
|
343
|
+
// setup
|
|
344
|
+
const iKey: string = "BDC8736D-D8E8-4B69-B19B-B0CE6B66A456";
|
|
345
|
+
const iKeyNoDash: string = "BDC8736DD8E84B69B19BB0CE6B66A456";
|
|
346
|
+
const plugin = new ChannelPlugin();
|
|
347
|
+
const core = new AppInsightsCore();
|
|
348
|
+
core.initialize(
|
|
349
|
+
{instrumentationKey: iKey},
|
|
350
|
+
[plugin]
|
|
351
|
+
);
|
|
352
|
+
const appInsights = new ApplicationInsights();
|
|
353
|
+
appInsights.initialize({instrumentationKey: core.config.instrumentationKey}, core, []);
|
|
354
|
+
const trackStub = this.sandbox.stub(appInsights.core, "track");
|
|
355
|
+
|
|
356
|
+
let envelope: ITelemetryItem;
|
|
357
|
+
const test = (action, expectedEnvelopeType, expectedDataType, test?: () => void) => {
|
|
358
|
+
action();
|
|
359
|
+
envelope = this.getFirstResult(action, trackStub);
|
|
360
|
+
Assert.equal("", envelope.iKey, "envelope iKey");
|
|
361
|
+
Assert.equal(expectedEnvelopeType, envelope.name, "envelope name");
|
|
362
|
+
Assert.equal(expectedDataType, envelope.baseType, "data type name");
|
|
363
|
+
if (typeof test === 'function') {test();}
|
|
364
|
+
trackStub.reset();
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
// Test
|
|
368
|
+
test(() => appInsights.trackException({exception: new Error(), severityLevel: SeverityLevel.Critical}), Exception.envelopeType, Exception.dataType)
|
|
369
|
+
test(() => appInsights.trackException({error: new Error(), severityLevel: SeverityLevel.Critical}), Exception.envelopeType, Exception.dataType)
|
|
370
|
+
test(() => appInsights.trackTrace({message: "some string"}), Trace.envelopeType, Trace.dataType);
|
|
371
|
+
test(() => appInsights.trackPageViewPerformance({name: undefined, uri: undefined, measurements: {somefield: 123}}, {vpHeight: 123}), PageViewPerformance.envelopeType, PageViewPerformance.dataType, () => {
|
|
372
|
+
Assert.deepEqual(undefined, envelope.baseData.properties, 'Properties does not exist in Part B');
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
this.testCase({
|
|
378
|
+
name: 'AppInsightsGenericTests: public APIs call track',
|
|
379
|
+
useFakeTimers: true,
|
|
380
|
+
test: () => {
|
|
381
|
+
// setup
|
|
382
|
+
const plugin = new ChannelPlugin();
|
|
383
|
+
const core = new AppInsightsCore();
|
|
384
|
+
core.initialize(
|
|
385
|
+
{instrumentationKey: "key"},
|
|
386
|
+
[plugin]
|
|
387
|
+
);
|
|
388
|
+
const appInsights = new ApplicationInsights();
|
|
389
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
390
|
+
const senderStub = this.sandbox.stub(appInsights.core, "track");
|
|
391
|
+
|
|
392
|
+
// Act
|
|
393
|
+
appInsights.trackException({exception: new Error(), severityLevel: SeverityLevel.Critical});
|
|
394
|
+
appInsights.trackException({error: new Error(), severityLevel: SeverityLevel.Critical});
|
|
395
|
+
this.clock.tick(1);
|
|
396
|
+
|
|
397
|
+
// Test
|
|
398
|
+
Assert.ok(senderStub.calledTwice, "Telemetry is sent when master switch is on");
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private addTrackExceptionTests(): void {
|
|
404
|
+
this.testCase({
|
|
405
|
+
name: "TrackExceptionTests: trackException accepts single exception",
|
|
406
|
+
test: () => {
|
|
407
|
+
// setup
|
|
408
|
+
const plugin = new ChannelPlugin();
|
|
409
|
+
const core = new AppInsightsCore();
|
|
410
|
+
core.initialize(
|
|
411
|
+
{instrumentationKey: "key"},
|
|
412
|
+
[plugin]
|
|
413
|
+
);
|
|
414
|
+
const appInsights = new ApplicationInsights();
|
|
415
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
416
|
+
const trackStub = this.sandbox.stub(appInsights.core, "track");
|
|
417
|
+
|
|
418
|
+
// Test
|
|
419
|
+
appInsights.trackException({error: new Error(), severityLevel: SeverityLevel.Critical});
|
|
420
|
+
Assert.ok(trackStub.calledOnce, "single exception is tracked");
|
|
421
|
+
|
|
422
|
+
// Verify ver is a string, as required by CS4.0
|
|
423
|
+
const baseData = (trackStub.args[0][0] as ITelemetryItem).baseData as IExceptionInternal;
|
|
424
|
+
Assert.equal("string", typeof baseData.ver, "Exception.ver should be a string for CS4.0");
|
|
425
|
+
Assert.equal("4.0", baseData.ver);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
this.testCase({
|
|
430
|
+
name: "TrackExceptionTests: trackException allows logging errors with different severity level",
|
|
431
|
+
test: () => {
|
|
432
|
+
// setup
|
|
433
|
+
const plugin = new ChannelPlugin();
|
|
434
|
+
const core = new AppInsightsCore();
|
|
435
|
+
core.initialize(
|
|
436
|
+
{instrumentationKey: "key"},
|
|
437
|
+
[plugin]
|
|
438
|
+
);
|
|
439
|
+
const appInsights = new ApplicationInsights();
|
|
440
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
441
|
+
const trackStub = this.sandbox.stub(appInsights.core, "track");
|
|
442
|
+
|
|
443
|
+
// Test
|
|
444
|
+
appInsights.trackException({error: new Error(), severityLevel: SeverityLevel.Critical});
|
|
445
|
+
Assert.ok(trackStub.calledOnce, "single exception is tracked");
|
|
446
|
+
Assert.equal(SeverityLevel.Critical, trackStub.firstCall.args[0].baseData.severityLevel);
|
|
447
|
+
|
|
448
|
+
trackStub.reset();
|
|
449
|
+
|
|
450
|
+
appInsights.trackException({error: new Error(), severityLevel: SeverityLevel.Error});
|
|
451
|
+
Assert.ok(trackStub.calledOnce, "single exception is tracked");
|
|
452
|
+
Assert.equal(SeverityLevel.Error, trackStub.firstCall.args[0].baseData.severityLevel);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
private addOnErrorTests(): void {
|
|
458
|
+
this.testCase({
|
|
459
|
+
name: "OnErrorTests: _onerror creates a dump of unexpected error thrown by trackException for logging",
|
|
460
|
+
test: () => {
|
|
461
|
+
// setup
|
|
462
|
+
const plugin = new ChannelPlugin();
|
|
463
|
+
const core = new AppInsightsCore();
|
|
464
|
+
core.initialize(
|
|
465
|
+
{instrumentationKey: "key"},
|
|
466
|
+
[plugin]
|
|
467
|
+
);
|
|
468
|
+
const appInsights = new ApplicationInsights();
|
|
469
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
470
|
+
|
|
471
|
+
const unexpectedError = new Error();
|
|
472
|
+
const expectedString = dumpObj(unexpectedError);
|
|
473
|
+
const throwSpy = this.sandbox.spy(core.logger, "throwInternal");
|
|
474
|
+
this.sandbox.stub(appInsights, "trackException").throws(unexpectedError);
|
|
475
|
+
|
|
476
|
+
// Act
|
|
477
|
+
appInsights._onerror({message: "msg", url: "some://url", lineNumber: 123, columnNumber: 456, error: unexpectedError});
|
|
478
|
+
|
|
479
|
+
// Assert
|
|
480
|
+
Assert.equal(1, throwSpy.callCount);
|
|
481
|
+
// Check Message
|
|
482
|
+
Assert.ok(throwSpy.args[0][2].indexOf("_onError threw exception while logging error,") !== -1, "Message should indicate that _onError failed");
|
|
483
|
+
// Check Exception contains the exception details
|
|
484
|
+
Assert.ok(throwSpy.args[0][3].exception.indexOf(expectedString) !== -1, "Expected error to contain - " + expectedString);
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
this.testCase({
|
|
489
|
+
name: "OnErrorTests: _onerror stringifies error object",
|
|
490
|
+
test: () => {
|
|
491
|
+
// setup
|
|
492
|
+
const plugin = new ChannelPlugin();
|
|
493
|
+
const core = new AppInsightsCore();
|
|
494
|
+
core.initialize(
|
|
495
|
+
{instrumentationKey: "key"},
|
|
496
|
+
[plugin]
|
|
497
|
+
);
|
|
498
|
+
const appInsights = new ApplicationInsights();
|
|
499
|
+
appInsights.initialize({ instrumentationKey: "ikey"}, core, []);
|
|
500
|
+
const unexpectedError = new Error("some message");
|
|
501
|
+
const throwSpy = this.sandbox.spy(core.logger, "throwInternal");
|
|
502
|
+
const stub = this.sandbox.stub(appInsights, "trackException").throws(unexpectedError);
|
|
503
|
+
|
|
504
|
+
// Act
|
|
505
|
+
appInsights._onerror({message: "any message", url: "any://url", lineNumber: 123, columnNumber: 456, error: unexpectedError});
|
|
506
|
+
|
|
507
|
+
// Test
|
|
508
|
+
const dumpExMsg = throwSpy.args[0][3].exception;
|
|
509
|
+
Assert.ok(dumpExMsg.indexOf("stack: ") != -1);
|
|
510
|
+
Assert.ok(dumpExMsg.indexOf(`message: '${unexpectedError.message}'`) !== -1);
|
|
511
|
+
Assert.ok(dumpExMsg.indexOf("name: 'Error'") !== -1);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
this.testCase({
|
|
516
|
+
name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics",
|
|
517
|
+
test: () => {
|
|
518
|
+
// setup
|
|
519
|
+
const plugin = new ChannelPlugin();
|
|
520
|
+
const core = new AppInsightsCore();
|
|
521
|
+
core.initialize(
|
|
522
|
+
{instrumentationKey: "key"},
|
|
523
|
+
[plugin]
|
|
524
|
+
);
|
|
525
|
+
const appInsights = new ApplicationInsights();
|
|
526
|
+
appInsights.initialize({ instrumentationKey: "key" }, core, []);
|
|
527
|
+
|
|
528
|
+
const throwInternal = this.sandbox.spy(appInsights.core.logger, "throwInternal");
|
|
529
|
+
|
|
530
|
+
this.sandbox.stub(appInsights, "trackException").throws(new CustomTestError("Simulated Error"));
|
|
531
|
+
const expectedErrorName: string = "CustomTestError";
|
|
532
|
+
|
|
533
|
+
appInsights._onerror({message: "some message", url: "some://url", lineNumber: 1234, columnNumber: 5678, error: new Error()});
|
|
534
|
+
|
|
535
|
+
Assert.ok(throwInternal.calledOnce, "throwInternal called once");
|
|
536
|
+
const logMessage: string = throwInternal.getCall(0).args[2];
|
|
537
|
+
Assert.notEqual(-1, logMessage.indexOf(expectedErrorName), "expected: " + logMessage);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
this.testCase({
|
|
542
|
+
name: "OnErrorTests: _onerror adds document URL in case of CORS error",
|
|
543
|
+
test: () => {
|
|
544
|
+
// setup
|
|
545
|
+
const plugin = new ChannelPlugin();
|
|
546
|
+
const core = new AppInsightsCore();
|
|
547
|
+
core.initialize(
|
|
548
|
+
{instrumentationKey: "key"},
|
|
549
|
+
[plugin]
|
|
550
|
+
);
|
|
551
|
+
const appInsights = new ApplicationInsights();
|
|
552
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
553
|
+
const trackSpy = this.sandbox.spy(appInsights.core, "track");
|
|
554
|
+
|
|
555
|
+
// Act
|
|
556
|
+
appInsights._onerror({message: "Script error.", url: "", lineNumber: 0, columnNumber: 0, error: null});
|
|
557
|
+
|
|
558
|
+
// Assert
|
|
559
|
+
Assert.equal(document.URL, trackSpy.args[0][0].baseData.url);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
this.testCase({
|
|
564
|
+
name: "OnErrorTests: _onerror adds document URL in case of no CORS error",
|
|
565
|
+
test: () => {
|
|
566
|
+
// setup
|
|
567
|
+
const plugin = new ChannelPlugin();
|
|
568
|
+
const core = new AppInsightsCore();
|
|
569
|
+
core.initialize(
|
|
570
|
+
{instrumentationKey: "key"},
|
|
571
|
+
[plugin]
|
|
572
|
+
);
|
|
573
|
+
const appInsights = new ApplicationInsights();
|
|
574
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
575
|
+
const trackExceptionSpy = this.sandbox.spy(appInsights, "trackException");
|
|
576
|
+
|
|
577
|
+
// Act
|
|
578
|
+
// Last arg is not an error/null which will be treated as not CORS issue
|
|
579
|
+
appInsights._onerror({message: "Script error.", url: "", lineNumber: 0, columnNumber: 0, error: new Object() as any});
|
|
580
|
+
|
|
581
|
+
// Assert
|
|
582
|
+
// properties are passed as a 3rd parameter
|
|
583
|
+
Assert.equal(document.URL, trackExceptionSpy.args[0][1].url);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
this.testCase({
|
|
588
|
+
name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics",
|
|
589
|
+
test: () => {
|
|
590
|
+
// setup
|
|
591
|
+
const plugin = new ChannelPlugin();
|
|
592
|
+
const core = new AppInsightsCore();
|
|
593
|
+
core.initialize(
|
|
594
|
+
{instrumentationKey: "key"},
|
|
595
|
+
[plugin]
|
|
596
|
+
);
|
|
597
|
+
const appInsights = new ApplicationInsights();
|
|
598
|
+
appInsights.initialize({ instrumentationKey: "key" }, core, []);
|
|
599
|
+
|
|
600
|
+
const throwInternal = this.sandbox.spy(appInsights.core.logger, "throwInternal");
|
|
601
|
+
|
|
602
|
+
// Internal code does call this anymore!
|
|
603
|
+
const expectedErrorName: string = "test error";
|
|
604
|
+
|
|
605
|
+
let theError = new Error();
|
|
606
|
+
theError.name = expectedErrorName;
|
|
607
|
+
this.sandbox.stub(appInsights, "trackException").throws(theError);
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
appInsights._onerror({message: "some message", url: "some://url", lineNumber: 1234, columnNumber: 5678, error: "the error message"});
|
|
611
|
+
|
|
612
|
+
Assert.ok(throwInternal.calledOnce, "throwInternal called once");
|
|
613
|
+
const logMessage: string = throwInternal.getCall(0).args[2];
|
|
614
|
+
Assert.notEqual(-1, logMessage.indexOf(expectedErrorName), "logMessage: " + logMessage);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
this.testCaseAsync({
|
|
620
|
+
name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics",
|
|
621
|
+
stepDelay: 1,
|
|
622
|
+
useFakeTimers: true,
|
|
623
|
+
steps: [() => {
|
|
624
|
+
// setup
|
|
625
|
+
const sender: Sender = new Sender();
|
|
626
|
+
const core = new AppInsightsCore();
|
|
627
|
+
core.initialize(
|
|
628
|
+
{
|
|
629
|
+
instrumentationKey: "key",
|
|
630
|
+
extensionConfig: {
|
|
631
|
+
[sender.identifier]: {
|
|
632
|
+
enableSessionStorageBuffer: false,
|
|
633
|
+
maxBatchInterval: 1
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
},
|
|
637
|
+
[sender]
|
|
638
|
+
);
|
|
639
|
+
const appInsights = new ApplicationInsights();
|
|
640
|
+
appInsights.initialize({ instrumentationKey: "key" }, core, []);
|
|
641
|
+
appInsights.addTelemetryInitializer((item: ITelemetryItem) => {
|
|
642
|
+
Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format");
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal");
|
|
646
|
+
sender._sender = (payload:string[], isAsync:boolean) => {
|
|
647
|
+
sender._onSuccess(payload, payload.length);
|
|
648
|
+
};
|
|
649
|
+
this.sandbox.spy()
|
|
650
|
+
this.trackSpy = this.sandbox.spy(sender, "_onSuccess");
|
|
651
|
+
|
|
652
|
+
this.exceptionHelper.capture(appInsights);
|
|
653
|
+
|
|
654
|
+
this.causeException(() => {
|
|
655
|
+
this.exceptionHelper.throwRuntimeException(AITestClass.orgSetTimeout);
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
Assert.ok(!this.trackSpy.calledOnce, "track not called yet");
|
|
659
|
+
Assert.ok(!this.throwInternalSpy.called, "No internal errors");
|
|
660
|
+
}].concat(this.waitForException(1))
|
|
661
|
+
.concat(() => {
|
|
662
|
+
|
|
663
|
+
let isLocal = window.location.protocol === "file:";
|
|
664
|
+
let exp = this.trackSpy.args[0];
|
|
665
|
+
const payloadStr: string[] = this.getPayloadMessages(this.trackSpy);
|
|
666
|
+
if (payloadStr.length > 0) {
|
|
667
|
+
const payload = JSON.parse(payloadStr[0]);
|
|
668
|
+
const data = payload.data;
|
|
669
|
+
Assert.ok(data, "Has Data");
|
|
670
|
+
if (data) {
|
|
671
|
+
Assert.ok(data.baseData, "Has BaseData");
|
|
672
|
+
let baseData = data.baseData;
|
|
673
|
+
if (baseData) {
|
|
674
|
+
const ex = baseData.exceptions[0];
|
|
675
|
+
if (isLocal) {
|
|
676
|
+
Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]");
|
|
677
|
+
Assert.equal("String", ex.typeName, "Got the correct typename [" + ex.typeName + "]");
|
|
678
|
+
} else {
|
|
679
|
+
Assert.ok(ex.message.indexOf("ug is not a function") !== -1, "Make sure the error message is present [" + ex.message + "]");
|
|
680
|
+
Assert.equal("TypeError", ex.typeName, "Got the correct typename [" + ex.typeName + "]");
|
|
681
|
+
Assert.ok(baseData.properties["columnNumber"], "has column number");
|
|
682
|
+
Assert.ok(baseData.properties["lineNumber"], "has Line number");
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
Assert.ok(ex.stack.length > 0, "Has stack");
|
|
686
|
+
Assert.ok(ex.parsedStack, "Stack was parsed");
|
|
687
|
+
Assert.ok(ex.hasFullStack, "Stack has been decoded");
|
|
688
|
+
Assert.ok(baseData.properties["url"], "has Url");
|
|
689
|
+
Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source");
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
})
|
|
694
|
+
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
this.testCaseAsync({
|
|
698
|
+
name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a text exception",
|
|
699
|
+
stepDelay: 1,
|
|
700
|
+
useFakeTimers: true,
|
|
701
|
+
steps: [() => {
|
|
702
|
+
// setup
|
|
703
|
+
const sender: Sender = new Sender();
|
|
704
|
+
const core = new AppInsightsCore();
|
|
705
|
+
core.initialize(
|
|
706
|
+
{
|
|
707
|
+
instrumentationKey: "key",
|
|
708
|
+
extensionConfig: {
|
|
709
|
+
[sender.identifier]: {
|
|
710
|
+
enableSessionStorageBuffer: false,
|
|
711
|
+
maxBatchInterval: 1
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
[sender]
|
|
716
|
+
);
|
|
717
|
+
const appInsights = new ApplicationInsights();
|
|
718
|
+
appInsights.initialize({ instrumentationKey: "key" }, core, []);
|
|
719
|
+
appInsights.addTelemetryInitializer((item: ITelemetryItem) => {
|
|
720
|
+
Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format");
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal");
|
|
724
|
+
sender._sender = (payload:string[], isAsync:boolean) => {
|
|
725
|
+
sender._onSuccess(payload, payload.length);
|
|
726
|
+
};
|
|
727
|
+
this.sandbox.spy()
|
|
728
|
+
this.trackSpy = this.sandbox.spy(sender, "_onSuccess");
|
|
729
|
+
|
|
730
|
+
this.exceptionHelper.capture(appInsights);
|
|
731
|
+
this.causeException(() => {
|
|
732
|
+
this.exceptionHelper.throw("Test Text Error!");
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
Assert.ok(!this.trackSpy.calledOnce, "track not called yet");
|
|
736
|
+
Assert.ok(!this.throwInternalSpy.called, "No internal errors");
|
|
737
|
+
}].concat(this.waitForException(1))
|
|
738
|
+
.concat(() => {
|
|
739
|
+
|
|
740
|
+
let exp = this.trackSpy.args[0];
|
|
741
|
+
const payloadStr: string[] = this.getPayloadMessages(this.trackSpy);
|
|
742
|
+
if (payloadStr.length > 0) {
|
|
743
|
+
const payload = JSON.parse(payloadStr[0]);
|
|
744
|
+
const data = payload.data;
|
|
745
|
+
Assert.ok(data, "Has Data");
|
|
746
|
+
if (data) {
|
|
747
|
+
Assert.ok(data.baseData, "Has BaseData");
|
|
748
|
+
let baseData = data.baseData;
|
|
749
|
+
if (baseData) {
|
|
750
|
+
const ex = baseData.exceptions[0];
|
|
751
|
+
Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]");
|
|
752
|
+
Assert.ok(baseData.properties["columnNumber"], "has column number");
|
|
753
|
+
Assert.ok(baseData.properties["lineNumber"], "has Line number");
|
|
754
|
+
Assert.equal("String", ex.typeName, "Got the correct typename");
|
|
755
|
+
Assert.ok(ex.stack.length > 0, "Has stack");
|
|
756
|
+
Assert.ok(ex.parsedStack, "Stack was parsed");
|
|
757
|
+
Assert.ok(ex.hasFullStack, "Stack has been decoded");
|
|
758
|
+
Assert.ok(baseData.properties["url"], "has Url");
|
|
759
|
+
Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source");
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
})
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
this.testCaseAsync({
|
|
767
|
+
name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a custom direct exception",
|
|
768
|
+
stepDelay: 1,
|
|
769
|
+
useFakeTimers: true,
|
|
770
|
+
steps: [() => {
|
|
771
|
+
// setup
|
|
772
|
+
const sender: Sender = new Sender();
|
|
773
|
+
const core = new AppInsightsCore();
|
|
774
|
+
core.initialize(
|
|
775
|
+
{
|
|
776
|
+
instrumentationKey: "key",
|
|
777
|
+
extensionConfig: {
|
|
778
|
+
[sender.identifier]: {
|
|
779
|
+
enableSessionStorageBuffer: false,
|
|
780
|
+
maxBatchInterval: 1
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
},
|
|
784
|
+
[sender]
|
|
785
|
+
);
|
|
786
|
+
const appInsights = new ApplicationInsights();
|
|
787
|
+
appInsights.initialize({ instrumentationKey: "key" }, core, []);
|
|
788
|
+
appInsights.addTelemetryInitializer((item: ITelemetryItem) => {
|
|
789
|
+
Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format");
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal");
|
|
793
|
+
sender._sender = (payload:string[], isAsync:boolean) => {
|
|
794
|
+
sender._onSuccess(payload, payload.length);
|
|
795
|
+
};
|
|
796
|
+
this.sandbox.spy()
|
|
797
|
+
this.trackSpy = this.sandbox.spy(sender, "_onSuccess");
|
|
798
|
+
|
|
799
|
+
this.exceptionHelper.capture(appInsights);
|
|
800
|
+
this.causeException(() => {
|
|
801
|
+
this.exceptionHelper.throw(new CustomTestError("Test Text Error!"));
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
Assert.ok(!this.trackSpy.calledOnce, "track not called yet");
|
|
805
|
+
Assert.ok(!this.throwInternalSpy.called, "No internal errors");
|
|
806
|
+
}].concat(this.waitForException(1))
|
|
807
|
+
.concat(() => {
|
|
808
|
+
|
|
809
|
+
let isLocal = window.location.protocol === "file:";
|
|
810
|
+
let exp = this.trackSpy.args[0];
|
|
811
|
+
const payloadStr: string[] = this.getPayloadMessages(this.trackSpy);
|
|
812
|
+
if (payloadStr.length > 0) {
|
|
813
|
+
const payload = JSON.parse(payloadStr[0]);
|
|
814
|
+
const data = payload.data;
|
|
815
|
+
Assert.ok(data, "Has Data");
|
|
816
|
+
if (data) {
|
|
817
|
+
Assert.ok(data.baseData, "Has BaseData");
|
|
818
|
+
let baseData = data.baseData;
|
|
819
|
+
if (baseData) {
|
|
820
|
+
const ex = baseData.exceptions[0];
|
|
821
|
+
if (isLocal) {
|
|
822
|
+
Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]");
|
|
823
|
+
Assert.equal("String", ex.typeName, "Got the correct typename");
|
|
824
|
+
} else {
|
|
825
|
+
Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]");
|
|
826
|
+
Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]");
|
|
827
|
+
Assert.equal("CustomTestError", ex.typeName, "Got the correct typename");
|
|
828
|
+
Assert.ok(baseData.properties["columnNumber"], "has column number");
|
|
829
|
+
Assert.ok(baseData.properties["lineNumber"], "has Line number");
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
Assert.ok(ex.stack.length > 0, "Has stack");
|
|
833
|
+
Assert.ok(ex.parsedStack, "Stack was parsed");
|
|
834
|
+
Assert.ok(ex.hasFullStack, "Stack has been decoded");
|
|
835
|
+
Assert.ok(baseData.properties["url"], "has Url");
|
|
836
|
+
Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source");
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
})
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
this.testCaseAsync({
|
|
844
|
+
name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a strict custom direct exception",
|
|
845
|
+
stepDelay: 1,
|
|
846
|
+
useFakeTimers: true,
|
|
847
|
+
steps: [() => {
|
|
848
|
+
// setup
|
|
849
|
+
const sender: Sender = new Sender();
|
|
850
|
+
const core = new AppInsightsCore();
|
|
851
|
+
core.initialize(
|
|
852
|
+
{
|
|
853
|
+
instrumentationKey: "key",
|
|
854
|
+
extensionConfig: {
|
|
855
|
+
[sender.identifier]: {
|
|
856
|
+
enableSessionStorageBuffer: false,
|
|
857
|
+
maxBatchInterval: 1
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
},
|
|
861
|
+
[sender]
|
|
862
|
+
);
|
|
863
|
+
const appInsights = new ApplicationInsights();
|
|
864
|
+
appInsights.initialize({ instrumentationKey: "key" }, core, []);
|
|
865
|
+
appInsights.addTelemetryInitializer((item: ITelemetryItem) => {
|
|
866
|
+
Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format");
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal");
|
|
870
|
+
sender._sender = (payload:string[], isAsync:boolean) => {
|
|
871
|
+
sender._onSuccess(payload, payload.length);
|
|
872
|
+
};
|
|
873
|
+
this.sandbox.spy()
|
|
874
|
+
this.trackSpy = this.sandbox.spy(sender, "_onSuccess");
|
|
875
|
+
|
|
876
|
+
this.exceptionHelper.capture(appInsights);
|
|
877
|
+
this.causeException(() => {
|
|
878
|
+
this.exceptionHelper.throwStrict(new CustomTestError("Test Text Error!"));
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
Assert.ok(!this.trackSpy.calledOnce, "track not called yet");
|
|
882
|
+
Assert.ok(!this.throwInternalSpy.called, "No internal errors");
|
|
883
|
+
}].concat(this.waitForException(1))
|
|
884
|
+
.concat(() => {
|
|
885
|
+
|
|
886
|
+
let isLocal = window.location.protocol === "file:";
|
|
887
|
+
let exp = this.trackSpy.args[0];
|
|
888
|
+
const payloadStr: string[] = this.getPayloadMessages(this.trackSpy);
|
|
889
|
+
if (payloadStr.length > 0) {
|
|
890
|
+
const payload = JSON.parse(payloadStr[0]);
|
|
891
|
+
const data = payload.data;
|
|
892
|
+
Assert.ok(data, "Has Data");
|
|
893
|
+
if (data) {
|
|
894
|
+
Assert.ok(data.baseData, "Has BaseData");
|
|
895
|
+
let baseData = data.baseData;
|
|
896
|
+
if (baseData) {
|
|
897
|
+
const ex = baseData.exceptions[0];
|
|
898
|
+
if (isLocal) {
|
|
899
|
+
Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]");
|
|
900
|
+
Assert.equal("String", ex.typeName, "Got the correct typename");
|
|
901
|
+
} else {
|
|
902
|
+
Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]");
|
|
903
|
+
Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]");
|
|
904
|
+
Assert.equal("CustomTestError", ex.typeName, "Got the correct typename");
|
|
905
|
+
Assert.ok(baseData.properties["columnNumber"], "has column number");
|
|
906
|
+
Assert.ok(baseData.properties["lineNumber"], "has Line number");
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
Assert.ok(ex.stack.length > 0, "Has stack");
|
|
910
|
+
Assert.ok(ex.parsedStack, "Stack was parsed");
|
|
911
|
+
Assert.ok(ex.hasFullStack, "Stack has been decoded");
|
|
912
|
+
Assert.ok(baseData.properties["url"], "has Url");
|
|
913
|
+
Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source");
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
})
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
private throwStrictRuntimeException() {
|
|
922
|
+
"use strict";
|
|
923
|
+
function doThrow() {
|
|
924
|
+
var ug: any = "Hello";
|
|
925
|
+
// This should throw
|
|
926
|
+
ug();
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
doThrow();
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
private addStartStopTrackPageTests() {
|
|
933
|
+
const testValues = {
|
|
934
|
+
name: "name",
|
|
935
|
+
url: "url",
|
|
936
|
+
duration: 200,
|
|
937
|
+
properties: {
|
|
938
|
+
"property1": "5",
|
|
939
|
+
"property2": "10",
|
|
940
|
+
"refUri": "test.com"
|
|
941
|
+
},
|
|
942
|
+
measurements: {
|
|
943
|
+
"measurement": 300
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
this.testCase({
|
|
948
|
+
name: "Timing Tests: Start/StopPageView pass correct duration",
|
|
949
|
+
useFakeTimers: true,
|
|
950
|
+
test: () => {
|
|
951
|
+
// setup
|
|
952
|
+
const plugin = new ChannelPlugin();
|
|
953
|
+
const core = new AppInsightsCore();
|
|
954
|
+
core.initialize(
|
|
955
|
+
{instrumentationKey: "key"},
|
|
956
|
+
[plugin]
|
|
957
|
+
);
|
|
958
|
+
const appInsights = new ApplicationInsights();
|
|
959
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
960
|
+
const spy = this.sandbox.spy(appInsights, "sendPageViewInternal");
|
|
961
|
+
this.clock.tick(1);
|
|
962
|
+
|
|
963
|
+
// act
|
|
964
|
+
appInsights.startTrackPage(testValues.name);
|
|
965
|
+
this.clock.tick(testValues.duration);
|
|
966
|
+
appInsights.stopTrackPage(testValues.name, testValues.url, testValues.properties, testValues.measurements);
|
|
967
|
+
|
|
968
|
+
// verify
|
|
969
|
+
Assert.ok(spy.calledOnce, "stop track page view sent data");
|
|
970
|
+
const actual = spy.args[0][0];
|
|
971
|
+
Assert.equal(testValues.name, actual.name);
|
|
972
|
+
Assert.equal(testValues.url, actual.uri);
|
|
973
|
+
|
|
974
|
+
const actualProperties = actual.properties;
|
|
975
|
+
const actualMeasurements = actual.measurements;
|
|
976
|
+
Assert.equal(testValues.duration, actualProperties.duration, "duration is calculated and sent correctly");
|
|
977
|
+
Assert.equal(testValues.properties.property1, actualProperties.property1);
|
|
978
|
+
Assert.equal(testValues.properties.property2, actualProperties.property2);
|
|
979
|
+
Assert.equal(testValues.properties.refUri, actualProperties.refUri);
|
|
980
|
+
Assert.equal(testValues.measurements.measurement, actualMeasurements.measurement);
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
this.testCase({
|
|
984
|
+
name: "Timing Tests: Start/StopPageView tracks single page view with no parameters",
|
|
985
|
+
useFakeTimers: true,
|
|
986
|
+
test: () => {
|
|
987
|
+
// setup
|
|
988
|
+
const core = new AppInsightsCore();
|
|
989
|
+
this.sandbox.stub(core, "getTransmissionControls");
|
|
990
|
+
const appInsights = new ApplicationInsights();
|
|
991
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
992
|
+
const trackStub = this.sandbox.stub(appInsights.core, "track");
|
|
993
|
+
this.clock.tick(10); // Needed to ensure the duration calculation works
|
|
994
|
+
|
|
995
|
+
// act
|
|
996
|
+
appInsights.startTrackPage();
|
|
997
|
+
this.clock.tick(testValues.duration);
|
|
998
|
+
appInsights.stopTrackPage();
|
|
999
|
+
Assert.ok(trackStub.calledOnce, "single page view tracking stopped");
|
|
1000
|
+
|
|
1001
|
+
// verify
|
|
1002
|
+
const telemetry: ITelemetryItem = trackStub.args[0][0];
|
|
1003
|
+
Assert.equal(window.document.title, telemetry.baseData.name);
|
|
1004
|
+
Assert.equal(testValues.duration, telemetry.baseData.properties.duration);
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
this.testCase({
|
|
1009
|
+
name: "Timing Tests: Multiple Start/StopPageView track single pages view ",
|
|
1010
|
+
useFakeTimers: true,
|
|
1011
|
+
test: () => {
|
|
1012
|
+
// setup
|
|
1013
|
+
const core = new AppInsightsCore();
|
|
1014
|
+
this.sandbox.stub(core, "getTransmissionControls");
|
|
1015
|
+
const appInsights = new ApplicationInsights();
|
|
1016
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
1017
|
+
const trackStub = this.sandbox.stub(appInsights.core, "track");
|
|
1018
|
+
this.clock.tick(10); // Needed to ensure the duration calculation works
|
|
1019
|
+
|
|
1020
|
+
// act
|
|
1021
|
+
appInsights.startTrackPage(testValues.name);
|
|
1022
|
+
this.clock.tick(testValues.duration);
|
|
1023
|
+
|
|
1024
|
+
appInsights.startTrackPage();
|
|
1025
|
+
this.clock.tick(testValues.duration);
|
|
1026
|
+
appInsights.stopTrackPage();
|
|
1027
|
+
Assert.ok(trackStub.calledOnce, "single page view tracking stopped no parameters");
|
|
1028
|
+
|
|
1029
|
+
this.clock.tick(testValues.duration);
|
|
1030
|
+
appInsights.stopTrackPage(testValues.name, testValues.url, testValues.properties);
|
|
1031
|
+
Assert.ok(trackStub.calledTwice, "single page view tracking stopped all parameters");
|
|
1032
|
+
|
|
1033
|
+
// verify
|
|
1034
|
+
// Empty parameters
|
|
1035
|
+
let telemetry: ITelemetryItem = trackStub.args[0][0];
|
|
1036
|
+
Assert.equal(window.document.title, telemetry.baseData.name);
|
|
1037
|
+
Assert.equal(window.document.location.href, telemetry.baseData.uri);
|
|
1038
|
+
|
|
1039
|
+
// // All parameters
|
|
1040
|
+
telemetry = trackStub.args[1][0];
|
|
1041
|
+
Assert.equal(testValues.name, telemetry.baseData.name);
|
|
1042
|
+
Assert.equal(testValues.url, telemetry.baseData.uri);
|
|
1043
|
+
Assert.deepEqual(testValues.properties, telemetry.baseData.properties);
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
|
|
1047
|
+
this.testCase({
|
|
1048
|
+
name: "Timing Tests: Multiple startTrackPage",
|
|
1049
|
+
test:
|
|
1050
|
+
() => {
|
|
1051
|
+
// setup
|
|
1052
|
+
const plugin = new ChannelPlugin();
|
|
1053
|
+
const core = new AppInsightsCore();
|
|
1054
|
+
core.initialize(
|
|
1055
|
+
{instrumentationKey: "key"},
|
|
1056
|
+
[plugin]
|
|
1057
|
+
);
|
|
1058
|
+
const appInsights = new ApplicationInsights();
|
|
1059
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
1060
|
+
const logStub = this.sandbox.stub(core.logger, "throwInternal");
|
|
1061
|
+
core.logger.consoleLoggingLevel = () => 999;
|
|
1062
|
+
|
|
1063
|
+
// act
|
|
1064
|
+
appInsights.startTrackPage();
|
|
1065
|
+
appInsights.startTrackPage();
|
|
1066
|
+
|
|
1067
|
+
// verify
|
|
1068
|
+
Assert.ok(logStub.calledOnce, "calling start twice triggers warning to user");
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
this.testCase({
|
|
1073
|
+
name: "Timing Tests: stopTrackPage called without a corresponding start",
|
|
1074
|
+
test:
|
|
1075
|
+
() => {
|
|
1076
|
+
// setup
|
|
1077
|
+
const plugin = new ChannelPlugin();
|
|
1078
|
+
const core = new AppInsightsCore();
|
|
1079
|
+
core.initialize(
|
|
1080
|
+
{instrumentationKey: "key"},
|
|
1081
|
+
[plugin]
|
|
1082
|
+
);
|
|
1083
|
+
const appInsights = new ApplicationInsights();
|
|
1084
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
1085
|
+
const logStub = this.sandbox.stub(core.logger, "throwInternal");
|
|
1086
|
+
core.logger.consoleLoggingLevel = () => 999;
|
|
1087
|
+
|
|
1088
|
+
// act
|
|
1089
|
+
appInsights.stopTrackPage();
|
|
1090
|
+
|
|
1091
|
+
// verify
|
|
1092
|
+
Assert.ok(logStub.calledOnce, "calling stop without a corresponding start triggers warning to user");
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
private addTrackMetricTests() {
|
|
1098
|
+
this.testCase({
|
|
1099
|
+
name: 'TrackMetricTests: trackMetric batches metrics sent in a hot loop',
|
|
1100
|
+
useFakeTimers: true,
|
|
1101
|
+
test: () => {
|
|
1102
|
+
// Setup
|
|
1103
|
+
const plugin = new ChannelPlugin();
|
|
1104
|
+
const core = new AppInsightsCore();
|
|
1105
|
+
core.initialize(
|
|
1106
|
+
{instrumentationKey: "key"},
|
|
1107
|
+
[plugin]
|
|
1108
|
+
);
|
|
1109
|
+
const appInsights = new ApplicationInsights();
|
|
1110
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, []);
|
|
1111
|
+
const trackStub = this.sandbox.stub(appInsights.core, "track");
|
|
1112
|
+
|
|
1113
|
+
// Act
|
|
1114
|
+
appInsights.trackMetric({name: "test metric", average: 0});
|
|
1115
|
+
this.clock.tick(1);
|
|
1116
|
+
|
|
1117
|
+
// Verify
|
|
1118
|
+
|
|
1119
|
+
Assert.ok(trackStub.calledOnce, "core.track was called once after sending one metric");
|
|
1120
|
+
trackStub.reset();
|
|
1121
|
+
|
|
1122
|
+
// Act
|
|
1123
|
+
for (let i = 0; i < 100; i++) {
|
|
1124
|
+
appInsights.trackMetric({name: "test metric", average: 0});
|
|
1125
|
+
}
|
|
1126
|
+
this.clock.tick(1);
|
|
1127
|
+
|
|
1128
|
+
// Test
|
|
1129
|
+
Assert.equal(100, trackStub.callCount, "core.track was called 100 times for sending 100 metrics");
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
private addTelemetryInitializerTests(): void {
|
|
1135
|
+
this.testCase({
|
|
1136
|
+
name: "TelemetryContext: onBeforeSendTelemetry is called within track() and gets the envelope as an argument",
|
|
1137
|
+
useFakeTimers: true,
|
|
1138
|
+
test: () => {
|
|
1139
|
+
// Setup
|
|
1140
|
+
const plugin = new ChannelPlugin();
|
|
1141
|
+
const core = new AppInsightsCore();
|
|
1142
|
+
const appInsights = new ApplicationInsights();
|
|
1143
|
+
core.initialize(
|
|
1144
|
+
{instrumentationKey: "key"},
|
|
1145
|
+
[plugin, appInsights]
|
|
1146
|
+
);
|
|
1147
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1148
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1149
|
+
|
|
1150
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1151
|
+
const telemetryInitializer = {
|
|
1152
|
+
initializer: (envelope) => { }
|
|
1153
|
+
}
|
|
1154
|
+
const spy = this.sandbox.spy(telemetryInitializer, "initializer");
|
|
1155
|
+
|
|
1156
|
+
// act
|
|
1157
|
+
appInsights.addTelemetryInitializer(telemetryInitializer.initializer);
|
|
1158
|
+
appInsights.trackEvent({name: 'test event'});
|
|
1159
|
+
this.clock.tick(1);
|
|
1160
|
+
|
|
1161
|
+
// verify
|
|
1162
|
+
Assert.ok(spy.calledOnce, 'telemetryInitializer was called');
|
|
1163
|
+
Assert.deepEqual(trackStub.args[0][0], spy.args[0][0], 'expected envelope is used');
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
|
|
1167
|
+
this.testCase({
|
|
1168
|
+
name: "TelemetryContext: onBeforeSendTelemetry changes the envelope props and sender gets them",
|
|
1169
|
+
useFakeTimers: true,
|
|
1170
|
+
test: () => {
|
|
1171
|
+
// Setup
|
|
1172
|
+
const plugin = new ChannelPlugin();
|
|
1173
|
+
const core = new AppInsightsCore();
|
|
1174
|
+
const appInsights = new ApplicationInsights();
|
|
1175
|
+
core.initialize(
|
|
1176
|
+
{instrumentationKey: "key"},
|
|
1177
|
+
[plugin, appInsights]
|
|
1178
|
+
);
|
|
1179
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1180
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1181
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1182
|
+
const nameOverride = "my unique name";
|
|
1183
|
+
const telemetryInitializer = {
|
|
1184
|
+
initializer: (envelope) => {
|
|
1185
|
+
envelope.name = nameOverride;
|
|
1186
|
+
return true;}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// act
|
|
1190
|
+
appInsights.addTelemetryInitializer(telemetryInitializer.initializer);
|
|
1191
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1192
|
+
this.clock.tick(1);
|
|
1193
|
+
|
|
1194
|
+
// verify
|
|
1195
|
+
Assert.ok(trackStub.calledOnce, "channel sender was called");
|
|
1196
|
+
|
|
1197
|
+
const envelope: ITelemetryItem = trackStub.args[0][0];
|
|
1198
|
+
Assert.equal(envelope.name, nameOverride, 'expected envelope is used');
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
|
|
1202
|
+
this.testCase({
|
|
1203
|
+
name: "TelemetryContext: telemetry initializer can modify the contents of an envelope",
|
|
1204
|
+
test: () => {
|
|
1205
|
+
// Setup
|
|
1206
|
+
const plugin = new ChannelPlugin();
|
|
1207
|
+
const core = new AppInsightsCore();
|
|
1208
|
+
const appInsights = new ApplicationInsights();
|
|
1209
|
+
core.initialize(
|
|
1210
|
+
{instrumentationKey: "key"},
|
|
1211
|
+
[plugin, appInsights]
|
|
1212
|
+
);
|
|
1213
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1214
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1215
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1216
|
+
|
|
1217
|
+
const messageOverride = "my unique name";
|
|
1218
|
+
const propOverride = "val1";
|
|
1219
|
+
const telemetryInitializer = {
|
|
1220
|
+
// This illustrates how to use telemetry initializer (onBeforeSendTelemetry)
|
|
1221
|
+
// to access/ modify the contents of an envelope.
|
|
1222
|
+
initializer: (envelope) => {
|
|
1223
|
+
if (envelope.baseType ===
|
|
1224
|
+
Trace.dataType) {
|
|
1225
|
+
const telemetryItem = envelope.baseData;
|
|
1226
|
+
telemetryItem.message = messageOverride;
|
|
1227
|
+
telemetryItem.properties = telemetryItem.properties || {};
|
|
1228
|
+
telemetryItem.properties["prop1"] = propOverride;
|
|
1229
|
+
return true;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
appInsights.addTelemetryInitializer(telemetryInitializer.initializer);
|
|
1235
|
+
|
|
1236
|
+
// act
|
|
1237
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1238
|
+
|
|
1239
|
+
// verify
|
|
1240
|
+
Assert.ok(trackStub.calledOnce, "sender should be called");
|
|
1241
|
+
|
|
1242
|
+
const envelope: ITelemetryItem = trackStub.args[0][0];
|
|
1243
|
+
Assert.equal(messageOverride, envelope.baseData.message);
|
|
1244
|
+
Assert.equal(propOverride, envelope.baseData.properties["prop1"]);
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
|
|
1248
|
+
this.testCase({
|
|
1249
|
+
name: "TelemetryContext: all added telemetry initializers get invoked",
|
|
1250
|
+
test: () => {
|
|
1251
|
+
// Setup
|
|
1252
|
+
const plugin = new ChannelPlugin();
|
|
1253
|
+
const core = new AppInsightsCore();
|
|
1254
|
+
const appInsights = new ApplicationInsights();
|
|
1255
|
+
core.initialize(
|
|
1256
|
+
{instrumentationKey: "key"},
|
|
1257
|
+
[plugin, appInsights]
|
|
1258
|
+
);
|
|
1259
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1260
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1261
|
+
const initializer1 = { init: () => { } };
|
|
1262
|
+
const initializer2 = { init: () => { } };
|
|
1263
|
+
const spy1 = this.sandbox.spy(initializer1, "init");
|
|
1264
|
+
const spy2 = this.sandbox.spy(initializer2, "init");
|
|
1265
|
+
|
|
1266
|
+
// act
|
|
1267
|
+
appInsights.addTelemetryInitializer(initializer1.init);
|
|
1268
|
+
appInsights.addTelemetryInitializer(initializer2.init);
|
|
1269
|
+
|
|
1270
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1271
|
+
|
|
1272
|
+
// verify
|
|
1273
|
+
Assert.ok(spy1.calledOnce);
|
|
1274
|
+
Assert.ok(spy2.calledOnce);
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1278
|
+
this.testCase({
|
|
1279
|
+
name: "TelemetryContext: all added telemetry initializers get invoked for trackException",
|
|
1280
|
+
test: () => {
|
|
1281
|
+
// Setup
|
|
1282
|
+
const plugin = new ChannelPlugin();
|
|
1283
|
+
const core = new AppInsightsCore();
|
|
1284
|
+
const appInsights = new ApplicationInsights();
|
|
1285
|
+
core.initialize(
|
|
1286
|
+
{instrumentationKey: "key"},
|
|
1287
|
+
[plugin, appInsights]
|
|
1288
|
+
);
|
|
1289
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1290
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1291
|
+
const initializer1 = { init: (item: ITelemetryItem) => {
|
|
1292
|
+
if (item.data !== undefined) {
|
|
1293
|
+
item.data.init1 = true;
|
|
1294
|
+
}
|
|
1295
|
+
} };
|
|
1296
|
+
const initializer2 = { init: (item: ITelemetryItem) => {
|
|
1297
|
+
if (item.data !== undefined) {
|
|
1298
|
+
item.data.init2 = true;
|
|
1299
|
+
}
|
|
1300
|
+
} };
|
|
1301
|
+
const spy1 = this.sandbox.spy(initializer1, "init");
|
|
1302
|
+
const spy2 = this.sandbox.spy(initializer2, "init");
|
|
1303
|
+
|
|
1304
|
+
// act
|
|
1305
|
+
appInsights.addTelemetryInitializer(initializer1.init);
|
|
1306
|
+
appInsights.addTelemetryInitializer(initializer2.init);
|
|
1307
|
+
|
|
1308
|
+
// Act
|
|
1309
|
+
appInsights._onerror({message: "msg", url: "some://url", lineNumber: 123, columnNumber: 456, error: new Error()});
|
|
1310
|
+
|
|
1311
|
+
// verify
|
|
1312
|
+
Assert.ok(spy1.calledOnce);
|
|
1313
|
+
Assert.ok(spy2.calledOnce);
|
|
1314
|
+
}
|
|
1315
|
+
});
|
|
1316
|
+
|
|
1317
|
+
this.testCase({
|
|
1318
|
+
name: "TelemetryContext: all added telemetry initializers get invoked for _onError calls",
|
|
1319
|
+
test: () => {
|
|
1320
|
+
// Setup
|
|
1321
|
+
const plugin = new ChannelPlugin();
|
|
1322
|
+
const core = new AppInsightsCore();
|
|
1323
|
+
const appInsights = new ApplicationInsights();
|
|
1324
|
+
core.initialize(
|
|
1325
|
+
{instrumentationKey: "key"},
|
|
1326
|
+
[plugin, appInsights]
|
|
1327
|
+
);
|
|
1328
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1329
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1330
|
+
const initializer1 = { init: () => { } };
|
|
1331
|
+
const initializer2 = { init: () => { } };
|
|
1332
|
+
const spy1 = this.sandbox.spy(initializer1, "init");
|
|
1333
|
+
const spy2 = this.sandbox.spy(initializer2, "init");
|
|
1334
|
+
|
|
1335
|
+
// act
|
|
1336
|
+
appInsights.addTelemetryInitializer(initializer1.init);
|
|
1337
|
+
appInsights.addTelemetryInitializer(initializer2.init);
|
|
1338
|
+
|
|
1339
|
+
appInsights.trackException({exception: new Error(), severityLevel: SeverityLevel.Critical});
|
|
1340
|
+
|
|
1341
|
+
// verify
|
|
1342
|
+
Assert.ok(spy1.calledOnce);
|
|
1343
|
+
Assert.ok(spy2.calledOnce);
|
|
1344
|
+
}
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1347
|
+
this.testCase({
|
|
1348
|
+
name: "TelemetryContext: telemetry initializer - returning false means don't send an item",
|
|
1349
|
+
test: () => {
|
|
1350
|
+
// Setup
|
|
1351
|
+
const plugin = new ChannelPlugin();
|
|
1352
|
+
const core = new AppInsightsCore();
|
|
1353
|
+
const appInsights = new ApplicationInsights();
|
|
1354
|
+
core.initialize(
|
|
1355
|
+
{instrumentationKey: "key"},
|
|
1356
|
+
[plugin, appInsights]
|
|
1357
|
+
);
|
|
1358
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1359
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1360
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1361
|
+
|
|
1362
|
+
// act
|
|
1363
|
+
appInsights.addTelemetryInitializer(() => false);
|
|
1364
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1365
|
+
|
|
1366
|
+
// verify
|
|
1367
|
+
Assert.ok(trackStub.notCalled);
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
|
|
1371
|
+
this.testCase({
|
|
1372
|
+
name: "TelemetryContext: telemetry initializer - returning void means do send an item (back compact with older telemetry initializers)",
|
|
1373
|
+
test: () => {
|
|
1374
|
+
// Setup
|
|
1375
|
+
const plugin = new ChannelPlugin();
|
|
1376
|
+
const core = new AppInsightsCore();
|
|
1377
|
+
const appInsights = new ApplicationInsights();
|
|
1378
|
+
core.initialize(
|
|
1379
|
+
{instrumentationKey: "key"},
|
|
1380
|
+
[plugin, appInsights]
|
|
1381
|
+
);
|
|
1382
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1383
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1384
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1385
|
+
|
|
1386
|
+
// act
|
|
1387
|
+
appInsights.addTelemetryInitializer(() => { return; });
|
|
1388
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1389
|
+
|
|
1390
|
+
// verify
|
|
1391
|
+
Assert.ok(trackStub.calledOnce); // TODO: use sender
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
|
|
1395
|
+
this.testCase({
|
|
1396
|
+
name: "TelemetryContext: telemetry initializer - returning true means do send an item",
|
|
1397
|
+
test: () => {
|
|
1398
|
+
// Setup
|
|
1399
|
+
const plugin = new ChannelPlugin();
|
|
1400
|
+
const core = new AppInsightsCore();
|
|
1401
|
+
const appInsights = new ApplicationInsights();
|
|
1402
|
+
core.initialize(
|
|
1403
|
+
{instrumentationKey: "key"},
|
|
1404
|
+
[plugin, appInsights]
|
|
1405
|
+
);
|
|
1406
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1407
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1408
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1409
|
+
|
|
1410
|
+
// act
|
|
1411
|
+
appInsights.addTelemetryInitializer(() => true);
|
|
1412
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1413
|
+
|
|
1414
|
+
// verify
|
|
1415
|
+
Assert.ok(trackStub.calledOnce);
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
this.testCase({
|
|
1420
|
+
name: "TelemetryContext: telemetry initializer - if one of initializers returns false than item is not sent",
|
|
1421
|
+
test: () => {
|
|
1422
|
+
// Setup
|
|
1423
|
+
const plugin = new ChannelPlugin();
|
|
1424
|
+
const core = new AppInsightsCore();
|
|
1425
|
+
const appInsights = new ApplicationInsights();
|
|
1426
|
+
core.initialize(
|
|
1427
|
+
{instrumentationKey: "key"},
|
|
1428
|
+
[plugin, appInsights]
|
|
1429
|
+
);
|
|
1430
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1431
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1432
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1433
|
+
|
|
1434
|
+
// act
|
|
1435
|
+
appInsights.addTelemetryInitializer(() => true);
|
|
1436
|
+
appInsights.addTelemetryInitializer(() => false);
|
|
1437
|
+
|
|
1438
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1439
|
+
|
|
1440
|
+
// verify
|
|
1441
|
+
Assert.ok(trackStub.notCalled);
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
|
+
this.testCase({
|
|
1446
|
+
name: "TelemetryContext: telemetry initializer - if one of initializers returns false (any order) than item is not sent",
|
|
1447
|
+
test: () => {
|
|
1448
|
+
// Setup
|
|
1449
|
+
const plugin = new ChannelPlugin();
|
|
1450
|
+
const core = new AppInsightsCore();
|
|
1451
|
+
const appInsights = new ApplicationInsights();
|
|
1452
|
+
core.initialize(
|
|
1453
|
+
{instrumentationKey: "key"},
|
|
1454
|
+
[plugin, appInsights]
|
|
1455
|
+
);
|
|
1456
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1457
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1458
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1459
|
+
|
|
1460
|
+
// act
|
|
1461
|
+
appInsights.addTelemetryInitializer(() => false);
|
|
1462
|
+
appInsights.addTelemetryInitializer(() => true);
|
|
1463
|
+
|
|
1464
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1465
|
+
|
|
1466
|
+
// verify
|
|
1467
|
+
Assert.ok(trackStub.notCalled);
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1470
|
+
|
|
1471
|
+
this.testCase({
|
|
1472
|
+
name: "TelemetryContext: telemetry initializer - returning not boolean/undefined/null means do send an item (back compat with older telemetry initializers)",
|
|
1473
|
+
test: () => {
|
|
1474
|
+
// Setup
|
|
1475
|
+
const plugin = new ChannelPlugin();
|
|
1476
|
+
const core = new AppInsightsCore();
|
|
1477
|
+
const appInsights = new ApplicationInsights();
|
|
1478
|
+
core.initialize(
|
|
1479
|
+
{instrumentationKey: "key"},
|
|
1480
|
+
[plugin, appInsights]
|
|
1481
|
+
);
|
|
1482
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1483
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1484
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1485
|
+
|
|
1486
|
+
// act
|
|
1487
|
+
appInsights.addTelemetryInitializer((() => "asdf") as any);
|
|
1488
|
+
appInsights.addTelemetryInitializer(() => null);
|
|
1489
|
+
appInsights.addTelemetryInitializer(() => undefined);
|
|
1490
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1491
|
+
|
|
1492
|
+
// verify
|
|
1493
|
+
Assert.ok(trackStub.calledOnce); // TODO: use sender
|
|
1494
|
+
}
|
|
1495
|
+
});
|
|
1496
|
+
|
|
1497
|
+
this.testCase({
|
|
1498
|
+
name: "TelemetryContext: telemetry initializer - if one initializer fails then error logged and is still sent",
|
|
1499
|
+
test: () => {
|
|
1500
|
+
// Setup
|
|
1501
|
+
const plugin = new ChannelPlugin();
|
|
1502
|
+
const core = new AppInsightsCore();
|
|
1503
|
+
const appInsights = new ApplicationInsights();
|
|
1504
|
+
core.initialize(
|
|
1505
|
+
{instrumentationKey: "key"},
|
|
1506
|
+
[plugin, appInsights]
|
|
1507
|
+
);
|
|
1508
|
+
appInsights.initialize({ "instrumentationKey": "ikey" }, core, [plugin, appInsights]);
|
|
1509
|
+
plugin.initialize({instrumentationKey: 'ikey'}, core, [plugin, appInsights]);
|
|
1510
|
+
const trackStub = this.sandbox.spy(appInsights.core.getTransmissionControls()[0][0], 'processTelemetry');
|
|
1511
|
+
const logStub = this.sandbox.spy(appInsights.core.logger, "throwInternal")
|
|
1512
|
+
// act
|
|
1513
|
+
appInsights.addTelemetryInitializer(() => { throw new Error("Test error IGNORE"); });
|
|
1514
|
+
appInsights.addTelemetryInitializer(() => { });
|
|
1515
|
+
appInsights.trackTrace({message: 'test message'});
|
|
1516
|
+
|
|
1517
|
+
// verify
|
|
1518
|
+
Assert.ok(trackStub.calledOnce);
|
|
1519
|
+
Assert.ok(logStub.calledOnce);
|
|
1520
|
+
|
|
1521
|
+
}
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
private getFirstResult(action: string, trackStub: SinonStub, skipSessionState?: boolean): ITelemetryItem {
|
|
1526
|
+
const index: number = skipSessionState ? 1 : 0;
|
|
1527
|
+
|
|
1528
|
+
Assert.ok(trackStub.args && trackStub.args[index] && trackStub.args[index][0], "track was called for: " + action);
|
|
1529
|
+
return trackStub.args[index][0] as ITelemetryItem;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
private checkNoInternalErrors() {
|
|
1533
|
+
if (this.throwInternalSpy) {
|
|
1534
|
+
Assert.ok(this.throwInternalSpy.notCalled, "Check no internal errors");
|
|
1535
|
+
if (this.throwInternalSpy.called) {
|
|
1536
|
+
Assert.ok(false, JSON.stringify(this.throwInternalSpy.args[0]));
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
private waitForException: any = (expectedCount:number, action: string = "", includeInit:boolean = false) => [
|
|
1542
|
+
() => {
|
|
1543
|
+
const message = "polling: " + new Date().toISOString() + " " + action;
|
|
1544
|
+
Assert.ok(true, message);
|
|
1545
|
+
console.log(message);
|
|
1546
|
+
this.checkNoInternalErrors();
|
|
1547
|
+
this.clock.tick(500);
|
|
1548
|
+
},
|
|
1549
|
+
(PollingAssert.createPollingAssert(() => {
|
|
1550
|
+
this.checkNoInternalErrors();
|
|
1551
|
+
let argCount = 0;
|
|
1552
|
+
if (this.trackSpy.called) {
|
|
1553
|
+
this.trackSpy.args.forEach(call => {
|
|
1554
|
+
argCount += call.length;
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
Assert.ok(true, "* [" + argCount + " of " + expectedCount + "] checking spy " + new Date().toISOString());
|
|
1559
|
+
|
|
1560
|
+
try {
|
|
1561
|
+
if (argCount >= expectedCount) {
|
|
1562
|
+
const payload = JSON.parse(this.trackSpy.args[0][0]);
|
|
1563
|
+
const baseType = payload.data.baseType;
|
|
1564
|
+
// call the appropriate Validate depending on the baseType
|
|
1565
|
+
switch (baseType) {
|
|
1566
|
+
case Event.dataType:
|
|
1567
|
+
return EventValidator.EventValidator.Validate(payload, baseType);
|
|
1568
|
+
case Trace.dataType:
|
|
1569
|
+
return TraceValidator.TraceValidator.Validate(payload, baseType);
|
|
1570
|
+
case Exception.dataType:
|
|
1571
|
+
return ExceptionValidator.ExceptionValidator.Validate(payload, baseType);
|
|
1572
|
+
case Metric.dataType:
|
|
1573
|
+
return MetricValidator.MetricValidator.Validate(payload, baseType);
|
|
1574
|
+
case PageView.dataType:
|
|
1575
|
+
return PageViewValidator.PageViewValidator.Validate(payload, baseType);
|
|
1576
|
+
case PageViewPerformance.dataType:
|
|
1577
|
+
return PageViewPerformanceValidator.PageViewPerformanceValidator.Validate(payload, baseType);
|
|
1578
|
+
case RemoteDependencyData.dataType:
|
|
1579
|
+
return RemoteDepdencyValidator.RemoteDepdencyValidator.Validate(payload, baseType);
|
|
1580
|
+
|
|
1581
|
+
default:
|
|
1582
|
+
return EventValidator.EventValidator.Validate(payload, baseType);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
} finally {
|
|
1586
|
+
this.clock.tick(500);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
return false;
|
|
1590
|
+
}, "sender succeeded", 10, 1000))
|
|
1591
|
+
];
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
class ChannelPlugin implements IPlugin {
|
|
1595
|
+
|
|
1596
|
+
public isFlushInvoked = false;
|
|
1597
|
+
public isTearDownInvoked = false;
|
|
1598
|
+
public isResumeInvoked = false;
|
|
1599
|
+
public isPauseInvoked = false;
|
|
1600
|
+
|
|
1601
|
+
public identifier = "Sender";
|
|
1602
|
+
|
|
1603
|
+
public priority: number = 1001;
|
|
1604
|
+
|
|
1605
|
+
constructor() {
|
|
1606
|
+
this.processTelemetry = this._processTelemetry.bind(this);
|
|
1607
|
+
}
|
|
1608
|
+
public pause(): void {
|
|
1609
|
+
this.isPauseInvoked = true;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
public resume(): void {
|
|
1613
|
+
this.isResumeInvoked = true;
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
public teardown(): void {
|
|
1617
|
+
this.isTearDownInvoked = true;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
flush(async?: boolean, callBack?: () => void): void {
|
|
1621
|
+
this.isFlushInvoked = true;
|
|
1622
|
+
if (callBack) {
|
|
1623
|
+
callBack();
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
public processTelemetry(env: ITelemetryItem) {}
|
|
1628
|
+
|
|
1629
|
+
setNextPlugin(next: any) {
|
|
1630
|
+
// no next setup
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
public initialize = (config: IConfiguration, core: IAppInsightsCore, plugin: IPlugin[]) => {
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
private _processTelemetry(env: ITelemetryItem) {
|
|
1637
|
+
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
class CustomTestError extends Error {
|
|
1642
|
+
constructor(message = "") {
|
|
1643
|
+
super(message);
|
|
1644
|
+
this.name = "CustomTestError";
|
|
1645
|
+
this.message = message + " -- test error.";
|
|
1646
|
+
}
|
|
1647
|
+
}
|