[main] enhance exception telemetry with optional script Information (#2388)
This commit is contained in:
Родитель
68fd1c92be
Коммит
f39a8151d5
|
@ -396,6 +396,8 @@ Most configuration fields are named such that they can be defaulted to falsey. A
|
|||
| featureOptIn <br/><sub>since 3.0.3</sub> | IFeatureOptIn | undefined | [Optional] Set Feature opt in details. |
|
||||
| throttleMgrCfg <br/><sub>since 3.0.3</sub> | `{[key: number]: IThrottleMgrConfig}` | undefined | [Optional] Set throttle mgr configuration by key. |
|
||||
| retryCodes | number[] | undefined | Identifies the status codes that will cause event batches to be resent, when `null` or `undefined` the SDK will use it's defaults `[401, 408, 429, 500, 502, 503, 504]`. `403` was removed in version 3.1.1. |
|
||||
| expCfg | [`IExceptionConfig`](https://github.com/microsoft/ApplicationInsights-JS/blob/main/shared/AppInsightsCommon/src/Interfaces/IExceptionTelemetry.ts) | undefined | Set additional configuration for exceptions, such as more scripts to include in the exception telemetry. |
|
||||
|
||||
|
||||
### ExtensionConfig
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ export interface IChannelConfiguration {
|
|||
* - "same-origin": only send and include credentials for same-origin requests.
|
||||
*
|
||||
* If not set, the default value will be "include".
|
||||
*
|
||||
*
|
||||
* For more information, refer to:
|
||||
* - [Fetch API - Using Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#including_credentials)
|
||||
* @since 3.3.1
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
Exception, SeverityLevel, Event, Trace, PageViewPerformance, IConfig, IExceptionInternal,
|
||||
AnalyticsPluginIdentifier, IAppInsights, Metric, PageView, RemoteDependencyData, utlCanUseLocalStorage, createDomEvent
|
||||
} from "@microsoft/applicationinsights-common";
|
||||
import { ITelemetryItem, AppInsightsCore, IPlugin, IConfiguration, IAppInsightsCore, setEnableEnvMocks, getLocation, dumpObj, __getRegisteredEvents, createCookieMgr } from "@microsoft/applicationinsights-core-js";
|
||||
import { ITelemetryItem, AppInsightsCore, IPlugin, IConfiguration, IAppInsightsCore, setEnableEnvMocks, getLocation, dumpObj, __getRegisteredEvents, createCookieMgr, findAllScripts } from "@microsoft/applicationinsights-core-js";
|
||||
import { Sender } from "@microsoft/applicationinsights-channel-js"
|
||||
import { PropertiesPlugin } from "@microsoft/applicationinsights-properties-js";
|
||||
import { AnalyticsPlugin } from "../../../src/JavaScriptSDK/AnalyticsPlugin";
|
||||
|
@ -406,6 +406,76 @@ export class AnalyticsPluginTests extends AITestClass {
|
|||
this.addOnErrorTests();
|
||||
this.addTrackMetricTests();
|
||||
this.addTelemetryInitializerTests();
|
||||
this.addScriptInfoTests();
|
||||
}
|
||||
|
||||
private addScriptInfoTests(): void {
|
||||
this.testCase({
|
||||
name: "AppInsightsTests: findAllScripts function returns correct information",
|
||||
useFakeTimers: true,
|
||||
test: () => {
|
||||
// Initialize Application Insights core with plugins
|
||||
let script = window.document.createElement("script");
|
||||
script.src = "https://www.example.com/test.js";
|
||||
script.innerHTML = 'test script';
|
||||
window.document.body.appendChild(script);
|
||||
|
||||
let doc = window.document;
|
||||
let scriptsInfo = findAllScripts(doc);
|
||||
Assert.deepEqual(true, JSON.stringify(scriptsInfo).indexOf("https://www.example.com/test.js") !== -1, "script info contains the correct url");
|
||||
}
|
||||
});
|
||||
this.testCase({
|
||||
name: "AppInsightsTests: trackException would contain scrips info when config turns on",
|
||||
useFakeTimers: true,
|
||||
test: () => {
|
||||
const appInsights = new AnalyticsPlugin();
|
||||
const core = new AppInsightsCore();
|
||||
const channel = new ChannelPlugin();
|
||||
const properties = new PropertiesPlugin();
|
||||
// Configuration
|
||||
const config = {
|
||||
instrumentationKey: 'ikey',
|
||||
};
|
||||
this.onDone(() => {
|
||||
core.unload(false);
|
||||
});
|
||||
// Initialize Application Insights core with plugins
|
||||
core.initialize(config, [appInsights, channel, properties]);
|
||||
|
||||
// add test script
|
||||
let script = window.document.createElement("script");
|
||||
script.src = "https://www.example1.com/test.js";
|
||||
script.setAttribute("referrerpolicy", "no-referrer");
|
||||
script.innerHTML = 'test script';
|
||||
let script2 = window.document.createElement("script");
|
||||
script2.src = "https://www.test.com/test.js";
|
||||
script2.innerHTML = "test tests";
|
||||
script2.setAttribute("async", "");
|
||||
window.document.body.appendChild(script);
|
||||
window.document.body.appendChild(script2);
|
||||
|
||||
|
||||
const trackStub = this.sandbox.stub(appInsights.core, "track");
|
||||
appInsights.trackException({error: new Error(), severityLevel: SeverityLevel.Critical});
|
||||
Assert.ok(trackStub.calledOnce, "single exception is tracked");
|
||||
const baseData = (trackStub.args[0][0] as ITelemetryItem).baseData as IExceptionInternal;
|
||||
const prop = baseData.properties;
|
||||
Assert.equal(-1, JSON.stringify(prop).indexOf("https://www.example.com/test.js"), "script info is not included");
|
||||
|
||||
appInsights.config.expCfg.inclScripts = true;
|
||||
this.clock.tick(1);
|
||||
appInsights.trackException({error: new Error(), severityLevel: SeverityLevel.Critical});
|
||||
Assert.ok(trackStub.calledTwice, "single exception is tracked");
|
||||
const baseData2 = (trackStub.args[1][0] as ITelemetryItem).baseData as IExceptionInternal;
|
||||
const prop2 = baseData2.properties;
|
||||
Assert.deepEqual(true, prop2["exceptionScripts"].includes('"url":"https://www.test.com/test.js","async":true}'))
|
||||
Assert.deepEqual(true, prop2["exceptionScripts"].includes('"url":"https://www.example1.com/test.js","referrerPolicy":"no-referrer"'))
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
private addGenericTests(): void {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import dynamicProto from "@microsoft/dynamicproto-js";
|
||||
import {
|
||||
AnalyticsPluginIdentifier, Event as EventTelemetry, Exception, IAppInsights, IAutoExceptionTelemetry, IConfig, IDependencyTelemetry,
|
||||
IEventTelemetry, IExceptionInternal, IExceptionTelemetry, IMetricTelemetry, IPageViewPerformanceTelemetry,
|
||||
IEventTelemetry, IExceptionConfig, IExceptionInternal, IExceptionTelemetry, IMetricTelemetry, IPageViewPerformanceTelemetry,
|
||||
IPageViewPerformanceTelemetryInternal, IPageViewTelemetry, IPageViewTelemetryInternal, ITraceTelemetry, Metric, PageView,
|
||||
PageViewPerformance, PropertiesPluginIdentifier, RemoteDependencyData, Trace, createDistributedTraceContextFromTrace, createDomEvent,
|
||||
createTelemetryItem, dataSanitizeString, eSeverityLevel, isCrossOriginError, strNotSpecified, utlDisableStorage, utlEnableStorage,
|
||||
|
@ -16,9 +16,10 @@ import {
|
|||
BaseTelemetryPlugin, IAppInsightsCore, IConfigDefaults, IConfiguration, ICookieMgr, ICustomProperties, IDistributedTraceContext,
|
||||
IInstrumentCallDetails, IPlugin, IProcessTelemetryContext, IProcessTelemetryUnloadContext, ITelemetryInitializerHandler, ITelemetryItem,
|
||||
ITelemetryPluginChain, ITelemetryUnloadState, InstrumentEvent, TelemetryInitializerFunction, _eInternalMessageId, arrForEach,
|
||||
cfgDfBoolean, cfgDfSet, cfgDfString, cfgDfValidate, createProcessTelemetryContext, createUniqueNamespace, dumpObj, eLoggingSeverity,
|
||||
eventOff, eventOn, generateW3CId, getDocument, getExceptionName, getHistory, getLocation, getWindow, hasHistory, hasWindow, isFunction,
|
||||
isNullOrUndefined, isString, isUndefined, mergeEvtNamespace, onConfigChange, safeGetCookieMgr, strUndefined, throwError
|
||||
cfgDfBoolean, cfgDfMerge, cfgDfSet, cfgDfString, cfgDfValidate, createProcessTelemetryContext, createUniqueNamespace, dumpObj,
|
||||
eLoggingSeverity, eventOff, eventOn, findAllScripts, generateW3CId, getDocument, getExceptionName, getHistory, getLocation, getWindow,
|
||||
hasHistory, hasWindow, isFunction, isNullOrUndefined, isString, isUndefined, mergeEvtNamespace, onConfigChange, safeGetCookieMgr,
|
||||
strUndefined, throwError
|
||||
} from "@microsoft/applicationinsights-core-js";
|
||||
import { PropertiesPlugin } from "@microsoft/applicationinsights-properties-js";
|
||||
import { isError, objDeepFreeze, objDefine, scheduleTimeout, strIndexOf } from "@nevware21/ts-utils";
|
||||
|
@ -66,7 +67,8 @@ const defaultValues: IConfigDefaults<IConfig> = objDeepFreeze({
|
|||
namePrefix: cfgDfString(),
|
||||
enableDebug: cfgDfBoolean(),
|
||||
disableFlushOnBeforeUnload: cfgDfBoolean(),
|
||||
disableFlushOnUnload: cfgDfBoolean(false, "disableFlushOnBeforeUnload")
|
||||
disableFlushOnUnload: cfgDfBoolean(false, "disableFlushOnBeforeUnload"),
|
||||
expCfg: cfgDfMerge<IExceptionConfig>({inclScripts: false})
|
||||
});
|
||||
|
||||
function _chkConfigMilliseconds(value: number, defValue: number): number {
|
||||
|
@ -422,7 +424,11 @@ export class AnalyticsPlugin extends BaseTelemetryPlugin implements IAppInsights
|
|||
exception.severityLevel,
|
||||
exception.id
|
||||
).toInterface();
|
||||
|
||||
var doc = getDocument();
|
||||
if (doc && _self.config.expCfg?.inclScripts) {
|
||||
var scriptsInfo = findAllScripts(doc);
|
||||
exceptionPartB.properties["exceptionScripts"] = JSON.stringify(scriptsInfo);
|
||||
}
|
||||
let telemetryItem: ITelemetryItem = createTelemetryItem<IExceptionInternal>(
|
||||
exceptionPartB,
|
||||
Exception.dataType,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
import { IConfiguration, ICustomProperties, isNullOrUndefined } from "@microsoft/applicationinsights-core-js";
|
||||
import { DistributedTracingModes } from "../Enums";
|
||||
import { IExceptionConfig } from "./IExceptionTelemetry";
|
||||
import { IRequestContext } from "./IRequestContext";
|
||||
import { IStorageBuffer } from "./IStorageBuffer";
|
||||
import { IThrottleMgrConfig } from "./IThrottleMgr";
|
||||
|
@ -389,6 +390,11 @@ export interface IConfig {
|
|||
* This URL takes precedence over the 'config.endpointUrl' and any endpoint in the connection string.
|
||||
*/
|
||||
userOverrideEndpointUrl?: string;
|
||||
|
||||
/**
|
||||
* [Optional] Set additional configuration for exceptions, such as more scripts to include in the exception telemetry.
|
||||
*/
|
||||
expCfg?: IExceptionConfig;
|
||||
}
|
||||
|
||||
export class ConfigurationManager {
|
||||
|
|
|
@ -4,6 +4,14 @@
|
|||
import { SeverityLevel } from "./Contracts/SeverityLevel";
|
||||
import { IPartC } from "./IPartC";
|
||||
|
||||
export interface IExceptionConfig{
|
||||
/**
|
||||
* If set to true, when exception is sent out, the SDK will also send out all scripts basic info that are loaded on the page.
|
||||
* Notice: This would increase the size of the exception telemetry.
|
||||
*/
|
||||
inclScripts?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @interface IExceptionTelemetry
|
||||
|
|
|
@ -26,7 +26,7 @@ export { IEventTelemetry } from "./Interfaces/IEventTelemetry";
|
|||
export { ITraceTelemetry } from "./Interfaces/ITraceTelemetry";
|
||||
export { IMetricTelemetry } from "./Interfaces/IMetricTelemetry";
|
||||
export { IDependencyTelemetry } from "./Interfaces/IDependencyTelemetry";
|
||||
export { IExceptionTelemetry, IAutoExceptionTelemetry, IExceptionInternal } from "./Interfaces/IExceptionTelemetry";
|
||||
export { IExceptionTelemetry, IAutoExceptionTelemetry, IExceptionInternal, IExceptionConfig } from "./Interfaces/IExceptionTelemetry";
|
||||
export { IPageViewTelemetry, IPageViewTelemetryInternal } from "./Interfaces/IPageViewTelemetry";
|
||||
export { IPageViewPerformanceTelemetry, IPageViewPerformanceTelemetryInternal } from "./Interfaces/IPageViewPerformanceTelemetry";
|
||||
export { Trace } from "./Telemetry/Trace";
|
||||
|
@ -64,7 +64,7 @@ export { eDistributedTracingModes, DistributedTracingModes, EventPersistence } f
|
|||
export { stringToBoolOrDefault, msToTimeSpan, getExtensionByName, isCrossOriginError } from "./HelperFuncs";
|
||||
export {
|
||||
isBeaconsSupported as isBeaconApiSupported,
|
||||
ITraceParent, createTraceParent, parseTraceParent, isValidTraceId, isValidSpanId, isValidTraceParent, isSampledFlag, formatTraceParent, findW3cTraceParent
|
||||
ITraceParent, createTraceParent, parseTraceParent, isValidTraceId, isValidSpanId, isValidTraceParent, isSampledFlag, formatTraceParent, findW3cTraceParent, findAllScripts
|
||||
} from "@microsoft/applicationinsights-core-js";
|
||||
export { createDomEvent } from "./DomHelperFuncs";
|
||||
export {
|
||||
|
|
|
@ -4,8 +4,8 @@ import * as pako from "pako";
|
|||
export class AppInsightsCoreSizeCheck extends AITestClass {
|
||||
private readonly MAX_RAW_SIZE = 65;
|
||||
private readonly MAX_BUNDLE_SIZE = 65;
|
||||
private readonly MAX_RAW_DEFLATE_SIZE = 27;
|
||||
private readonly MAX_BUNDLE_DEFLATE_SIZE = 27;
|
||||
private readonly MAX_RAW_DEFLATE_SIZE = 28;
|
||||
private readonly MAX_BUNDLE_DEFLATE_SIZE = 28;
|
||||
private readonly rawFilePath = "../dist/es5/applicationinsights-core-js.min.js";
|
||||
private readonly prodFilePath = "../browser/es5/applicationinsights-core-js.min.js";
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { isArray, isString, strLeft, strTrim } from "@nevware21/ts-utils";
|
||||
import { arrForEach, isArray, isString, strLeft, strTrim } from "@nevware21/ts-utils";
|
||||
import { ITraceParent } from "../JavaScriptSDK.Interfaces/ITraceParent";
|
||||
import { generateW3CId } from "./CoreUtils";
|
||||
import { findMetaTag, findNamedServerTiming } from "./EnvUtils";
|
||||
|
@ -202,3 +202,45 @@ export function findW3cTraceParent(selectIdx?: number): ITraceParent {
|
|||
|
||||
return traceParent;
|
||||
}
|
||||
|
||||
export interface scriptsInfo {
|
||||
url: string;
|
||||
crossOrigin?: string;
|
||||
async?: boolean;
|
||||
defer?: boolean;
|
||||
referrerPolicy?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all script tags in the provided document and return the information about them.
|
||||
* @param doc
|
||||
* @returns
|
||||
*/
|
||||
export function findAllScripts(doc: any) {
|
||||
let scripts = doc.getElementsByTagName("script");
|
||||
let result: scriptsInfo[] = [];
|
||||
arrForEach(scripts, (script: any) => {
|
||||
let src = script.getAttribute("src");
|
||||
if (src) {
|
||||
let crossOrigin = script.getAttribute("crossorigin");
|
||||
let async = script.hasAttribute("async") === true;
|
||||
let defer = script.hasAttribute("defer") === true;
|
||||
let referrerPolicy = script.getAttribute("referrerpolicy");
|
||||
let info: scriptsInfo = { url: src };
|
||||
if (crossOrigin) {
|
||||
info.crossOrigin = crossOrigin;
|
||||
}
|
||||
if (async) {
|
||||
info.async = async;
|
||||
}
|
||||
if (defer) {
|
||||
info.defer = defer;
|
||||
}
|
||||
if (referrerPolicy) {
|
||||
info.referrerPolicy = referrerPolicy;
|
||||
}
|
||||
result.push(info);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ export { ITelemetryUnloadState } from "./JavaScriptSDK.Interfaces/ITelemetryUnlo
|
|||
export { IDistributedTraceContext } from "./JavaScriptSDK.Interfaces/IDistributedTraceContext";
|
||||
export { ITraceParent } from "./JavaScriptSDK.Interfaces/ITraceParent";
|
||||
export {
|
||||
createTraceParent, parseTraceParent, isValidTraceId, isValidSpanId, isValidTraceParent, isSampledFlag, formatTraceParent, findW3cTraceParent
|
||||
createTraceParent, parseTraceParent, isValidTraceId, isValidSpanId, isValidTraceParent, isSampledFlag, formatTraceParent, findW3cTraceParent, findAllScripts
|
||||
} from "./JavaScriptSDK/W3cTraceParent";
|
||||
|
||||
// Dynamic Config definitions
|
||||
|
|
Загрузка…
Ссылка в новой задаче