This commit is contained in:
siyuniu-ms 2024-08-06 15:20:57 -07:00
Родитель d93870910b 7e80e0a20e
Коммит cafb6acc0b
9 изменённых файлов: 147 добавлений и 13 удалений

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

@ -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

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

@ -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