Skip to content

Commit

Permalink
Enable support for reusing plugins in multiple instances of AppInsights
Browse files Browse the repository at this point in the history
  • Loading branch information
Nev Wylie committed Dec 19, 2019
1 parent f3ba52c commit db7bf82
Show file tree
Hide file tree
Showing 27 changed files with 1,296 additions and 551 deletions.
7 changes: 6 additions & 1 deletion AISKU/Tests/ApplicationInsightsDeprecatedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,12 @@ export class ApplicationInsightsDeprecatedTests extends TestClass {
if(this.successSpy.called) {
let currentCount: number = 0;
this.successSpy.args.forEach(call => {
currentCount += call[1];
call[0].forEach(message => {
// Ignore the internal SendBrowserInfoOnUserInit message (Only occurs when running tests in a browser)
if (message.indexOf("AI (Internal): 72 ") == -1) {
currentCount ++;
}
});
});
console.log('curr: ' + currentCount + ' exp: ' + expectedCount);
return currentCount === expectedCount;
Expand Down
37 changes: 30 additions & 7 deletions AISKU/Tests/applicationinsights.e2e.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ export class ApplicationInsightsTests extends TestClass {
// Assert.deepEqual(this._ai, window[this._aiName], `AI is available from window.${this._aiName}`);

Assert.ok(this._ai.appInsights, 'App Analytics exists');
Assert.equal(true, this._ai.appInsights['_isInitialized'], 'App Analytics is initialized');
Assert.equal(true, this._ai.appInsights.isInitialized(), 'App Analytics is initialized');


Assert.ok(this._ai.appInsights.core, 'Core exists');
Assert.equal(true, this._ai.appInsights.core['_isInitialized'],
Assert.equal(true, this._ai.appInsights.core.isInitialized(),
'Core is initialized');
}
});
Expand Down Expand Up @@ -318,7 +318,14 @@ export class ApplicationInsightsTests extends TestClass {
.concat(() => {
if (this.successSpy.called) {
const payloadStr: string[] = this.successSpy.args[0][0];
Assert.equal(1, payloadStr.length, 'Only 1 track item is sent');
let payloadItems = 0;
payloadStr.forEach(message => {
// Ignore the internal SendBrowserInfoOnUserInit message (Only occurs when running tests in a browser)
if (message.indexOf("AI (Internal): 72 ") == -1) {
payloadItems ++;
}
});
Assert.equal(1, payloadItems, 'Only 1 track item is sent');
const payload = JSON.parse(payloadStr[0]);
Assert.ok(payload);

Expand Down Expand Up @@ -536,12 +543,23 @@ export class ApplicationInsightsTests extends TestClass {
.concat(this.asserts(1))
.concat(PollingAssert.createPollingAssert(() => {
if (this.successSpy.called) {
const payloadStr: string[] = this.successSpy.args[0][0];
if (payloadStr.length !== 1) {
let thePayload:string = null;
let payloadEvents = 0;
this.successSpy.args.forEach(call => {
call[0].forEach(payloadStr => {
// Ignore the internal SendBrowserInfoOnUserInit message (Only occurs when running tests in a browser)
if (payloadStr.indexOf("AI (Internal): 72 ") == -1) {
thePayload = payloadStr;
payloadEvents ++;
}
});
});

if (payloadEvents !== 1) {
// Only 1 track should be sent
return false;
}
const payload = JSON.parse(payloadStr[0]);
const payload = JSON.parse(thePayload);
if (payload && payload.tags) {
const tagName: string = this.tagKeys.userAuthUserId;
return '10001' === payload.tags[tagName];
Expand Down Expand Up @@ -701,7 +719,12 @@ export class ApplicationInsightsTests extends TestClass {
if (this.successSpy.called) {
let currentCount: number = 0;
this.successSpy.args.forEach(call => {
currentCount += call[1];
call[0].forEach(message => {
// Ignore the internal SendBrowserInfoOnUserInit message (Only occurs when running tests in a browser)
if (message.indexOf("AI (Internal): 72 ") == -1) {
currentCount ++;
}
});
});
console.log('curr: ' + currentCount + ' exp: ' + expectedCount, ' appId: ' + this._ai.context.appId());
if (currentCount === expectedCount && !!this._ai.context.appId()) {
Expand Down
11 changes: 10 additions & 1 deletion AISKU/Tests/validate.e2e.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,16 @@ export class ValidateE2ETests extends TestClass {
.concat(this.waitForResponse())
.concat(this.boilerPlateAsserts)
.concat(() => {
const acceptedItems = this.successSpy.args[0][1];
let acceptedItems = 0;
this.successSpy.args.forEach(call => {
call[0].forEach(message => {
// Ignore the internal SendBrowserInfoOnUserInit message (Only occurs when running tests in a browser)
if (message.indexOf("AI (Internal): 72 ") == -1) {
acceptedItems ++;
}
});
});

Assert.equal(4, acceptedItems, "backend should accept all four events");
})
});
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,17 @@ Here is the priority ranges available:
- Priorty range < 201 is reserved.
- Priority range > 1000 is for channels (advanced scenario)

[BaseTelemetryPlugin](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK/BaseTelemetryPlugin.ts)

To help with the creation of new extensions there is now a supported base class which can be used, this not only provides the common (boilerplate) implementations of common functions it will enable future plugins to automatically receive functional updates with the need to recode the plugins. it provides implementations for :-
* [ITelemetryPlugin.setNextPlugin()](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts) implementation to continuing supporting existing (non-shared) execution of plugins, however, new plugins should use the new [IProcessTelemetryContext.processNext()](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IProcessTelemetryContext.ts) moving forward as this support the creation of shared (singleton) plugins;
* New [ITelemetryPlugin.isInitialized()](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts) implementation
* And several helper methods.
* [processNext()](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK/BaseTelemetryPlugin.ts), - to call the next plugin using the context or the _nextPlugin value
* [diagLog()](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK/BaseTelemetryPlugin.ts): - to access the current [IDiagnosticLogger](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IDiagnosticLogger.ts) instance.

If you are creating new extensions it is recommended that you extend from this base class so that your extension will automatically inherit any future enhancements that are added to the ITelemetryPlugin interface without it requiring updates.

Usage:

```ts
Expand Down
20 changes: 10 additions & 10 deletions channels/applicationinsights-channel-js/Tests/Sender.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ export class SenderTests extends TestClass {
}, new AppInsightsCore(), []
);

Assert.equal(123, this._sender._config.maxBatchInterval(), 'Channel config can be set from root config (maxBatchInterval)');
Assert.equal('https://example.com', this._sender._config.endpointUrl(), 'Channel config can be set from root config (endpointUrl)');
Assert.notEqual(654, this._sender._config.maxBatchSizeInBytes(), 'Channel config does not equal root config option if extensionConfig field is also set');
Assert.equal(456, this._sender._config.maxBatchSizeInBytes(), 'Channel config prioritizes extensionConfig over root config');
Assert.equal(123, this._sender._senderConfig.maxBatchInterval(), 'Channel config can be set from root config (maxBatchInterval)');
Assert.equal('https://example.com', this._sender._senderConfig.endpointUrl(), 'Channel config can be set from root config (endpointUrl)');
Assert.notEqual(654, this._sender._senderConfig.maxBatchSizeInBytes(), 'Channel config does not equal root config option if extensionConfig field is also set');
Assert.equal(456, this._sender._senderConfig.maxBatchSizeInBytes(), 'Channel config prioritizes extensionConfig over root config');
}
});

Expand All @@ -60,7 +60,7 @@ export class SenderTests extends TestClass {
baseData: {}
};
try {
this._sender.processTelemetry(telemetryItem);
this._sender.processTelemetry(telemetryItem, null);
} catch(e) {
Assert.ok(false);
}
Expand All @@ -86,7 +86,7 @@ export class SenderTests extends TestClass {
};
this._sender.setNextPlugin(nextPlugin);

const processTelemetrySpy = this.sandbox.stub((this._sender as any)._nextPlugin, "processTelemetry");
const processTelemetrySpy = this.sandbox.stub(nextPlugin, "processTelemetry");
const telemetryItem: ITelemetryItem = {
name: 'fake item',
iKey: 'iKey',
Expand All @@ -98,7 +98,7 @@ export class SenderTests extends TestClass {

telemetryItem.tags["ProcessLegacy"] = [e => true, e => false, f=> true];
try {
this._sender.processTelemetry(telemetryItem);
this._sender.processTelemetry(telemetryItem, null);
} catch(e) {
Assert.ok(false);
}
Expand Down Expand Up @@ -136,7 +136,7 @@ export class SenderTests extends TestClass {
Assert.ok(xhrSenderSpy.notCalled, "xhr sender was not called before");

try {
sender.processTelemetry(telemetryItem);
sender.processTelemetry(telemetryItem, null);
sender.flush();
} catch(e) {
Assert.ok(false);
Expand Down Expand Up @@ -177,7 +177,7 @@ export class SenderTests extends TestClass {
Assert.ok(xhrSenderSpy.notCalled, "xhr sender was not called before");

try {
sender.processTelemetry(telemetryItem);
sender.processTelemetry(telemetryItem, null);
sender.flush();
} catch(e) {
Assert.ok(false);
Expand Down Expand Up @@ -231,7 +231,7 @@ export class SenderTests extends TestClass {

try {
for (let i = 0; i < 8; i++) {
sender.processTelemetry(telemetryItems[i]);
sender.processTelemetry(telemetryItems[i], null);
}
sender.flush();
} catch(e) {
Expand Down

0 comments on commit db7bf82

Please sign in to comment.