@microsoft/applicationinsights-core-js 2.7.2-nightly.2111-09 → 2.7.2-nightly.2111-14
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/browser/applicationinsights-core-js.integrity.json +9 -9
- package/browser/applicationinsights-core-js.js +63 -2
- package/browser/applicationinsights-core-js.js.map +1 -1
- package/browser/applicationinsights-core-js.min.js +2 -2
- package/browser/applicationinsights-core-js.min.js.map +1 -1
- package/dist/applicationinsights-core-js.api.json +315 -0
- package/dist/applicationinsights-core-js.api.md +25 -0
- package/dist/applicationinsights-core-js.d.ts +20 -1
- package/dist/applicationinsights-core-js.js +63 -2
- package/dist/applicationinsights-core-js.js.map +1 -1
- package/dist/applicationinsights-core-js.min.js +2 -2
- package/dist/applicationinsights-core-js.min.js.map +1 -1
- package/dist/applicationinsights-core-js.rollup.d.ts +20 -1
- package/dist-esm/JavaScriptSDK/AppInsightsCore.js +1 -1
- package/dist-esm/JavaScriptSDK/BaseCore.js +5 -1
- package/dist-esm/JavaScriptSDK/BaseCore.js.map +1 -1
- package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +1 -1
- package/dist-esm/JavaScriptSDK/ChannelController.js +1 -1
- package/dist-esm/JavaScriptSDK/Constants.js +1 -1
- package/dist-esm/JavaScriptSDK/CookieMgr.js +1 -1
- package/dist-esm/JavaScriptSDK/CoreUtils.js +1 -1
- package/dist-esm/JavaScriptSDK/DbgExtensionUtils.js +47 -0
- package/dist-esm/JavaScriptSDK/DbgExtensionUtils.js.map +1 -0
- package/dist-esm/JavaScriptSDK/DiagnosticLogger.js +20 -2
- package/dist-esm/JavaScriptSDK/DiagnosticLogger.js.map +1 -1
- package/dist-esm/JavaScriptSDK/EnvUtils.js +1 -1
- package/dist-esm/JavaScriptSDK/HelperFuncs.js +1 -1
- package/dist-esm/JavaScriptSDK/InstrumentHooks.js +1 -1
- package/dist-esm/JavaScriptSDK/NotificationManager.js +1 -1
- package/dist-esm/JavaScriptSDK/PerfManager.js +1 -1
- package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js +1 -1
- package/dist-esm/JavaScriptSDK/RandomHelper.js +1 -1
- package/dist-esm/JavaScriptSDK/TelemetryHelpers.js +1 -1
- package/dist-esm/JavaScriptSDK/TelemetryPluginChain.js +1 -1
- package/dist-esm/JavaScriptSDK.Enums/EventsDiscardedReason.js +1 -1
- package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +1 -1
- package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js +8 -0
- package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js.map +1 -0
- package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +3 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js.map +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -1
- package/dist-esm/applicationinsights-core-js.js +2 -1
- package/dist-esm/applicationinsights-core-js.js.map +1 -1
- package/package.json +1 -1
- package/src/JavaScriptSDK/BaseCore.ts +5 -0
- package/src/JavaScriptSDK/DbgExtensionUtils.ts +55 -0
- package/src/JavaScriptSDK/DiagnosticLogger.ts +18 -1
- package/src/JavaScriptSDK.Interfaces/IConfiguration.ts +6 -0
- package/src/JavaScriptSDK.Interfaces/IDbgExtension.ts +14 -0
- package/src/JavaScriptSDK.Interfaces/IPerfEvent.ts +0 -1
- package/src/JavaScriptSDK.Interfaces/IPerfManager.ts +0 -1
- package/types/JavaScriptSDK/DbgExtensionUtils.d.ts +5 -0
- package/types/JavaScriptSDK.Interfaces/IConfiguration.d.ts +5 -0
- package/types/JavaScriptSDK.Interfaces/IDbgExtension.d.ts +10 -0
- package/types/applicationinsights-core-js.d.ts +2 -0
- package/CONTRIBUTING.md +0 -14
- package/Tests/Perf/src/CorePerfCheck.Tests.ts +0 -828
- package/Tests/Perf/src/aiperftests.ts +0 -6
- package/Tests/Perf/tsconfig.json +0 -17
- package/Tests/PerfTests.html +0 -54
- package/Tests/Unit/src/AppInsightsCoreSize.Tests.ts +0 -59
- package/Tests/Unit/src/ApplicationInsightsCore.Tests.ts +0 -1015
- package/Tests/Unit/src/CookieManager.Tests.ts +0 -477
- package/Tests/Unit/src/HelperFunc.Tests.ts +0 -59
- package/Tests/Unit/src/aiunittests.ts +0 -13
- package/Tests/UnitTests.html +0 -48
- package/Tests/tsconfig.json +0 -17
- package/api-extractor.json +0 -361
- package/applicationinsights-core-js.build.error.log +0 -205
- package/applicationinsights-core-js.build.log +0 -612
- package/microsoft-applicationinsights-core-js-2.7.2-nightly.2111-09.tgz +0 -0
- package/rollup.config.js +0 -138
- package/src/applicationinsights-core-js.ts +0 -59
- package/temp/applicationinsights-core-js.api.md +0 -934
- package/tslint.json +0 -5
|
@@ -1,1015 +0,0 @@
|
|
|
1
|
-
import { Assert, AITestClass } from "@microsoft/ai-test-framework";
|
|
2
|
-
import { IConfiguration, ITelemetryPlugin, ITelemetryItem, IPlugin, CoreUtils, IAppInsightsCore, normalizeJsName, random32, mwcRandom32, mwcRandomSeed } from "../../../src/applicationinsights-core-js"
|
|
3
|
-
import { AppInsightsCore } from "../../../src/JavaScriptSDK/AppInsightsCore";
|
|
4
|
-
import { IChannelControls } from "../../../src/JavaScriptSDK.Interfaces/IChannelControls";
|
|
5
|
-
import { _InternalMessageId, LoggingSeverity } from "../../../src/JavaScriptSDK.Enums/LoggingEnums";
|
|
6
|
-
import { _InternalLogMessage, DiagnosticLogger } from "../../../src/JavaScriptSDK/DiagnosticLogger";
|
|
7
|
-
|
|
8
|
-
const AIInternalMessagePrefix = "AITR_";
|
|
9
|
-
const MaxInt32 = 0xFFFFFFFF;
|
|
10
|
-
|
|
11
|
-
export class ApplicationInsightsCoreTests extends AITestClass {
|
|
12
|
-
|
|
13
|
-
public testInitialize() {
|
|
14
|
-
super.testInitialize();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public testCleanup() {
|
|
18
|
-
super.testCleanup();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public registerTests() {
|
|
22
|
-
|
|
23
|
-
this.testCase({
|
|
24
|
-
name: "ApplicationInsightsCore: Initialization validates input",
|
|
25
|
-
test: () => {
|
|
26
|
-
|
|
27
|
-
const samplingPlugin = new TestSamplingPlugin();
|
|
28
|
-
|
|
29
|
-
const appInsightsCore = new AppInsightsCore();
|
|
30
|
-
try {
|
|
31
|
-
appInsightsCore.initialize(null, [samplingPlugin]);
|
|
32
|
-
} catch (error) {
|
|
33
|
-
Assert.ok(true, "Validates configuration");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const config2: IConfiguration = {
|
|
37
|
-
endpointUrl: "https://dc.services.visualstudio.com/v2/track",
|
|
38
|
-
instrumentationKey: "40ed4f60-2a2f-4f94-a617-22b20a520864",
|
|
39
|
-
extensionConfig: {}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
appInsightsCore.initialize(config2, null);
|
|
44
|
-
} catch (error) {
|
|
45
|
-
Assert.ok(true, "Validates extensions are provided");
|
|
46
|
-
}
|
|
47
|
-
const config: IConfiguration = {
|
|
48
|
-
endpointUrl: "https://dc.services.visualstudio.com/v2/track",
|
|
49
|
-
instrumentationKey: "",
|
|
50
|
-
extensionConfig: {}
|
|
51
|
-
};
|
|
52
|
-
try {
|
|
53
|
-
appInsightsCore.initialize(config, [samplingPlugin]);
|
|
54
|
-
} catch (error) {
|
|
55
|
-
Assert.ok(true, "Validates instrumentationKey");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const channelPlugin1 = new ChannelPlugin();
|
|
59
|
-
channelPlugin1.priority = 1001;
|
|
60
|
-
|
|
61
|
-
const config3 = {
|
|
62
|
-
extensions: [channelPlugin1],
|
|
63
|
-
endpointUrl: "https://dc.services.visualstudio.com/v2/track",
|
|
64
|
-
instrumentationKey: "",
|
|
65
|
-
extensionConfig: {}
|
|
66
|
-
};
|
|
67
|
-
try {
|
|
68
|
-
appInsightsCore.initialize(config3, [samplingPlugin]);
|
|
69
|
-
} catch (error) {
|
|
70
|
-
Assert.ok(true, "Validates channels cannot be passed in through extensions");
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const channelPlugin2 = new ChannelPlugin();
|
|
74
|
-
channelPlugin2.priority = 200;
|
|
75
|
-
|
|
76
|
-
const config4 = {
|
|
77
|
-
channels: [[channelPlugin2]],
|
|
78
|
-
endpointUrl: "https://dc.services.visualstudio.com/v2/track",
|
|
79
|
-
instrumentationKey: "",
|
|
80
|
-
extensionConfig: {}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
let thrown = false;
|
|
84
|
-
try {
|
|
85
|
-
appInsightsCore.initialize(config4, [samplingPlugin]);
|
|
86
|
-
} catch (error) {
|
|
87
|
-
thrown = true;
|
|
88
|
-
}
|
|
89
|
-
Assert.ok(thrown, "Validates channels passed in through config, priority cannot be less Channel controller priority");
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
this.testCase({
|
|
95
|
-
name: "ApplicationInsightsCore: Initialization initializes setNextPlugin",
|
|
96
|
-
test: () => {
|
|
97
|
-
const samplingPlugin = new TestSamplingPlugin();
|
|
98
|
-
samplingPlugin.priority = 20;
|
|
99
|
-
|
|
100
|
-
const channelPlugin = new ChannelPlugin();
|
|
101
|
-
channelPlugin.priority = 1001;
|
|
102
|
-
// Assert prior to initialize
|
|
103
|
-
Assert.ok(!samplingPlugin.nexttPlugin, "Not setup prior to pipeline initialization");
|
|
104
|
-
|
|
105
|
-
const appInsightsCore = new AppInsightsCore();
|
|
106
|
-
appInsightsCore.initialize(
|
|
107
|
-
{ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41" },
|
|
108
|
-
[samplingPlugin, channelPlugin]);
|
|
109
|
-
Assert.ok(!!samplingPlugin.nexttPlugin, "setup prior to pipeline initialization");
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
this.testCase({
|
|
115
|
-
name: "ApplicationInsightsCore: Plugins can be added with same priority",
|
|
116
|
-
test: () => {
|
|
117
|
-
const samplingPlugin = new TestSamplingPlugin();
|
|
118
|
-
samplingPlugin.priority = 20;
|
|
119
|
-
|
|
120
|
-
const samplingPlugin1 = new TestSamplingPlugin();
|
|
121
|
-
samplingPlugin1.priority = 20;
|
|
122
|
-
|
|
123
|
-
const channelPlugin = new ChannelPlugin();
|
|
124
|
-
channelPlugin.priority = 1001;
|
|
125
|
-
|
|
126
|
-
const appInsightsCore = new AppInsightsCore();
|
|
127
|
-
try {
|
|
128
|
-
appInsightsCore.initialize(
|
|
129
|
-
{ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41" },
|
|
130
|
-
[samplingPlugin, samplingPlugin1, channelPlugin]);
|
|
131
|
-
|
|
132
|
-
Assert.ok("No error on duplicate priority");
|
|
133
|
-
} catch (error) {
|
|
134
|
-
Assert.ok(false); // duplicate priority does not throw error
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
this.testCase({
|
|
140
|
-
name: "ApplicationInsightsCore: flush clears channel buffer",
|
|
141
|
-
test: () => {
|
|
142
|
-
const channelPlugin = new ChannelPlugin();
|
|
143
|
-
const appInsightsCore = new AppInsightsCore();
|
|
144
|
-
appInsightsCore.initialize(
|
|
145
|
-
{ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41" },
|
|
146
|
-
[channelPlugin]);
|
|
147
|
-
|
|
148
|
-
Assert.ok(!channelPlugin.isUnloadInvoked, "Unload not called on initialize");
|
|
149
|
-
appInsightsCore.getTransmissionControls().forEach(queues => {
|
|
150
|
-
queues.forEach((q: IChannelControls & ChannelPlugin) => {
|
|
151
|
-
if (q.onunloadFlush) {
|
|
152
|
-
q.onunloadFlush()
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
Assert.ok(channelPlugin.isUnloadInvoked, "Unload triggered for channel");
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
this.testCase({
|
|
162
|
-
name: "config.channel adds additional queue to existing channels",
|
|
163
|
-
test: () => {
|
|
164
|
-
const channelPlugin = new ChannelPlugin();
|
|
165
|
-
channelPlugin.priority = 1030;
|
|
166
|
-
|
|
167
|
-
const channelPlugin1 = new ChannelPlugin();
|
|
168
|
-
channelPlugin1.priority = 1030;
|
|
169
|
-
|
|
170
|
-
const appInsightsCore = new AppInsightsCore();
|
|
171
|
-
appInsightsCore.initialize(
|
|
172
|
-
{ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41", channels: [[channelPlugin1]] },
|
|
173
|
-
[channelPlugin]);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const channelQueues = appInsightsCore.getTransmissionControls();
|
|
177
|
-
Assert.equal(2, channelQueues.length, "Total number of channel queues");
|
|
178
|
-
Assert.equal(1, channelQueues[0].length, "Number of channels in queue 1");
|
|
179
|
-
Assert.equal(1, channelQueues[1].length, "Number of channels in queue 2");
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
this.testCase({
|
|
184
|
-
name: 'ApplicationInsightsCore: track adds required default fields if missing',
|
|
185
|
-
useFakeTimers: true,
|
|
186
|
-
test: () => {
|
|
187
|
-
const expectedIKey: string = "09465199-12AA-4124-817F-544738CC7C41";
|
|
188
|
-
const expectedTimestamp = new Date().toISOString();
|
|
189
|
-
const expectedBaseType = "EventData";
|
|
190
|
-
|
|
191
|
-
const channelPlugin = new ChannelPlugin();
|
|
192
|
-
const appInsightsCore = new AppInsightsCore();
|
|
193
|
-
appInsightsCore.initialize({ instrumentationKey: expectedIKey }, [channelPlugin]);
|
|
194
|
-
|
|
195
|
-
// Act
|
|
196
|
-
const bareItem: ITelemetryItem = { name: 'test item' };
|
|
197
|
-
appInsightsCore.track(bareItem);
|
|
198
|
-
this.clock.tick(1);
|
|
199
|
-
|
|
200
|
-
// Test
|
|
201
|
-
Assert.equal(expectedIKey, bareItem.iKey, "Instrumentation key is added");
|
|
202
|
-
Assert.deepEqual(expectedTimestamp, bareItem.time, "Timestamp is added");
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
this.testCase({
|
|
207
|
-
name: 'ApplicationInsightsCore: track does not replace non-empty iKey',
|
|
208
|
-
useFakeTimers: true,
|
|
209
|
-
test: () => {
|
|
210
|
-
const configIkey: string = "configIkey";
|
|
211
|
-
const eventIkey: string = "eventIkey";
|
|
212
|
-
|
|
213
|
-
const channelPlugin = new ChannelPlugin();
|
|
214
|
-
const appInsightsCore = new AppInsightsCore();
|
|
215
|
-
appInsightsCore.initialize({ instrumentationKey:configIkey}, [channelPlugin]);
|
|
216
|
-
|
|
217
|
-
// Act
|
|
218
|
-
const bareItem: ITelemetryItem = { name: 'test item', iKey: eventIkey };
|
|
219
|
-
appInsightsCore.track(bareItem);
|
|
220
|
-
this.clock.tick(1);
|
|
221
|
-
|
|
222
|
-
// Test
|
|
223
|
-
Assert.equal(eventIkey, bareItem.iKey, "Instrumentation key is replaced");
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
this.testCase({
|
|
228
|
-
name: "DiagnosticLogger: Critical logging history is saved",
|
|
229
|
-
test: () => {
|
|
230
|
-
// Setup
|
|
231
|
-
const channelPlugin = new ChannelPlugin();
|
|
232
|
-
const appInsightsCore = new AppInsightsCore();
|
|
233
|
-
appInsightsCore.initialize({ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41", loggingLevelTelemetry: 999 }, [channelPlugin]);
|
|
234
|
-
|
|
235
|
-
const messageId: _InternalMessageId = _InternalMessageId.CannotAccessCookie; // can be any id
|
|
236
|
-
|
|
237
|
-
const logInternalSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
|
|
238
|
-
|
|
239
|
-
// Test precondition
|
|
240
|
-
Assert.ok(logInternalSpy.notCalled, 'PRE: No internal logging performed yet');
|
|
241
|
-
Assert.equal(0, appInsightsCore.logger.queue.length, 'PRE: No logging recorded');
|
|
242
|
-
|
|
243
|
-
// Act
|
|
244
|
-
appInsightsCore.logger.throwInternal(LoggingSeverity.CRITICAL, messageId, "Test Error");
|
|
245
|
-
|
|
246
|
-
// Test postcondition
|
|
247
|
-
Assert.ok(logInternalSpy.calledOnce, 'POST: Logging success');
|
|
248
|
-
Assert.equal(messageId, logInternalSpy.args[0][1].messageId, "Correct message logged");
|
|
249
|
-
Assert.ok(logInternalSpy.args[0][1].message.indexOf('Test Error') !== -1, "Correct message logged");
|
|
250
|
-
Assert.equal(1, appInsightsCore.logger.queue.length, "POST: Correct messageId logged");
|
|
251
|
-
Assert.ok(appInsightsCore.logger.queue[0].message.indexOf('Test Error') !== -1, "Correct message logged");
|
|
252
|
-
Assert.equal(messageId, appInsightsCore.logger.queue[0].messageId, "Correct message logged");
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
this.testCase({
|
|
257
|
-
name: 'DiagnosticLogger: Logger can be created with default constructor',
|
|
258
|
-
test: () => {
|
|
259
|
-
// setup
|
|
260
|
-
const channelPlugin = new ChannelPlugin();
|
|
261
|
-
const appInsightsCore = new AppInsightsCore();
|
|
262
|
-
appInsightsCore.logger = new DiagnosticLogger();
|
|
263
|
-
|
|
264
|
-
const messageId: _InternalMessageId = _InternalMessageId.CannotAccessCookie; // can be any id
|
|
265
|
-
const logInternalSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
|
|
266
|
-
|
|
267
|
-
// Verify precondition
|
|
268
|
-
Assert.ok(logInternalSpy.notCalled, 'PRE: No internal logging performed yet');
|
|
269
|
-
Assert.equal(0, appInsightsCore.logger.queue.length, 'PRE: No internal logging performed yet');
|
|
270
|
-
|
|
271
|
-
// Act
|
|
272
|
-
appInsightsCore.logger.throwInternal(LoggingSeverity.CRITICAL, messageId, "Some message");
|
|
273
|
-
|
|
274
|
-
// Test postcondition
|
|
275
|
-
Assert.ok(logInternalSpy.calledOnce, 'POST: Logging success');
|
|
276
|
-
Assert.equal(messageId, logInternalSpy.args[0][1].messageId, "Correct message logged");
|
|
277
|
-
Assert.equal(messageId, appInsightsCore.logger.queue[0].messageId, "POST: Correct messageId logged");
|
|
278
|
-
|
|
279
|
-
// Logging same error doesn't duplicate
|
|
280
|
-
Assert.equal(1, appInsightsCore.logger.queue.length, "Pre: Only 1 logged message");
|
|
281
|
-
appInsightsCore.logger.throwInternal(LoggingSeverity.CRITICAL, messageId, "Some message");
|
|
282
|
-
Assert.equal(1, appInsightsCore.logger.queue.length, "Pre: Still only 1 logged message");
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// TODO: test no reinitialization
|
|
287
|
-
this.testCase({
|
|
288
|
-
name: "Initialize: core cannot be reinitialized",
|
|
289
|
-
test: () => {
|
|
290
|
-
// Setup
|
|
291
|
-
const channelPlugin = new ChannelPlugin();
|
|
292
|
-
const appInsightsCore = new AppInsightsCore();
|
|
293
|
-
const initFunction = () => appInsightsCore.initialize({ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41" }, [channelPlugin]);
|
|
294
|
-
|
|
295
|
-
// Assert precondition
|
|
296
|
-
Assert.ok(!appInsightsCore.isInitialized(), "PRE: core constructed but not initialized");
|
|
297
|
-
|
|
298
|
-
// Init
|
|
299
|
-
initFunction();
|
|
300
|
-
|
|
301
|
-
// Assert initialized
|
|
302
|
-
Assert.ok(appInsightsCore.isInitialized(), "core is initialized");
|
|
303
|
-
|
|
304
|
-
Assert.throws(initFunction, Error, "Core cannot be reinitialized");
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
// TODO: test pollInternalLogs
|
|
309
|
-
this.testCase({
|
|
310
|
-
name: "DiagnosticLogger: Logs can be polled",
|
|
311
|
-
useFakeTimers: true,
|
|
312
|
-
test: () => {
|
|
313
|
-
// Setup
|
|
314
|
-
const channelPlugin = new ChannelPlugin();
|
|
315
|
-
const appInsightsCore = new AppInsightsCore();
|
|
316
|
-
appInsightsCore.initialize(
|
|
317
|
-
{
|
|
318
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41",
|
|
319
|
-
diagnosticLogInterval: 1
|
|
320
|
-
}, [channelPlugin]);
|
|
321
|
-
const trackTraceSpy = this.sandbox.stub(appInsightsCore, "track");
|
|
322
|
-
|
|
323
|
-
Assert.equal(0, appInsightsCore.logger.queue.length, "Queue is empty");
|
|
324
|
-
|
|
325
|
-
// Setup queue
|
|
326
|
-
const queue: _InternalLogMessage[] = appInsightsCore.logger.queue;
|
|
327
|
-
queue.push(new _InternalLogMessage(1, "Hello1"));
|
|
328
|
-
queue.push(new _InternalLogMessage(2, "Hello2"));
|
|
329
|
-
const poller = appInsightsCore.pollInternalLogs();
|
|
330
|
-
|
|
331
|
-
// Assert precondition
|
|
332
|
-
Assert.equal(2, appInsightsCore.logger.queue.length, "Queue contains 2 items");
|
|
333
|
-
|
|
334
|
-
// Act
|
|
335
|
-
this.clock.tick(1);
|
|
336
|
-
|
|
337
|
-
// Assert postcondition
|
|
338
|
-
Assert.equal(0, appInsightsCore.logger.queue.length, "Queue is empty");
|
|
339
|
-
|
|
340
|
-
const data1 = trackTraceSpy.args[0][0];
|
|
341
|
-
Assert.ok(data1.baseData.message.indexOf("Hello1") !== -1);
|
|
342
|
-
|
|
343
|
-
const data2 = trackTraceSpy.args[1][0];
|
|
344
|
-
Assert.ok(data2.baseData.message.indexOf("Hello2") !== -1);
|
|
345
|
-
|
|
346
|
-
// Cleanup
|
|
347
|
-
clearInterval(poller);
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// TODO: test stopPollingInternalLogs
|
|
352
|
-
this.testCase({
|
|
353
|
-
name: "DiagnosticLogger: stop Polling InternalLogs",
|
|
354
|
-
useFakeTimers: true,
|
|
355
|
-
test: () => {
|
|
356
|
-
// Setup
|
|
357
|
-
const channelPlugin = new ChannelPlugin();
|
|
358
|
-
const appInsightsCore = new AppInsightsCore();
|
|
359
|
-
appInsightsCore.initialize(
|
|
360
|
-
{
|
|
361
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41",
|
|
362
|
-
diagnosticLogInterval: 1
|
|
363
|
-
}, [channelPlugin]);
|
|
364
|
-
|
|
365
|
-
Assert.equal(0, appInsightsCore.logger.queue.length, "Queue is empty");
|
|
366
|
-
|
|
367
|
-
// Setup queue
|
|
368
|
-
const queue: _InternalLogMessage[] = appInsightsCore.logger.queue;
|
|
369
|
-
queue.push(new _InternalLogMessage(1, "Hello1"));
|
|
370
|
-
queue.push(new _InternalLogMessage(2, "Hello2"));
|
|
371
|
-
appInsightsCore.pollInternalLogs();
|
|
372
|
-
|
|
373
|
-
// Assert precondition
|
|
374
|
-
Assert.equal(2, appInsightsCore.logger.queue.length, "Queue contains 2 items");
|
|
375
|
-
|
|
376
|
-
// Act
|
|
377
|
-
appInsightsCore.stopPollingInternalLogs();
|
|
378
|
-
this.clock.tick(1);
|
|
379
|
-
|
|
380
|
-
// Assert postcondition
|
|
381
|
-
Assert.equal(2, appInsightsCore.logger.queue.length, "Queue is not empty");
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// TODO: test stopPollingInternalLogs and check max size of the queue.
|
|
386
|
-
this.testCase({
|
|
387
|
-
name: "DiagnosticLogger: stop Polling InternalLogs",
|
|
388
|
-
useFakeTimers: true,
|
|
389
|
-
test: () => {
|
|
390
|
-
// Setup
|
|
391
|
-
const channelPlugin = new ChannelPlugin();
|
|
392
|
-
const appInsightsCore = new AppInsightsCore();
|
|
393
|
-
appInsightsCore.initialize(
|
|
394
|
-
{
|
|
395
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41",
|
|
396
|
-
diagnosticLogInterval: 1
|
|
397
|
-
}, [channelPlugin]);
|
|
398
|
-
|
|
399
|
-
appInsightsCore.pollInternalLogs();
|
|
400
|
-
|
|
401
|
-
// Assert precondition
|
|
402
|
-
Assert.equal(0, appInsightsCore.logger.queue.length, "Queue contains 0 items");
|
|
403
|
-
|
|
404
|
-
// Act
|
|
405
|
-
appInsightsCore.stopPollingInternalLogs();
|
|
406
|
-
let count = 1002;
|
|
407
|
-
while(count > 0) {
|
|
408
|
-
appInsightsCore.logger.throwInternal(LoggingSeverity.CRITICAL, count, "Test Error");
|
|
409
|
-
--count;
|
|
410
|
-
}
|
|
411
|
-
// this.clock.tick(1000);
|
|
412
|
-
// Assert postcondition
|
|
413
|
-
Assert.equal(26, appInsightsCore.logger.queue.length, "Queue is not empty");
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
// TODO: test logger crosscontamination
|
|
418
|
-
this.testCase({
|
|
419
|
-
name: "DiagnosticLogger: Logs in separate cores do not interfere",
|
|
420
|
-
test: () => {
|
|
421
|
-
// Setup
|
|
422
|
-
const channelPlugin = new ChannelPlugin();
|
|
423
|
-
const appInsightsCore = new AppInsightsCore();
|
|
424
|
-
appInsightsCore.initialize(
|
|
425
|
-
{
|
|
426
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41",
|
|
427
|
-
loggingLevelTelemetry: 999
|
|
428
|
-
}, [channelPlugin]
|
|
429
|
-
);
|
|
430
|
-
const dummyCore = new AppInsightsCore();
|
|
431
|
-
dummyCore.initialize(
|
|
432
|
-
{
|
|
433
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41",
|
|
434
|
-
loggingLevelTelemetry: 999
|
|
435
|
-
}, [channelPlugin]
|
|
436
|
-
);
|
|
437
|
-
|
|
438
|
-
const aiSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
|
|
439
|
-
const dummySpy = this.sandbox.spy(dummyCore.logger, 'logInternalMessage');
|
|
440
|
-
|
|
441
|
-
const messageId: _InternalMessageId = _InternalMessageId.CannotAccessCookie; // can be any id
|
|
442
|
-
|
|
443
|
-
// Test precondition
|
|
444
|
-
Assert.equal(0, appInsightsCore.logger.queue.length, 'PRE: No internal logging performed yet');
|
|
445
|
-
Assert.ok(aiSpy.notCalled, "PRE: messageId not yet logged");
|
|
446
|
-
Assert.equal(0, dummyCore.logger.queue.length, 'PRE: No dummy logging');
|
|
447
|
-
Assert.ok(dummySpy.notCalled, "PRE: No dummy messageId logged");
|
|
448
|
-
|
|
449
|
-
// Act
|
|
450
|
-
appInsightsCore.logger.throwInternal(LoggingSeverity.CRITICAL, messageId, "Test Error");
|
|
451
|
-
|
|
452
|
-
// Test postcondition
|
|
453
|
-
Assert.equal(1, appInsightsCore.logger.queue.length, 'POST: Logging success');
|
|
454
|
-
Assert.ok(aiSpy.called, "POST: Correct messageId logged");
|
|
455
|
-
Assert.equal(0, dummyCore.logger.queue.length, 'POST: No dummy logging');
|
|
456
|
-
Assert.ok(dummySpy.notCalled, "POST: No dummy messageId logged");
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
this.testCase({
|
|
461
|
-
name: "ApplicationInsightsCore: Plugins can be provided through configuration",
|
|
462
|
-
test: () => {
|
|
463
|
-
const samplingPlugin = new TestSamplingPlugin();
|
|
464
|
-
samplingPlugin.priority = 20;
|
|
465
|
-
|
|
466
|
-
const channelPlugin = new ChannelPlugin();
|
|
467
|
-
channelPlugin.priority = 1001;
|
|
468
|
-
|
|
469
|
-
const appInsightsCore = new AppInsightsCore();
|
|
470
|
-
try {
|
|
471
|
-
appInsightsCore.initialize(
|
|
472
|
-
{ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41", extensions: [samplingPlugin] },
|
|
473
|
-
[channelPlugin]);
|
|
474
|
-
} catch (error) {
|
|
475
|
-
Assert.ok(false, "No error expected");
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
let found = false;
|
|
479
|
-
(appInsightsCore as any)._extensions.forEach(ext => {
|
|
480
|
-
if (ext.identifier === samplingPlugin.identifier) {
|
|
481
|
-
found = true;
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
Assert.ok(found, "Plugin pased in through config is part of pipeline");
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
this.testCase({
|
|
490
|
-
name: "ApplicationInsightsCore: Non telemetry specific plugins are initialized and not part of telemetry processing pipeline",
|
|
491
|
-
test: () => {
|
|
492
|
-
const samplingPlugin = new TestSamplingPlugin();
|
|
493
|
-
samplingPlugin.priority = 20;
|
|
494
|
-
|
|
495
|
-
const testPlugin = new TestPlugin();
|
|
496
|
-
|
|
497
|
-
const channelPlugin = new ChannelPlugin();
|
|
498
|
-
channelPlugin.priority = 1001;
|
|
499
|
-
|
|
500
|
-
const appInsightsCore = new AppInsightsCore();
|
|
501
|
-
try {
|
|
502
|
-
appInsightsCore.initialize(
|
|
503
|
-
{ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41" },
|
|
504
|
-
[testPlugin, samplingPlugin, channelPlugin]);
|
|
505
|
-
} catch (error) {
|
|
506
|
-
Assert.ok(false, "Exception not expected");
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
Assert.ok(typeof ((appInsightsCore as any)._extensions[0].processTelemetry) !== 'function', "Extensions can be provided through overall configuration");
|
|
510
|
-
}
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
this.testCase({
|
|
514
|
-
name: "Channels can be passed in through configuration",
|
|
515
|
-
test: () => {
|
|
516
|
-
|
|
517
|
-
const channelPlugin1 = new ChannelPlugin();
|
|
518
|
-
channelPlugin1.priority = 1001;
|
|
519
|
-
|
|
520
|
-
const channelPlugin2 = new ChannelPlugin();
|
|
521
|
-
channelPlugin2.priority = 1002;
|
|
522
|
-
|
|
523
|
-
const channelPlugin3 = new ChannelPlugin();
|
|
524
|
-
channelPlugin3.priority = 1001;
|
|
525
|
-
|
|
526
|
-
const appInsightsCore = new AppInsightsCore();
|
|
527
|
-
appInsightsCore.initialize(
|
|
528
|
-
{
|
|
529
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41",
|
|
530
|
-
channels: [[channelPlugin1, channelPlugin2], [channelPlugin3]]
|
|
531
|
-
},
|
|
532
|
-
[]);
|
|
533
|
-
|
|
534
|
-
Assert.ok(channelPlugin1._nextPlugin === channelPlugin2);
|
|
535
|
-
Assert.ok(CoreUtils.isNullOrUndefined(channelPlugin3._nextPlugin));
|
|
536
|
-
const channelControls = appInsightsCore.getTransmissionControls();
|
|
537
|
-
Assert.ok(channelControls.length === 2);
|
|
538
|
-
Assert.ok(channelControls[0].length === 2);
|
|
539
|
-
Assert.ok(channelControls[1].length === 1);
|
|
540
|
-
Assert.ok(channelControls[0][0] === channelPlugin1);
|
|
541
|
-
Assert.ok(channelControls[1][0] === channelPlugin3);
|
|
542
|
-
Assert.ok(channelPlugin2._nextPlugin === undefined);
|
|
543
|
-
Assert.ok(channelPlugin3._nextPlugin === undefined);
|
|
544
|
-
}
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
this.testCase({
|
|
548
|
-
name: 'ApplicationInsightsCore: user can add two channels in single queue',
|
|
549
|
-
test: () => {
|
|
550
|
-
const channelPlugin1 = new ChannelPlugin();
|
|
551
|
-
channelPlugin1.priority = 1001;
|
|
552
|
-
|
|
553
|
-
const channelPlugin2 = new ChannelPlugin();
|
|
554
|
-
channelPlugin2.priority = 1002;
|
|
555
|
-
|
|
556
|
-
const channelPlugin3 = new ChannelPlugin();
|
|
557
|
-
channelPlugin3.priority = 1003;
|
|
558
|
-
|
|
559
|
-
const appInsightsCore = new AppInsightsCore();
|
|
560
|
-
appInsightsCore.initialize(
|
|
561
|
-
{
|
|
562
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41"
|
|
563
|
-
},
|
|
564
|
-
[channelPlugin1, channelPlugin2, channelPlugin3]);
|
|
565
|
-
|
|
566
|
-
Assert.ok(channelPlugin1._nextPlugin === channelPlugin2);
|
|
567
|
-
Assert.ok(channelPlugin2._nextPlugin === channelPlugin3);
|
|
568
|
-
Assert.ok(CoreUtils.isNullOrUndefined(channelPlugin3._nextPlugin));
|
|
569
|
-
const channelControls = appInsightsCore.getTransmissionControls();
|
|
570
|
-
Assert.ok(channelControls.length === 1);
|
|
571
|
-
Assert.ok(channelControls[0].length === 3);
|
|
572
|
-
Assert.ok(channelControls[0][0] === channelPlugin1);
|
|
573
|
-
Assert.ok(channelControls[0][1] === channelPlugin2);
|
|
574
|
-
Assert.ok(channelControls[0][2] === channelPlugin3);
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
this.testCase({
|
|
579
|
-
name: 'ApplicationInsightsCore: Validates root level properties in telemetry item',
|
|
580
|
-
test: () => {
|
|
581
|
-
const expectedIKey: string = "09465199-12AA-4124-817F-544738CC7C41";
|
|
582
|
-
|
|
583
|
-
const channelPlugin = new ChannelPlugin();
|
|
584
|
-
channelPlugin.priority = 1001;
|
|
585
|
-
const samplingPlugin = new TestSamplingPlugin(true);
|
|
586
|
-
const appInsightsCore = new AppInsightsCore();
|
|
587
|
-
appInsightsCore.initialize({ instrumentationKey: expectedIKey }, [samplingPlugin, channelPlugin]);
|
|
588
|
-
|
|
589
|
-
// Act
|
|
590
|
-
const bareItem: ITelemetryItem = {
|
|
591
|
-
name: 'test item',
|
|
592
|
-
ext: {
|
|
593
|
-
"user": { "id": "test" }
|
|
594
|
-
},
|
|
595
|
-
tags: [{ "device.id": "AABA40BC-EB0D-44A7-96F5-ED2103E47AE9" }],
|
|
596
|
-
data: {
|
|
597
|
-
"custom data": {
|
|
598
|
-
"data1": "value1"
|
|
599
|
-
}
|
|
600
|
-
},
|
|
601
|
-
baseType: "PageviewData",
|
|
602
|
-
baseData: { name: "Test Page" }
|
|
603
|
-
};
|
|
604
|
-
|
|
605
|
-
appInsightsCore.track(bareItem);
|
|
606
|
-
}
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
this.testCase({
|
|
610
|
-
name: "Channels work even if no extensions are present",
|
|
611
|
-
test: () => {
|
|
612
|
-
const channelPlugin = new ChannelPlugin();
|
|
613
|
-
channelPlugin.priority = 1030;
|
|
614
|
-
const appInsightsCore = new AppInsightsCore();
|
|
615
|
-
const channelSpy = this.sandbox.stub(channelPlugin, "processTelemetry");
|
|
616
|
-
appInsightsCore.initialize(
|
|
617
|
-
{
|
|
618
|
-
instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41", channels: [[channelPlugin]]
|
|
619
|
-
}, []);
|
|
620
|
-
const event: ITelemetryItem = { name: 'test' };
|
|
621
|
-
appInsightsCore.track(event);
|
|
622
|
-
const evt = channelSpy.args[0][0];
|
|
623
|
-
Assert.ok(evt.name === "test");
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
|
|
627
|
-
this.testCase({
|
|
628
|
-
name: "ApplicationInsightsCore: Track queue event when not all extensions are initialized",
|
|
629
|
-
test: () => {
|
|
630
|
-
const trackPlugin = new TrackPlugin();
|
|
631
|
-
const channelPlugin = new ChannelPlugin();
|
|
632
|
-
channelPlugin.priority = 1001;
|
|
633
|
-
const appInsightsCore = new AppInsightsCore();
|
|
634
|
-
const channelSpy = this.sandbox.stub(channelPlugin, "processTelemetry");
|
|
635
|
-
appInsightsCore.initialize(
|
|
636
|
-
{ instrumentationKey: "09465199-12AA-4124-817F-544738CC7C41" },
|
|
637
|
-
[trackPlugin, channelPlugin]);
|
|
638
|
-
Assert.ok(channelSpy.calledOnce, "Channel process incorrect number of times");
|
|
639
|
-
Assert.ok(channelSpy.args[0][0].name == "TestEvent1", "Incorrect event");
|
|
640
|
-
Assert.ok(appInsightsCore.eventCnt() == 0, "Event queue wrong number of events");
|
|
641
|
-
}
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
this.testCase({
|
|
645
|
-
name: "ApplicationInsightsCore: Validate JS name normalization",
|
|
646
|
-
test: () => {
|
|
647
|
-
Assert.equal("Hello", normalizeJsName("Hello"));
|
|
648
|
-
Assert.equal("Hello_World", normalizeJsName("Hello.World"));
|
|
649
|
-
Assert.equal("_Hello_World", normalizeJsName("@Hello.World"));
|
|
650
|
-
Assert.equal("_Hello_World", normalizeJsName("#Hello.World"));
|
|
651
|
-
Assert.equal("_Hello_World", normalizeJsName(".Hello#World"));
|
|
652
|
-
Assert.equal("_Hello_World_", normalizeJsName(".Hello(World)"));
|
|
653
|
-
Assert.equal("_Hello_World_", normalizeJsName(".Hello&World%"));
|
|
654
|
-
Assert.equal("_Hello_World_", normalizeJsName("!Hello=World+"));
|
|
655
|
-
Assert.equal("_Hello_World_", normalizeJsName("~Hello[World]"));
|
|
656
|
-
Assert.equal("_Hello_World_", normalizeJsName(":Hello{World}"));
|
|
657
|
-
Assert.equal("_Hello_World_", normalizeJsName("\'Hello\'World;"));
|
|
658
|
-
Assert.equal("_Hello_World_", normalizeJsName("\"Hello\\World\""));
|
|
659
|
-
Assert.equal("_Hello_World_", normalizeJsName("|Hello<World>"));
|
|
660
|
-
Assert.equal("_Hello_World_", normalizeJsName("?Hello,World-"));
|
|
661
|
-
}
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
this.testCase({
|
|
666
|
-
name: 'newId tests length',
|
|
667
|
-
test: () => {
|
|
668
|
-
_checkNewId(5, CoreUtils.newId(5), "Test the previous length");
|
|
669
|
-
_checkNewId(10, CoreUtils.newId(10), "Test the double the previous length");
|
|
670
|
-
_checkNewId(22, CoreUtils.newId(), "Test new default length");
|
|
671
|
-
_checkNewId(99, CoreUtils.newId(99), "Test 99 character == 74.25 bytes");
|
|
672
|
-
_checkNewId(200, CoreUtils.newId(200), "Test 200 character == 150 bytes");
|
|
673
|
-
|
|
674
|
-
// Check the id is not zero filled ("A") based on the an int32 === 5 base64 bytes (plus 2 bits)
|
|
675
|
-
let newId = CoreUtils.newId();
|
|
676
|
-
Assert.notEqual("AAAAAAAAAAAAAAAA", newId.substring(0, 16), "Make sure that [" + newId + "] value is not zero filled (generally -- it is randomly possible)")
|
|
677
|
-
Assert.notEqual("AAAAAAAAAAAAAAAA", newId.substring(5), "Make sure that [" + newId + "] value is not zero filled (generally -- it is randomly possible)")
|
|
678
|
-
}
|
|
679
|
-
});
|
|
680
|
-
|
|
681
|
-
this.testCase({
|
|
682
|
-
name: 'newId check randomness',
|
|
683
|
-
timeout: 15000,
|
|
684
|
-
test: () => {
|
|
685
|
-
let map = {};
|
|
686
|
-
|
|
687
|
-
// Check that mwcRandom is bing called (relies on the mwc implementation from the default seed)
|
|
688
|
-
mwcRandomSeed(1);
|
|
689
|
-
Assert.notEqual(722346555, random32(), "Make sure that the mwcRandom was not being called - step 1");
|
|
690
|
-
Assert.notEqual(3284929732, random32(), "Make sure that the mwcRandom was not being called - step2");
|
|
691
|
-
|
|
692
|
-
// cause auto seeding again
|
|
693
|
-
mwcRandomSeed();
|
|
694
|
-
|
|
695
|
-
for (let lp = 0; lp < 10000; lp ++) {
|
|
696
|
-
let newId = CoreUtils.newId();
|
|
697
|
-
if (map[newId]) {
|
|
698
|
-
Assert.ok(false, "[" + newId + "] was duplicated...")
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
map[newId] = true;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
mwcRandomSeed(1);
|
|
705
|
-
Assert.notEqual(722346555, random32(), "Make sure that the mwcRandom was not being called");
|
|
706
|
-
}
|
|
707
|
-
});
|
|
708
|
-
|
|
709
|
-
this.testCase({
|
|
710
|
-
name: 'newId check randomness -- emulating IE',
|
|
711
|
-
timeout: 15000,
|
|
712
|
-
test: () => {
|
|
713
|
-
let map = {};
|
|
714
|
-
|
|
715
|
-
// Enumlate IE
|
|
716
|
-
this.setUserAgent("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)");
|
|
717
|
-
this.setCrypto(null);
|
|
718
|
-
|
|
719
|
-
// Check that mwcRandom is bing called (relies on the mwc implementation from the default seed)
|
|
720
|
-
mwcRandomSeed(1);
|
|
721
|
-
Assert.equal(722346555, random32(), "Make sure that the mwcRandom was being called - step 1");
|
|
722
|
-
Assert.equal(3284929732, random32(), "Make sure that the mwcRandom was being called - step2");
|
|
723
|
-
|
|
724
|
-
// cause auto seeding again
|
|
725
|
-
mwcRandomSeed();
|
|
726
|
-
Assert.notEqual(722346555, random32(), "Make sure that the mwcRandom was being called - step 3");
|
|
727
|
-
|
|
728
|
-
for (let lp = 0; lp < 10000; lp ++) {
|
|
729
|
-
let newId = CoreUtils.newId();
|
|
730
|
-
if (map[newId]) {
|
|
731
|
-
Assert.ok(false, "[" + newId + "] was duplicated...")
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
map[newId] = true;
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// Reset the seed and re-check the expected result
|
|
738
|
-
mwcRandomSeed(1);
|
|
739
|
-
Assert.equal(722346555, random32(), "Make sure that the mwcRandom was not being called - step 4");
|
|
740
|
-
}
|
|
741
|
-
});
|
|
742
|
-
|
|
743
|
-
this.testCase({
|
|
744
|
-
name: 'Test CoreUtils.randomValue() randomness and distribution',
|
|
745
|
-
timeout: 15000,
|
|
746
|
-
test: () => {
|
|
747
|
-
let numBuckets = 100;
|
|
748
|
-
let buckets: number[] = _createBuckets(100);
|
|
749
|
-
let runs = 1000000;
|
|
750
|
-
|
|
751
|
-
for (let lp = 0; lp < runs; lp++) {
|
|
752
|
-
const bucket = CoreUtils.randomValue(numBuckets-1);
|
|
753
|
-
buckets[bucket] ++;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
let min = 10;
|
|
757
|
-
let max = -1;
|
|
758
|
-
let mode = 0;
|
|
759
|
-
|
|
760
|
-
for (let lp = 0; lp < numBuckets; lp++) {
|
|
761
|
-
buckets[lp] /= runs;
|
|
762
|
-
mode += buckets[lp];
|
|
763
|
-
min = Math.min(min, buckets[lp]);
|
|
764
|
-
max = Math.max(max, buckets[lp]);
|
|
765
|
-
|
|
766
|
-
if (buckets[lp] === 0) {
|
|
767
|
-
Assert.ok(false, 'Bucket: ' + lp + ' is empty!');
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
Assert.equal(undefined, buckets[numBuckets], 'Make sure that we only allocated the correct number of buckets');
|
|
772
|
-
|
|
773
|
-
const totalVariance = mode / numBuckets;
|
|
774
|
-
|
|
775
|
-
let perfectDist = 1 / numBuckets;
|
|
776
|
-
let testDist = perfectDist * 1.5;
|
|
777
|
-
|
|
778
|
-
Assert.ok(min > 0 && min <= testDist, min + ': Make sure that we have a good minimum distribution, perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
779
|
-
Assert.ok(max > 0 && max <= testDist, max + ': Make sure that we have a good maximum distribution, perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
780
|
-
Assert.ok(totalVariance > 0 && totalVariance <= testDist, totalVariance + ': Check the average distribution perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
781
|
-
}
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
this.testCase({
|
|
785
|
-
name: 'Test CoreUtils.random32() randomness and distribution',
|
|
786
|
-
timeout: 15000,
|
|
787
|
-
test: () => {
|
|
788
|
-
let numBuckets = 100;
|
|
789
|
-
let buckets: number[] = _createBuckets(100);
|
|
790
|
-
let runs = 1000000;
|
|
791
|
-
|
|
792
|
-
for (let lp = 0; lp < runs; lp++) {
|
|
793
|
-
// Need to use floor otherwise the bucket is defined as a float as the index
|
|
794
|
-
const bucket = Math.floor((CoreUtils.random32() / MaxInt32) * numBuckets);
|
|
795
|
-
buckets[bucket] ++;
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
let min = 10;
|
|
799
|
-
let max = -1;
|
|
800
|
-
let mode = 0;
|
|
801
|
-
|
|
802
|
-
for (let lp = 0; lp < numBuckets; lp++) {
|
|
803
|
-
buckets[lp] /= runs;
|
|
804
|
-
mode += buckets[lp];
|
|
805
|
-
min = Math.min(min, buckets[lp]);
|
|
806
|
-
max = Math.max(max, buckets[lp]);
|
|
807
|
-
|
|
808
|
-
if (buckets[lp] === 0) {
|
|
809
|
-
Assert.ok(false, 'Bucket: ' + lp + ' is empty!');
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
Assert.equal(undefined, buckets[numBuckets], 'Make sure that we only allocated the correct number of buckets');
|
|
814
|
-
|
|
815
|
-
const totalVariance = mode / numBuckets;
|
|
816
|
-
|
|
817
|
-
let perfectDist = 1 / numBuckets;
|
|
818
|
-
let testDist = perfectDist * 1.5;
|
|
819
|
-
|
|
820
|
-
Assert.ok(min > 0 && min <= testDist, min + ': Make sure that we have a good minimum distribution, perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
821
|
-
Assert.ok(max > 0 && max <= testDist, max + ': Make sure that we have a good maximum distribution, perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
822
|
-
Assert.ok(totalVariance > 0 && totalVariance <= testDist, totalVariance + ': Check the average distribution perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
823
|
-
}
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
this.testCase({
|
|
827
|
-
name: 'Test CoreUtils.mwcRandom32() randomness and distribution',
|
|
828
|
-
timeout: 15000,
|
|
829
|
-
test: () => {
|
|
830
|
-
let numBuckets = 100;
|
|
831
|
-
let buckets: number[] = _createBuckets(100);
|
|
832
|
-
let runs = 1000000;
|
|
833
|
-
|
|
834
|
-
for (let lp = 0; lp < runs; lp++) {
|
|
835
|
-
// Need to use floor otherwise the bucket is defined as a float as the index
|
|
836
|
-
const bucket = Math.floor((CoreUtils.mwcRandom32() / MaxInt32) * numBuckets);
|
|
837
|
-
buckets[bucket] ++;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
let min = 10;
|
|
841
|
-
let max = -1;
|
|
842
|
-
let mode = 0;
|
|
843
|
-
|
|
844
|
-
for (let lp = 0; lp < numBuckets; lp++) {
|
|
845
|
-
buckets[lp] /= runs;
|
|
846
|
-
mode += buckets[lp];
|
|
847
|
-
min = Math.min(min, buckets[lp]);
|
|
848
|
-
max = Math.max(max, buckets[lp]);
|
|
849
|
-
|
|
850
|
-
if (buckets[lp] === 0) {
|
|
851
|
-
Assert.ok(false, 'Bucket: ' + lp + ' is empty!');
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
Assert.equal(undefined, buckets[numBuckets], 'Make sure that we only allocated the correct number of buckets');
|
|
856
|
-
|
|
857
|
-
const totalVariance = mode / numBuckets;
|
|
858
|
-
|
|
859
|
-
let perfectDist = 1 / numBuckets;
|
|
860
|
-
let testDist = perfectDist * 1.5;
|
|
861
|
-
|
|
862
|
-
Assert.ok(min > 0 && min <= testDist, min + ': Make sure that we have a good minimum distribution, perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
863
|
-
Assert.ok(max > 0 && max <= testDist, max + ': Make sure that we have a good maximum distribution, perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
864
|
-
Assert.ok(totalVariance > 0 && totalVariance <= testDist, totalVariance + ': Check the average distribution perfect distribution is (1/bucketCount) = ' + perfectDist);
|
|
865
|
-
}
|
|
866
|
-
});
|
|
867
|
-
|
|
868
|
-
function _createBuckets(num: number) {
|
|
869
|
-
// Using helper function as TypeScript 2.5.3 is complaining about new Array<number>(100).fill(0);
|
|
870
|
-
let buckets: number[] = [];
|
|
871
|
-
for (let lp = 0; lp < num; lp++) {
|
|
872
|
-
buckets[lp] = 0;
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
return buckets;
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
function _checkNewId(idLen: number, newId: string, message: string) {
|
|
879
|
-
Assert.equal(idLen, newId.length, "[" + newId + "] - " + message);
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
class TestSamplingPlugin implements ITelemetryPlugin {
|
|
885
|
-
public processTelemetry: (env: ITelemetryItem) => void;
|
|
886
|
-
public initialize: (config: IConfiguration) => void;
|
|
887
|
-
public identifier: string = "AzureSamplingPlugin";
|
|
888
|
-
public setNextPlugin: (next: ITelemetryPlugin) => void;
|
|
889
|
-
public priority: number = 5;
|
|
890
|
-
public version = "1.0.31-Beta";
|
|
891
|
-
public nexttPlugin: ITelemetryPlugin;
|
|
892
|
-
private samplingPercentage;
|
|
893
|
-
private _validateItem = false;
|
|
894
|
-
|
|
895
|
-
constructor(validateItem: boolean = false) {
|
|
896
|
-
this.processTelemetry = this._processTelemetry.bind(this);
|
|
897
|
-
this.initialize = this._start.bind(this);
|
|
898
|
-
this.setNextPlugin = this._setNextPlugin.bind(this);
|
|
899
|
-
this._validateItem = validateItem;
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
private _processTelemetry(env: ITelemetryItem) {
|
|
903
|
-
if (!env) {
|
|
904
|
-
throw Error("Invalid telemetry object");
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
if (this._validateItem) {
|
|
908
|
-
Assert.ok(env.baseData);
|
|
909
|
-
Assert.ok(env.baseType);
|
|
910
|
-
Assert.ok(env.data);
|
|
911
|
-
Assert.ok(env.ext);
|
|
912
|
-
Assert.ok(env.tags);
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
private _start(config: IConfiguration) {
|
|
917
|
-
if (!config) {
|
|
918
|
-
throw Error("required configuration missing");
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
const pluginConfig = config.extensions ? config.extensions[this.identifier] : null;
|
|
922
|
-
this.samplingPercentage = pluginConfig ? pluginConfig.samplingPercentage : 100;
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
private _setNextPlugin(next: ITelemetryPlugin): void {
|
|
926
|
-
this.nexttPlugin = next;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
class ChannelPlugin implements IChannelControls {
|
|
931
|
-
public _nextPlugin: ITelemetryPlugin;
|
|
932
|
-
public isFlushInvoked = false;
|
|
933
|
-
public isUnloadInvoked = false;
|
|
934
|
-
public isTearDownInvoked = false;
|
|
935
|
-
public isResumeInvoked = false;
|
|
936
|
-
public isPauseInvoked = false;
|
|
937
|
-
public version: string = "1.0.33-Beta";
|
|
938
|
-
|
|
939
|
-
public processTelemetry;
|
|
940
|
-
|
|
941
|
-
public identifier = "Sender";
|
|
942
|
-
|
|
943
|
-
public priority: number = 1001;
|
|
944
|
-
|
|
945
|
-
constructor() {
|
|
946
|
-
this.processTelemetry = this._processTelemetry.bind(this);
|
|
947
|
-
}
|
|
948
|
-
public pause(): void {
|
|
949
|
-
this.isPauseInvoked = true;
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
public resume(): void {
|
|
953
|
-
this.isResumeInvoked = true;
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
public teardown(): void {
|
|
957
|
-
this.isTearDownInvoked = true;
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
flush(async?: boolean, callBack?: () => void): void {
|
|
961
|
-
this.isFlushInvoked = true;
|
|
962
|
-
if (callBack) {
|
|
963
|
-
callBack();
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
onunloadFlush(async?: boolean) {
|
|
968
|
-
this.isUnloadInvoked = true;
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
setNextPlugin(next: ITelemetryPlugin) {
|
|
972
|
-
this._nextPlugin = next;
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
public initialize = (config: IConfiguration) => {
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
public _processTelemetry(env: ITelemetryItem) {
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
class TestPlugin implements IPlugin {
|
|
983
|
-
public identifier: string = "TestPlugin";
|
|
984
|
-
public version: string = "1.0.31-Beta";
|
|
985
|
-
|
|
986
|
-
private _config: IConfiguration;
|
|
987
|
-
|
|
988
|
-
public initialize(config: IConfiguration) {
|
|
989
|
-
this._config = config;
|
|
990
|
-
// do custom one time initialization
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
class TrackPlugin implements IPlugin {
|
|
995
|
-
public identifier: string = "TrackPlugin";
|
|
996
|
-
public version: string = "1.0.31-Beta";
|
|
997
|
-
public priority = 2;
|
|
998
|
-
public _nextPlugin: ITelemetryPlugin;
|
|
999
|
-
public isInitialized: any;
|
|
1000
|
-
private _config: IConfiguration;
|
|
1001
|
-
|
|
1002
|
-
public initialize(config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[]) {
|
|
1003
|
-
this._config = config;
|
|
1004
|
-
core.track({ name: 'TestEvent1' });
|
|
1005
|
-
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
public setNextPlugin(next: ITelemetryPlugin) {
|
|
1009
|
-
this._nextPlugin = next;
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
public processTelemetry(evt: ITelemetryItem) {
|
|
1013
|
-
this._nextPlugin.processTelemetry(evt);
|
|
1014
|
-
}
|
|
1015
|
-
}
|