@airwallex/airtracker
Advanced tools
Comparing version
import { DEFAULT_COMMON_DATA, DEFAULT_CONFIG, UNKNOWN_VALUE } from './constant/config'; | ||
import { createPipeline, sendNormalLogPipe, throttlePipe, errorLogLimitPipe } from './pipes/index'; | ||
import { generateUId, getDeviceId, getNetworkType, getPlatform } from './util/index'; | ||
import { generateUId, getDeviceId, getMFEName, getNetworkType, getPlatform } from './util/index'; | ||
import { EventEmitter } from './util/eventEmitter'; | ||
@@ -9,2 +9,3 @@ import { lifeCycleEventName, NetworkType, SeverityType } from './constant'; | ||
import { assetSpeedPlugin } from './plugins/assetsSpeedPlugin'; | ||
import { onPageChangePlugin } from './plugins/onPageChangePlugin'; | ||
export default class AirTracker { | ||
@@ -18,16 +19,12 @@ constructor({ config, plugins = [] }) { | ||
this.timeMap = {}; | ||
this.detectHrefChange = () => { | ||
let previousUrl = location.href; | ||
// eslint-disable-next-line @typescript-eslint/no-this-alias | ||
const that = this; | ||
const observer = new MutationObserver(function () { | ||
if (location.href !== previousUrl) { | ||
previousUrl = location.href; | ||
that.updateCommonData({ currentHref: location.href }); | ||
} | ||
}); | ||
const config = { subtree: true, childList: true }; | ||
observer.observe(document, config); | ||
this.normalPipelineObj = createPipeline([throttlePipe(this, 5), errorLogLimitPipe(this), sendNormalLogPipe(this)]); | ||
this.normalLogPipeLine = ({ severity, eventName, extraInfo, }) => { | ||
const packedData = Object.assign({ severity, | ||
eventName, currentHref: (location === null || location === void 0 ? void 0 : location.href) || 'unknown href' }, extraInfo); | ||
// if isWebappContainer, the MFE name will be assigned | ||
if (this.config.isWebappContainer) { | ||
packedData.MFEName = getMFEName(); | ||
} | ||
return this.normalPipelineObj(packedData); | ||
}; | ||
this.normalLogPipeLine = createPipeline([throttlePipe(this, 5), errorLogLimitPipe(this), sendNormalLogPipe(this)]); | ||
this.plugins = [...plugins]; | ||
@@ -37,3 +34,2 @@ this.setConfig(config); | ||
this.lifeCycle.emit(lifeCycleEventName.onInit); | ||
this.detectHrefChange(); | ||
// if allow enableErrorMonitoring, then enable errorDetectionPlugin | ||
@@ -46,5 +42,9 @@ if (config.enableErrorMonitoring) { | ||
} | ||
if ((config === null || config === void 0 ? void 0 : config.assetSpeedMonitoringWhiteList) && config.assetSpeedMonitoringWhiteList.length > 0) { | ||
if (((config === null || config === void 0 ? void 0 : config.assetSpeedMonitoringWhiteList) && config.assetSpeedMonitoringWhiteList.length > 0) || | ||
config.isWebappContainer) { | ||
this.plugins.push(assetSpeedPlugin); | ||
} | ||
if (config === null || config === void 0 ? void 0 : config.enableDetectPageChange) { | ||
this.plugins.push(onPageChangePlugin); | ||
} | ||
this.installPlugins(); // install all plugins | ||
@@ -69,3 +69,2 @@ } | ||
this._commonData.appName = config.appName; | ||
this._commonData.currentHref = location.href; | ||
this.lifeCycle.emit(lifeCycleEventName.onCommonDataInit, this.commonData); | ||
@@ -87,2 +86,6 @@ } | ||
setConfig(config) { | ||
// once set as isWebappContainer, we will not allow setConfig again. | ||
if (this.config.isWebappContainer) { | ||
return; | ||
} | ||
const setValue = (key, value) => { | ||
@@ -102,11 +105,23 @@ this.config[key] = value; | ||
info(eventName, extraInfo) { | ||
this.normalLogPipeLine(Object.assign({ severity: SeverityType.INFO, eventName }, extraInfo)); | ||
this.normalLogPipeLine({ | ||
severity: SeverityType.INFO, | ||
eventName, | ||
extraInfo, | ||
}); | ||
} | ||
// send warn level log | ||
warn(eventName, extraInfo) { | ||
this.normalLogPipeLine(Object.assign({ severity: SeverityType.WARN, eventName }, extraInfo)); | ||
this.normalLogPipeLine({ | ||
severity: SeverityType.WARN, | ||
eventName, | ||
extraInfo, | ||
}); | ||
} | ||
// send error level log | ||
error(eventName, extraInfo) { | ||
this.normalLogPipeLine(Object.assign({ severity: SeverityType.ERROR, eventName }, extraInfo)); | ||
this.normalLogPipeLine({ | ||
severity: SeverityType.ERROR, | ||
eventName, | ||
extraInfo, | ||
}); | ||
} | ||
@@ -116,3 +131,7 @@ // send business related log, usually used for data analysis | ||
businessLog(eventName, extraInfo) { | ||
this.normalLogPipeLine(Object.assign({ severity: SeverityType.INFO, isBusinessLog: true, eventName }, extraInfo)); | ||
this.normalLogPipeLine({ | ||
severity: SeverityType.INFO, | ||
eventName, | ||
extraInfo: Object.assign(Object.assign({}, extraInfo), { isBusinessLog: true }), | ||
}); | ||
} | ||
@@ -136,5 +155,10 @@ // duration: milliseconds | ||
eventName, | ||
duration: duration, | ||
extraInfo: { | ||
duration: duration, | ||
}, | ||
}); | ||
} | ||
getTimerKey(eventName) { | ||
return this.config.isWebappContainer ? `${getMFEName()}_${eventName}` : eventName; | ||
} | ||
timeStart(eventName) { | ||
@@ -145,6 +169,6 @@ if (typeof eventName !== 'string') { | ||
} | ||
if (this.timeMap[eventName]) { | ||
if (this.timeMap[this.getTimerKey(eventName)]) { | ||
console.warn(`Timer ${eventName} already exists`); | ||
} | ||
this.timeMap[eventName] = Date.now(); | ||
this.timeMap[this.getTimerKey(eventName)] = Date.now(); | ||
} | ||
@@ -156,11 +180,13 @@ timeEnd(eventName, delta) { | ||
} | ||
if (this.timeMap[eventName]) { | ||
if (this.timeMap[this.getTimerKey(eventName)]) { | ||
// if you need an amount 'delta' to confirm the event did end, you can subtract it | ||
const duration = Date.now() - this.timeMap[eventName] + (delta || 0); | ||
const duration = Date.now() - this.timeMap[this.getTimerKey(eventName)] + (delta || 0); | ||
this.normalLogPipeLine({ | ||
severity: SeverityType.SPEED, | ||
eventName, | ||
duration: duration, | ||
extraInfo: { | ||
duration: duration, | ||
}, | ||
}); | ||
delete this.timeMap[eventName]; | ||
delete this.timeMap[this.getTimerKey(eventName)]; | ||
} | ||
@@ -171,4 +197,23 @@ else { | ||
} | ||
addToAssetSpeedWhiteListByMFE({ MFEName, whiteList }) { | ||
var _a, _b, _c; | ||
if (!MFEName || !(whiteList === null || whiteList === void 0 ? void 0 : whiteList.length)) { | ||
return; | ||
} | ||
// if no assetSpeedMonitoringWhiteListByMFE, initialize one | ||
if (!this.config.assetSpeedMonitoringWhiteListByMFE) { | ||
this.config.assetSpeedMonitoringWhiteListByMFE = {}; | ||
} | ||
if (!((_a = this.config.assetSpeedMonitoringWhiteListByMFE) === null || _a === void 0 ? void 0 : _a[MFEName])) { | ||
this.config.assetSpeedMonitoringWhiteListByMFE = Object.assign(Object.assign({}, this.config.assetSpeedMonitoringWhiteListByMFE), { [MFEName]: whiteList }); | ||
} | ||
else { | ||
(_c = (_b = this.config.assetSpeedMonitoringWhiteListByMFE) === null || _b === void 0 ? void 0 : _b[MFEName]) === null || _c === void 0 ? void 0 : _c.push(...whiteList); | ||
} | ||
} | ||
// please call destroy from your app root component when your app unmount | ||
destroy() { | ||
if (this.config.isWebappContainer) { | ||
return; | ||
} | ||
this.plugins.forEach((item) => { | ||
@@ -175,0 +220,0 @@ item.uninstall(); |
@@ -9,2 +9,3 @@ export var SeverityType; | ||
SeverityType["SPEED"] = "speed"; | ||
SeverityType["AUTO_DETECT_EVENT"] = "autoDetectEvent"; | ||
})(SeverityType || (SeverityType = {})); | ||
@@ -59,1 +60,5 @@ // platform type | ||
})(StaticFileType || (StaticFileType = {})); | ||
export var AutoDetectedEventType; | ||
(function (AutoDetectedEventType) { | ||
AutoDetectedEventType["onPageChange"] = "onPageChange"; | ||
})(AutoDetectedEventType || (AutoDetectedEventType = {})); |
@@ -7,2 +7,3 @@ import { Environment, PlatformType } from './common'; | ||
env: Environment.staging, | ||
isWebappContainer: false, | ||
delay: 2000, | ||
@@ -13,2 +14,4 @@ errorRepeatTime: 3, | ||
assetSpeedMonitoringWhiteList: [], | ||
enableDetectPageChange: false, | ||
assetSpeedMonitoringWhiteListByMFE: {}, | ||
}; | ||
@@ -15,0 +18,0 @@ export const DEFAULT_COMMON_DATA = { |
@@ -27,8 +27,9 @@ import { SeverityType, PerformanceType } from '../constant'; | ||
// only listen on static file type | ||
if (ASSETS_INITIATOR_TYPE.indexOf(entry.initiatorType) !== -1 && | ||
checkIfInWhiteList(entry.name, airTracker.config.assetSpeedMonitoringWhiteList)) { | ||
if (ASSETS_INITIATOR_TYPE.indexOf(entry.initiatorType) !== -1 && checkIfInWhiteList(entry.name, airTracker)) { | ||
airTracker.normalLogPipeLine({ | ||
severity: SeverityType.PERFORMANCE, | ||
eventName: PerformanceType.ASSETS_SPEED, | ||
log: generateSpeedLog(entry), | ||
extraInfo: { | ||
log: generateSpeedLog(entry), | ||
}, | ||
}); | ||
@@ -35,0 +36,0 @@ } |
@@ -10,3 +10,5 @@ import { AutoDetectedErrorType, SeverityType, StaticFileType } from '../constant'; | ||
eventName: AutoDetectedErrorType.windowOnError, | ||
error: errString, | ||
extraInfo: { | ||
error: errString, | ||
}, | ||
}); | ||
@@ -19,3 +21,5 @@ }; | ||
eventName: AutoDetectedErrorType.promiseError, | ||
error: reason, | ||
extraInfo: { | ||
error: reason, | ||
}, | ||
}); | ||
@@ -71,4 +75,6 @@ }; | ||
eventName: AutoDetectedErrorType.staticFileLoadError, | ||
staticFileType, | ||
error: `${tagName} load fail: ${url}`, | ||
extraInfo: { | ||
staticFileType, | ||
error: `${tagName} load fail: ${url}`, | ||
}, | ||
}); | ||
@@ -75,0 +81,0 @@ } |
@@ -27,3 +27,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
eventName: name, | ||
log: { navigationType, rating, value }, | ||
extraInfo: { | ||
log: { navigationType, rating, value }, | ||
}, | ||
}); | ||
@@ -30,0 +32,0 @@ }; |
@@ -17,3 +17,2 @@ import { Config, CommonData, ExtraInfo } from './interface/index'; | ||
get commonData(): CommonData; | ||
private detectHrefChange; | ||
private initCommonData; | ||
@@ -23,3 +22,8 @@ private updateCommonDataBasedOnConfig; | ||
setConfig(config: Partial<Config>): void; | ||
normalLogPipeLine: import("./pipes/index").Pipe<any, any>; | ||
private normalPipelineObj; | ||
normalLogPipeLine: ({ severity, eventName, extraInfo, }: { | ||
severity: string; | ||
eventName: string; | ||
extraInfo?: ExtraInfo | undefined; | ||
}) => void; | ||
info(eventName: string, extraInfo?: ExtraInfo): void; | ||
@@ -30,6 +34,11 @@ warn(eventName: string, extraInfo?: ExtraInfo): void; | ||
reportDuration(eventName: string, duration: number): void; | ||
private getTimerKey; | ||
timeStart(eventName: string): void; | ||
timeEnd(eventName: string, delta?: number): void; | ||
addToAssetSpeedWhiteListByMFE({ MFEName, whiteList }: { | ||
MFEName: string; | ||
whiteList: (string | RegExp)[]; | ||
}): void; | ||
destroy(): void; | ||
} | ||
//# sourceMappingURL=airTracker.d.ts.map |
@@ -7,3 +7,4 @@ export declare enum SeverityType { | ||
PERFORMANCE = "performance", | ||
SPEED = "speed" | ||
SPEED = "speed", | ||
AUTO_DETECT_EVENT = "autoDetectEvent" | ||
} | ||
@@ -50,2 +51,5 @@ export declare enum PlatformType { | ||
} | ||
export declare enum AutoDetectedEventType { | ||
onPageChange = "onPageChange" | ||
} | ||
export interface ExtraCommonDataFormat { | ||
@@ -52,0 +56,0 @@ [key: string]: string | undefined; |
@@ -9,7 +9,12 @@ import { Environment } from '../constant/common'; | ||
accountId?: string; | ||
isWebappContainer?: boolean; | ||
errorRepeatTime?: number; | ||
enableErrorMonitoring?: boolean; | ||
enableWebVitals?: boolean; | ||
enableDetectPageChange?: boolean; | ||
assetSpeedMonitoringWhiteList?: (string | RegExp)[]; | ||
assetSpeedMonitoringWhiteListByMFE?: { | ||
[key: string]: (string | RegExp)[]; | ||
}; | ||
} | ||
//# sourceMappingURL=config.d.ts.map |
@@ -19,3 +19,2 @@ import { Environment, NetworkType, PlatformType, SeverityType } from '../constant/common'; | ||
networkType?: NetworkType; | ||
currentHref?: string; | ||
[key: string]: string | undefined; | ||
@@ -22,0 +21,0 @@ } |
import { NetworkType, PlatformType } from '../constant/common'; | ||
import AirTracker from '..'; | ||
export declare const generateUId: () => string; | ||
export declare const getMFEName: () => string; | ||
export declare const getDeviceId: () => string | undefined; | ||
@@ -17,3 +19,4 @@ export declare const getPlatform: () => PlatformType; | ||
export declare const getReportVal: <T>(rawVal?: T | undefined, isDefaultByString?: boolean) => T | ReportDefaultVal; | ||
export declare const checkIfInWhiteList: (url: string, whiteList: (RegExp | string)[] | undefined) => boolean; | ||
export declare const checkIfInWhiteList: (url: string, airTracker: AirTracker) => boolean; | ||
export declare const checkIfInWhiteListHelper: (url: string, whiteList: (RegExp | string)[] | undefined) => boolean; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -11,2 +11,6 @@ import { DEVICE_ID_STORAGE_KEY } from '../constant/index'; | ||
}; | ||
export const getMFEName = () => { | ||
var _a, _b; | ||
return ((_b = (_a = location === null || location === void 0 ? void 0 : location.pathname) === null || _a === void 0 ? void 0 : _a.split('/')) === null || _b === void 0 ? void 0 : _b[2]) || 'unknown'; | ||
}; | ||
export const getDeviceId = () => { | ||
@@ -115,3 +119,14 @@ try { | ||
}; | ||
export const checkIfInWhiteList = (url, whiteList) => { | ||
export const checkIfInWhiteList = (url, airTracker) => { | ||
var _a; | ||
let isInWhiteList = false; | ||
if (!airTracker.config.isWebappContainer) { | ||
isInWhiteList = checkIfInWhiteListHelper(url, airTracker.config.assetSpeedMonitoringWhiteList); | ||
return isInWhiteList; | ||
} | ||
// if isWebappContainer, check both assetSpeedMonitoringWhiteList and assetSpeedMonitoringWhiteListByMFE | ||
const MFEName = getMFEName(); | ||
return (isInWhiteList || checkIfInWhiteListHelper(url, (_a = airTracker.config.assetSpeedMonitoringWhiteListByMFE) === null || _a === void 0 ? void 0 : _a[MFEName])); | ||
}; | ||
export const checkIfInWhiteListHelper = (url, whiteList) => { | ||
if (!(whiteList === null || whiteList === void 0 ? void 0 : whiteList.length)) { | ||
@@ -118,0 +133,0 @@ return false; |
{ | ||
"name": "@airwallex/airtracker", | ||
"version": "0.4.9", | ||
"version": "1.0.0", | ||
"scripts": { | ||
@@ -20,3 +20,3 @@ "clean": "rm -rf ./lib", | ||
"main": "lib/index.js", | ||
"types": "./lib/types/index.d.ts", | ||
"types": "lib/types/index.d.ts", | ||
"files": [ | ||
@@ -75,2 +75,2 @@ "lib/**/*" | ||
} | ||
} | ||
} |
yarn add @airwallex/airTracker | ||
# How to test airTracker | ||
1. under AirTracker Dir, run `npm link` | ||
2. under AirTracker Dir, run `npm build` | ||
3. under your project Dir which use AirTracker as an dependency, run `npm link @airwallex/airtracker` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
63489
13.2%71
4.41%1261
12.69%1
-50%6
200%