You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2022/04/26 11:29:02 UTC
[skywalking-client-js] branch master updated: feat: reset custom configurations when the page router changed for SPA (#86)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-client-js.git
The following commit(s) were added to refs/heads/master by this push:
new 639731f feat: reset custom configurations when the page router changed for SPA (#86)
639731f is described below
commit 639731fad4dc7bf1147640cc57a9d135a0315737
Author: Fine0830 <fi...@outlook.com>
AuthorDate: Tue Apr 26 19:28:58 2022 +0800
feat: reset custom configurations when the page router changed for SPA (#86)
---
src/errors/ajax.ts | 16 ++++++++++++----
src/errors/frames.ts | 16 +++++++++-------
src/errors/js.ts | 16 ++++++++++++----
src/errors/promise.ts | 16 ++++++++++++----
src/errors/resource.ts | 20 ++++++++++++++------
src/errors/vue.ts | 19 ++++++++++++-------
src/monitor.ts | 20 ++++++++++++++++++--
src/trace/interceptors/fetch.ts | 39 ++++++++++++++++++---------------------
src/trace/interceptors/xhr.ts | 25 +++++++++++++++++--------
src/trace/segment.ts | 9 +++++++--
10 files changed, 131 insertions(+), 65 deletions(-)
diff --git a/src/errors/ajax.ts b/src/errors/ajax.ts
index f2e2825..839f450 100644
--- a/src/errors/ajax.ts
+++ b/src/errors/ajax.ts
@@ -18,14 +18,21 @@
import uuid from '../services/uuid';
import Base from '../services/base';
import { GradeTypeEnum, ErrorsCategory, ReportTypes } from '../services/constant';
+import { CustomReportOptions } from '../types';
class AjaxErrors extends Base {
+ private infoOpt: CustomReportOptions = {
+ service: '',
+ pagePath: '',
+ serviceVersion: '',
+ };
// get http error info
- public handleError(options: { service: string; serviceVersion: string; pagePath: string; collector: string }) {
+ public handleError(options: CustomReportOptions) {
// XMLHttpRequest Object
if (!window.XMLHttpRequest) {
return;
}
+ this.infoOpt = options;
window.addEventListener(
'xhrReadyStateChange',
(event: CustomEvent<XMLHttpRequest & { getRequestConfig: any[] }>) => {
@@ -42,10 +49,8 @@ class AjaxErrors extends Base {
}
this.logInfo = {
+ ...this.infoOpt,
uniqueId: uuid(),
- service: options.service,
- serviceVersion: options.serviceVersion,
- pagePath: options.pagePath,
category: ErrorsCategory.AJAX_ERROR,
grade: GradeTypeEnum.ERROR,
errorUrl: detail.getRequestConfig[1],
@@ -57,6 +62,9 @@ class AjaxErrors extends Base {
},
);
}
+ setOptions(opt: CustomReportOptions) {
+ this.infoOpt = opt;
+ }
}
export default new AjaxErrors();
diff --git a/src/errors/frames.ts b/src/errors/frames.ts
index 7471a8d..e8d2c75 100644
--- a/src/errors/frames.ts
+++ b/src/errors/frames.ts
@@ -18,17 +18,19 @@
import uuid from '../services/uuid';
import Base from '../services/base';
import { GradeTypeEnum, ErrorsCategory } from '../services/constant';
+import { CustomReportOptions } from '../types';
class FrameErrors extends Base {
- public handleErrors(
- options: { service: string; serviceVersion: string; pagePath: string; collector?: string },
- error: Error,
- ) {
+ private infoOpt: CustomReportOptions = {
+ service: '',
+ pagePath: '',
+ serviceVersion: '',
+ };
+ public handleErrors(options: CustomReportOptions, error: Error) {
+ this.infoOpt = options;
this.logInfo = {
+ ...this.infoOpt,
uniqueId: uuid(),
- service: options.service,
- serviceVersion: options.serviceVersion,
- pagePath: options.pagePath,
category: ErrorsCategory.JS_ERROR,
grade: GradeTypeEnum.ERROR,
errorUrl: error.name || location.href,
diff --git a/src/errors/js.ts b/src/errors/js.ts
index 9ff7f49..da00952 100644
--- a/src/errors/js.ts
+++ b/src/errors/js.ts
@@ -18,14 +18,19 @@
import uuid from '../services/uuid';
import Base from '../services/base';
import { GradeTypeEnum, ErrorsCategory } from '../services/constant';
+import { CustomReportOptions } from '../types';
class JSErrors extends Base {
- public handleErrors(options: { service: string; serviceVersion: string; pagePath: string; collector: string }) {
+ private infoOpt: CustomReportOptions = {
+ service: '',
+ pagePath: '',
+ serviceVersion: '',
+ };
+ public handleErrors(options: CustomReportOptions) {
+ this.infoOpt = options;
window.onerror = (message, url, line, col, error) => {
this.logInfo = {
+ ...this.infoOpt,
uniqueId: uuid(),
- service: options.service,
- serviceVersion: options.serviceVersion,
- pagePath: options.pagePath,
category: ErrorsCategory.JS_ERROR,
grade: GradeTypeEnum.ERROR,
errorUrl: url,
@@ -38,5 +43,8 @@ class JSErrors extends Base {
this.traceInfo();
};
}
+ setOptions(opt: CustomReportOptions) {
+ this.infoOpt = opt;
+ }
}
export default new JSErrors();
diff --git a/src/errors/promise.ts b/src/errors/promise.ts
index fd46b70..543a9a1 100644
--- a/src/errors/promise.ts
+++ b/src/errors/promise.ts
@@ -18,9 +18,16 @@
import uuid from '../services/uuid';
import Base from '../services/base';
import { GradeTypeEnum, ErrorsCategory } from '../services/constant';
+import { CustomReportOptions } from '../types';
class PromiseErrors extends Base {
- public handleErrors(options: { service: string; serviceVersion: string; pagePath: string; collector: string }) {
+ private infoOpt: CustomReportOptions = {
+ service: '',
+ pagePath: '',
+ serviceVersion: '',
+ };
+ public handleErrors(options: CustomReportOptions) {
+ this.infoOpt = options;
window.addEventListener('unhandledrejection', (event) => {
try {
let url = '';
@@ -31,10 +38,8 @@ class PromiseErrors extends Base {
url = event.reason.config.url;
}
this.logInfo = {
+ ...this.infoOpt,
uniqueId: uuid(),
- service: options.service,
- serviceVersion: options.serviceVersion,
- pagePath: options.pagePath,
category: ErrorsCategory.PROMISE_ERROR,
grade: GradeTypeEnum.ERROR,
errorUrl: url || location.href,
@@ -48,5 +53,8 @@ class PromiseErrors extends Base {
}
});
}
+ setOptions(opt: CustomReportOptions) {
+ this.infoOpt = opt;
+ }
}
export default new PromiseErrors();
diff --git a/src/errors/resource.ts b/src/errors/resource.ts
index 0cfbe50..206c8ef 100644
--- a/src/errors/resource.ts
+++ b/src/errors/resource.ts
@@ -18,15 +18,22 @@
import uuid from '../services/uuid';
import Base from '../services/base';
import { GradeTypeEnum, ErrorsCategory } from '../services/constant';
+import { CustomReportOptions } from '../types';
class ResourceErrors extends Base {
- public handleErrors(options: { service: string; pagePath: string; serviceVersion: string; collector: string }) {
+ private infoOpt: CustomReportOptions = {
+ service: '',
+ pagePath: '',
+ serviceVersion: '',
+ };
+ public handleErrors(options: CustomReportOptions) {
+ this.infoOpt = options;
window.addEventListener('error', (event) => {
try {
if (!event) {
return;
}
- const target: any = event.target || event.srcElement;
+ const target: any = event.target;
const isElementTarget =
target instanceof HTMLScriptElement ||
target instanceof HTMLLinkElement ||
@@ -37,13 +44,11 @@ class ResourceErrors extends Base {
return;
}
this.logInfo = {
+ ...this.infoOpt,
uniqueId: uuid(),
- service: options.service,
- serviceVersion: options.serviceVersion,
- pagePath: options.pagePath,
category: ErrorsCategory.RESOURCE_ERROR,
grade: target.tagName === 'IMG' ? GradeTypeEnum.WARNING : GradeTypeEnum.ERROR,
- errorUrl: target.src || target.href || location.href,
+ errorUrl: (target as HTMLScriptElement).src || (target as HTMLLinkElement).href || location.href,
message: `load ${target.tagName} resource error`,
collector: options.collector,
stack: `load ${target.tagName} resource error`,
@@ -54,5 +59,8 @@ class ResourceErrors extends Base {
}
});
}
+ setOptions(opt: CustomReportOptions) {
+ this.infoOpt = opt;
+ }
}
export default new ResourceErrors();
diff --git a/src/errors/vue.ts b/src/errors/vue.ts
index a1de936..2cf805c 100644
--- a/src/errors/vue.ts
+++ b/src/errors/vue.ts
@@ -18,19 +18,21 @@
import uuid from '../services/uuid';
import Base from '../services/base';
import { GradeTypeEnum, ErrorsCategory } from '../services/constant';
+import { CustomReportOptions } from '../types';
class VueErrors extends Base {
- public handleErrors(
- options: { service: string; pagePath: string; serviceVersion: string; collector: string },
- Vue: any,
- ) {
+ private infoOpt: CustomReportOptions = {
+ service: '',
+ pagePath: '',
+ serviceVersion: '',
+ };
+ public handleErrors(options: CustomReportOptions, Vue: any) {
+ this.infoOpt = options;
Vue.config.errorHandler = (error: Error, vm: any, info: string) => {
try {
this.logInfo = {
+ ...this.infoOpt,
uniqueId: uuid(),
- service: options.service,
- serviceVersion: options.serviceVersion,
- pagePath: options.pagePath,
category: ErrorsCategory.VUE_ERROR,
grade: GradeTypeEnum.ERROR,
errorUrl: location.href,
@@ -44,6 +46,9 @@ class VueErrors extends Base {
}
};
}
+ setOptions(opt: CustomReportOptions) {
+ this.infoOpt = opt;
+ }
}
export default new VueErrors();
diff --git a/src/monitor.ts b/src/monitor.ts
index de8f949..6c12d7d 100644
--- a/src/monitor.ts
+++ b/src/monitor.ts
@@ -18,7 +18,7 @@
import { CustomOptionsType, CustomReportOptions } from './types';
import { JSErrors, PromiseErrors, AjaxErrors, ResourceErrors, VueErrors, FrameErrors } from './errors/index';
import tracePerf from './performance/index';
-import traceSegment from './trace/segment';
+import traceSegment, { setConfig } from './trace/segment';
const ClientMonitor = {
customOptions: {
@@ -79,13 +79,29 @@ const ClientMonitor = {
ResourceErrors.handleErrors({ service, pagePath, serviceVersion, collector });
}
},
- setPerformance(configs: CustomOptionsType) {
+ setPerformance(configs: CustomReportOptions) {
// history router
this.customOptions = {
...this.customOptions,
...configs,
+ useFmp: false,
};
this.performance(this.customOptions);
+ const { service, pagePath, serviceVersion, collector } = this.customOptions;
+ if (this.customOptions.jsErrors) {
+ JSErrors.setOptions({ service, pagePath, serviceVersion, collector });
+ PromiseErrors.setOptions({ service, pagePath, serviceVersion, collector });
+ if (this.customOptions.vue) {
+ VueErrors.setOptions({ service, pagePath, serviceVersion, collector });
+ }
+ }
+ if (this.customOptions.apiErrors) {
+ AjaxErrors.setOptions({ service, pagePath, serviceVersion, collector });
+ }
+ if (this.customOptions.resourceErrors) {
+ ResourceErrors.setOptions({ service, pagePath, serviceVersion, collector });
+ }
+ setConfig(this.customOptions);
},
reportFrameErrors(configs: CustomReportOptions, error: Error) {
FrameErrors.handleErrors(configs, error);
diff --git a/src/trace/interceptors/fetch.ts b/src/trace/interceptors/fetch.ts
index 90eabe4..bc231e8 100644
--- a/src/trace/interceptors/fetch.ts
+++ b/src/trace/interceptors/fetch.ts
@@ -19,17 +19,11 @@ import uuid from '../../services/uuid';
import { SegmentFields, SpanFields } from '../type';
import { CustomOptionsType } from '../../types';
import Base from '../../services/base';
-import {
- ComponentId,
- ReportTypes,
- SpanLayer,
- SpanType,
- ErrorsCategory,
- GradeTypeEnum,
-} from '../../services/constant';
-
+import { ComponentId, ReportTypes, SpanLayer, SpanType, ErrorsCategory, GradeTypeEnum } from '../../services/constant';
+let customConfig: any = {};
export default function windowFetch(options: CustomOptionsType, segments: SegmentFields[]) {
const originFetch: any = window.fetch;
+ setFetchOptions(options);
window.fetch = async (...args: any) => {
const startTime = new Date().getTime();
@@ -37,9 +31,9 @@ export default function windowFetch(options: CustomOptionsType, segments: Segmen
const traceSegmentId = uuid();
let segment = {
traceId: '',
- service: options.service,
+ service: customConfig.service,
spans: [],
- serviceInstance: options.serviceVersion,
+ serviceInstance: customConfig.serviceVersion,
traceSegmentId: '',
} as SegmentFields;
let url = {} as URL;
@@ -53,7 +47,7 @@ export default function windowFetch(options: CustomOptionsType, segments: Segmen
url.pathname = args[0];
}
- const noTraceOrigins = options.noTraceOrigins.some((rule: string | RegExp) => {
+ const noTraceOrigins = customConfig.noTraceOrigins.some((rule: string | RegExp) => {
if (typeof rule === 'string') {
if (rule === url.origin) {
return true;
@@ -64,18 +58,18 @@ export default function windowFetch(options: CustomOptionsType, segments: Segmen
}
}
});
- const cURL = new URL(options.collector);
+ const cURL = new URL(customConfig.collector);
const pathname = cURL.pathname === '/' ? url.pathname : url.pathname.replace(new RegExp(`^${cURL.pathname}`), '');
const internals = [ReportTypes.ERROR, ReportTypes.ERRORS, ReportTypes.PERF, ReportTypes.SEGMENTS] as string[];
const isSDKInternal = internals.includes(pathname);
- const hasTrace = !noTraceOrigins || (isSDKInternal && options.traceSDKInternal);
+ const hasTrace = !noTraceOrigins || (isSDKInternal && customConfig.traceSDKInternal);
if (hasTrace) {
const traceIdStr = String(encode(traceId));
const segmentId = String(encode(traceSegmentId));
const service = String(encode(segment.service));
const instance = String(encode(segment.serviceInstance));
- const endpoint = String(encode(options.pagePath));
+ const endpoint = String(encode(customConfig.pagePath));
const peer = String(encode(url.host));
const index = segment.spans.length;
const values = `${1}-${traceIdStr}-${segmentId}-${index}-${service}-${instance}-${endpoint}-${peer}`;
@@ -95,14 +89,14 @@ export default function windowFetch(options: CustomOptionsType, segments: Segmen
if (response && (response.status === 0 || response.status >= 400)) {
const logInfo = {
uniqueId: uuid(),
- service: options.service,
- serviceVersion: options.serviceVersion,
- pagePath: options.pagePath,
+ service: customConfig.service,
+ serviceVersion: customConfig.serviceVersion,
+ pagePath: customConfig.pagePath,
category: ErrorsCategory.AJAX_ERROR,
grade: GradeTypeEnum.ERROR,
errorUrl: (response && response.url) || `${url.protocol}//${url.host}${url.pathname}`,
message: `status: ${response ? response.status : 0}; statusText: ${response && response.statusText};`,
- collector: options.collector,
+ collector: customConfig.collector,
stack: 'Fetch: ' + response && response.statusText,
};
new Base().traceInfo(logInfo);
@@ -110,7 +104,7 @@ export default function windowFetch(options: CustomOptionsType, segments: Segmen
if (hasTrace) {
const endTime = new Date().getTime();
const exitSpan: SpanFields = {
- operationName: options.pagePath,
+ operationName: customConfig.pagePath,
startTime: startTime,
endTime,
spanId: segment.spans.length,
@@ -120,7 +114,7 @@ export default function windowFetch(options: CustomOptionsType, segments: Segmen
parentSpanId: segment.spans.length - 1,
componentId: ComponentId,
peer: url.host,
- tags: options.detailMode
+ tags: customConfig.detailMode
? [
{
key: 'http.method',
@@ -147,3 +141,6 @@ export default function windowFetch(options: CustomOptionsType, segments: Segmen
return response.clone();
};
}
+export function setFetchOptions(opt: CustomOptionsType) {
+ customConfig = { ...customConfig, ...opt };
+}
diff --git a/src/trace/interceptors/xhr.ts b/src/trace/interceptors/xhr.ts
index ec2e627..8074f0b 100644
--- a/src/trace/interceptors/xhr.ts
+++ b/src/trace/interceptors/xhr.ts
@@ -20,11 +20,17 @@ import { encode } from 'js-base64';
import { CustomOptionsType } from '../../types';
import { SegmentFields, SpanFields } from '../type';
+let customConfig: CustomOptionsType | any = {};
export default function xhrInterceptor(options: CustomOptionsType, segments: SegmentFields[]) {
+ setOptions(options);
const originalXHR = window.XMLHttpRequest as any;
const xhrSend = XMLHttpRequest.prototype.send;
const xhrOpen = XMLHttpRequest.prototype.open;
+ if (!(xhrSend && xhrOpen)) {
+ console.error('Tracing is not supported');
+ return;
+ }
originalXHR.getRequestConfig = [];
function ajaxEventTrigger(event: string) {
@@ -69,9 +75,9 @@ export default function xhrInterceptor(options: CustomOptionsType, segments: Seg
window.addEventListener('xhrReadyStateChange', (event: CustomEvent<XMLHttpRequest & { getRequestConfig: any[] }>) => {
let segment = {
traceId: '',
- service: options.service,
+ service: customConfig.service,
spans: [],
- serviceInstance: options.serviceVersion,
+ serviceInstance: customConfig.serviceVersion,
traceSegmentId: '',
} as SegmentFields;
const xhrState = event.detail.readyState;
@@ -86,7 +92,7 @@ export default function xhrInterceptor(options: CustomOptionsType, segments: Seg
url.pathname = config[1];
}
- const noTraceOrigins = options.noTraceOrigins.some((rule: string | RegExp) => {
+ const noTraceOrigins = customConfig.noTraceOrigins.some((rule: string | RegExp) => {
if (typeof rule === 'string') {
if (rule === url.origin) {
return true;
@@ -101,12 +107,12 @@ export default function xhrInterceptor(options: CustomOptionsType, segments: Seg
return;
}
- const cURL = new URL(options.collector);
+ const cURL = new URL(customConfig.collector);
const pathname = cURL.pathname === '/' ? url.pathname : url.pathname.replace(new RegExp(`^${cURL.pathname}`), '');
const internals = [ReportTypes.ERROR, ReportTypes.ERRORS, ReportTypes.PERF, ReportTypes.SEGMENTS] as string[];
const isSDKInternal = internals.includes(pathname);
- if (isSDKInternal && !options.traceSDKInternal) {
+ if (isSDKInternal && !customConfig.traceSDKInternal) {
return;
}
@@ -126,7 +132,7 @@ export default function xhrInterceptor(options: CustomOptionsType, segments: Seg
const segmentId = String(encode(traceSegmentId));
const service = String(encode(segment.service));
const instance = String(encode(segment.serviceInstance));
- const endpoint = String(encode(options.pagePath));
+ const endpoint = String(encode(customConfig.pagePath));
const peer = String(encode(url.host));
const index = segment.spans.length;
const values = `${1}-${traceIdStr}-${segmentId}-${index}-${service}-${instance}-${endpoint}-${peer}`;
@@ -144,7 +150,7 @@ export default function xhrInterceptor(options: CustomOptionsType, segments: Seg
}
const exitSpan: SpanFields = {
- operationName: options.pagePath,
+ operationName: customConfig.pagePath,
startTime: segCollector[i].startTime,
endTime,
spanId: segment.spans.length,
@@ -154,7 +160,7 @@ export default function xhrInterceptor(options: CustomOptionsType, segments: Seg
parentSpanId: segment.spans.length - 1,
componentId: ComponentId,
peer: responseURL.host,
- tags: options.detailMode
+ tags: customConfig.detailMode
? [
{
key: 'http.method',
@@ -180,3 +186,6 @@ export default function xhrInterceptor(options: CustomOptionsType, segments: Seg
}
});
}
+export function setOptions(opt: CustomOptionsType) {
+ customConfig = { ...customConfig, ...opt };
+}
diff --git a/src/trace/segment.ts b/src/trace/segment.ts
index 1a3d072..b8ea454 100644
--- a/src/trace/segment.ts
+++ b/src/trace/segment.ts
@@ -15,8 +15,8 @@
* limitations under the License.
*/
-import xhrInterceptor from './interceptors/xhr';
-import windowFetch from './interceptors/fetch';
+import xhrInterceptor, { setOptions } from './interceptors/xhr';
+import windowFetch, { setFetchOptions } from './interceptors/fetch';
import Report from '../services/report';
import { SegmentFields } from './type';
import { CustomOptionsType } from '../types';
@@ -41,3 +41,8 @@ export default function traceSegment(options: CustomOptionsType) {
segments.splice(0, segments.length);
}, options.traceTimeInterval);
}
+
+export function setConfig(opt: CustomOptionsType) {
+ setOptions(opt);
+ setFetchOptions(opt);
+}