[BUG] address issues #1517 add unload listener and #1524 config from snippet (#1532)

* bug fix - add unload listener and initialize missing config items

* remove unnecessary initializations and pass in config to getDefault method

* add correlationHeaderExcludePatterns default value

* fix test
This commit is contained in:
Xiao Li 2021-04-16 14:19:13 -07:00 коммит произвёл GitHub
Родитель 1c39bf97fa
Коммит ababc00b43
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 135 добавлений и 6 удалений

Просмотреть файл

@ -485,6 +485,7 @@ export class Initialization implements IApplicationInsights {
// Hook the unload event for the document, window and body to ensure that the client events are flushed to the server
// As just hooking the window does not always fire (on chrome) for page navigations.
let added = addEventHandler('beforeunload', performHousekeeping);
added = addEventHandler('unload', performHousekeeping) || added;
added = addEventHandler('pagehide', performHousekeeping) || added;
// A reactNative app may not have a window and therefore the beforeunload/pagehide events -- so don't

Просмотреть файл

@ -253,7 +253,7 @@ export class ApplicationInsightsTests extends AITestClass {
Assert.equal(12, appInsights.config.samplingPercentage);
Assert.notEqual('aaa', appInsights.config.accountId);
Assert.equal('def', appInsights.config.accountId);
Assert.equal(undefined, (appInsights['config'] as IConfiguration).instrumentationKey);
Assert.equal('instrumentation_key', (appInsights['config'] as IConfiguration).instrumentationKey);
Assert.equal(30 * 60 * 1000, appInsights.config.sessionRenewalMs);
Assert.equal(24 * 60 * 60 * 1000, appInsights.config.sessionExpirationMs);
@ -262,7 +262,7 @@ export class ApplicationInsightsTests extends AITestClass {
Assert.equal(12, extConfig.samplingPercentage);
Assert.notEqual('aaa', extConfig.accountId);
Assert.equal('def', extConfig.accountId);
Assert.equal(undefined, (extConfig as any).instrumentationKey);
Assert.equal('instrumentation_key', (extConfig as any).instrumentationKey);
Assert.equal(30 * 60 * 1000, extConfig.sessionRenewalMs);
Assert.equal(24 * 60 * 60 * 1000, extConfig.sessionExpirationMs);
}

Просмотреть файл

@ -76,6 +76,10 @@ export class ApplicationInsights extends BaseTelemetryPlugin implements IAppInsi
config.enableAutoRouteTracking = stringToBoolOrDefault(config.enableAutoRouteTracking);
config.namePrefix = config.namePrefix || "";
config.enableDebug = stringToBoolOrDefault(config.enableDebug);
config.disableFlushOnBeforeUnload = stringToBoolOrDefault(config.disableFlushOnBeforeUnload);
config.disableFlushOnUnload = stringToBoolOrDefault(config.disableFlushOnUnload, config.disableFlushOnBeforeUnload);
return config;
}
@ -498,7 +502,7 @@ export class ApplicationInsights extends BaseTelemetryPlugin implements IAppInsi
_self.config = ctx.getExtCfg<IConfig>(identifier);
// load default values if specified
const defaults: IConfig = ApplicationInsights.getDefaultConfig();
const defaults: IConfig = ApplicationInsights.getDefaultConfig(config);
if (defaults !== undefined) {
objForEachKey(defaults, (field, value) => {
// for each unspecified field, set the default value
@ -915,7 +919,7 @@ class Timing {
if (typeof _events[name] !== "undefined") {
logger.throwInternal(
LoggingSeverity.WARNING, _InternalMessageId.StartCalledMoreThanOnce, "start was called more than once for this event without calling stop.",
{ name: name, key: name }, true);
{ name, key: name }, true);
}
_events[name] = +new Date;
@ -926,7 +930,7 @@ class Timing {
if (isNaN(start)) {
logger.throwInternal(
LoggingSeverity.WARNING, _InternalMessageId.StopCalledWithoutStart, "stop was called without a corresponding start.",
{ name: name, key: name }, true);
{ name, key: name }, true);
} else {
const end = +new Date;
const duration = dateTimeUtilsDuration(start, end);

Просмотреть файл

@ -1491,7 +1491,46 @@ export class AjaxTests extends TestClass {
Assert.equal("|", id[0]);
Assert.equal(".", id[id.length - 1]);
}
})
});
this.testCase({
name: "Ajax: should not create and pass a traceparent header if correlationHeaderExcludePatterns set to exclude all",
test: () => {
this._ajax = new AjaxMonitor();
let appInsightsCore = new AppInsightsCore();
let coreConfig = {
instrumentationKey: "instrumentationKey",
correlationHeaderExcludePatterns: [/.*/],
extensionConfig: {
"AjaxDependencyPlugin": {
appId: "appId",
distributedTracingMode: DistributedTracingModes.AI_AND_W3C
}
}
};
appInsightsCore.initialize(coreConfig, [this._ajax, new TestChannelPlugin()]);
var trackStub = this.sandbox.stub(appInsightsCore, "track");
// Use test hook to simulate the correct url location
this._ajax["_currentWindowHost"] = "www.example.com";
// Act
var xhr = new XMLHttpRequest();
var stub = this.sandbox.stub(xhr, "setRequestHeader");
xhr.open("GET", "http://www.example.com");
xhr.send();
// Assert that both headers are not sent
Assert.equal(false, stub.calledWith(RequestHeaders.requestIdHeader)); // AI
Assert.equal(false, stub.calledWith(RequestHeaders.traceParentHeader)); // W3C
// Emulate response so perf monitoring is cleaned up
(<any>xhr).respond(200, {"Content-Type": "application/json; charset=utf-8", "Access-Control-Allow-Origin": "*"}, "");
var id = trackStub.args[0][0].baseData.id;
Assert.equal("|", id[0]);
Assert.equal(".", id[id.length - 1]);
}
});
this.testCase({
name: "Ajax: should create and only pass a traceparent header if w3c is enabled",
@ -2096,6 +2135,90 @@ export class AjaxPerfTests extends TestClass {
return false;
}, 'response received', 600, 1000) as any)
});
this.testCaseAsync({
name: "Fetch: should not create and pass correlation header if correlationHeaderExcludePatterns set to exclude all.",
stepDelay: 10,
timeOut: 10000,
steps: [ (done) => {
let fetchCalls = hookFetch((resolve) => {
TestClass.orgSetTimeout(function() {
resolve({
headers: new Headers(),
ok: true,
body: null,
bodyUsed: false,
redirected: false,
status: 200,
statusText: "Hello",
trailer: null,
type: "basic",
url: "https://httpbin.org/status/200"
});
}, 0);
});
this._ajax = new AjaxMonitor();
let appInsightsCore = new AppInsightsCore();
let coreConfig = {
instrumentationKey: "instrumentationKey",
disableFetchTracking: false,
disableAjaxTracking: false,
correlationHeaderExcludePatterns: [/.*/],
extensionConfig: {
"AjaxDependencyPlugin": {
appId: "appId",
distributedTracingMode: DistributedTracingModes.AI_AND_W3C
}
}
};
appInsightsCore.initialize(coreConfig, [this._ajax, new TestChannelPlugin()]);
let trackSpy = this.sandbox.spy(appInsightsCore, "track")
this._context["trackStub"] = trackSpy;
// Use test hook to simulate the correct url location
this._ajax["_currentWindowHost"] = "httpbin.org";
// Setup
let headers = new Headers();
headers.append('My-Header', 'Header field');
let init = {
method: 'get',
headers
};
const url = 'https://httpbin.org/status/200';
// Act
Assert.ok(trackSpy.notCalled, "No fetch called yet");
fetch(url, init).then(() => {
// Assert
Assert.ok(trackSpy.called, "The request was not tracked");
Assert.equal(1, fetchCalls.length);
Assert.notEqual(undefined, fetchCalls[0].init, "Has init param");
let headers:Headers = fetchCalls[0].init.headers as Headers;
Assert.equal(true, headers.has("My-Header"), "My-Header should be present");
Assert.equal(false, headers.has(RequestHeaders.requestIdHeader), "Correlation header - AI header should be excluded"); // AI
Assert.equal(false, headers.has(RequestHeaders.traceParentHeader), "Correlation header - W3c header should be excluded"); // W3C
}, () => {
Assert.ok(false, "fetch failed!");
done();
});
}]
.concat(PollingAssert.createPollingAssert(() => {
let trackStub = this._context["trackStub"] as SinonStub;
if (trackStub.called) {
Assert.ok(trackStub.calledOnce, "track is called");
let data = trackStub.args[0][0].baseData;
Assert.equal("Fetch", data.type, "request is Fatch type");
var id = data.id;
Assert.equal("|", id[0]);
Assert.equal(".", id[id.length - 1]);
return true;
}
return false;
}, 'response received', 60, 1000) as any)
})
}
}

Просмотреть файл

@ -163,6 +163,7 @@ export class AjaxMonitor extends BaseTelemetryPlugin implements IDependenciesPlu
"*.blob.core.cloudapi.de",
"*.blob.core.usgovcloudapi.net"],
correlationHeaderDomains: undefined,
correlationHeaderExcludePatterns: undefined,
appId: undefined,
enableCorsCorrelation: false,
enableRequestHeaderTracking: false,