fix: update parameters in segments (#32)
diff --git a/README.md b/README.md
index 034c394..2c8eb52 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,7 @@
|enableSPA|Boolean|Monitor the page hashchange event and report PV, which is suitable for single page application scenarios|false|false|
|autoTracePerf|Boolean|Support sending of performance data automatically.|false|true|
|vue|Boolean|Support vue errors monitoring|false|true|
+|traceSDKInternal|Boolean|Support tracing SDK internal RPC.|false|false|
## Collect Metrics Manually
Use the `setPerformance` method to report metrics at the moment of page loaded or any other moment meaningful.
diff --git a/src/errors/ajax.ts b/src/errors/ajax.ts
index 3ec705f..d5b7f72 100644
--- a/src/errors/ajax.ts
+++ b/src/errors/ajax.ts
@@ -28,7 +28,7 @@
const xhrSend = XMLHttpRequest.prototype.send;
const xhrEvent = (event: any) => {
try {
- if (event && event.currentTarget && event.currentTarget.status >= 400) {
+ if (event && event.currentTarget && (event.currentTarget.status >= 400 || event.currentTarget.status === 0)) {
this.logInfo = {
uniqueId: uuid(),
service: options.service,
diff --git a/src/interceptors/xhr.ts b/src/interceptors/xhr.ts
index aa12781..a743401 100644
--- a/src/interceptors/xhr.ts
+++ b/src/interceptors/xhr.ts
@@ -16,13 +16,18 @@
*/
export default function xhrInterceptor() {
- const originalXHR = window.XMLHttpRequest;
+ const originalXHR = window.XMLHttpRequest as any;
+ const xhrSend = XMLHttpRequest.prototype.send;
+ const xhrOpen = XMLHttpRequest.prototype.open;
+
+ originalXHR.getRequestConfig = [];
function ajaxEventTrigger(event: string) {
const ajaxEvent = new CustomEvent(event, { detail: this });
window.dispatchEvent(ajaxEvent);
}
+
function customizedXHR() {
const liveXHR = new originalXHR();
@@ -34,6 +39,15 @@
false,
);
+ liveXHR.open = function (method: string, url: string) {
+ this.getRequestConfig = arguments;
+
+ return xhrOpen.apply(this, arguments);
+ };
+ liveXHR.send = function (body: any) {
+ return xhrSend.apply(this, arguments);
+ };
+
return liveXHR;
}
(window as any).XMLHttpRequest = customizedXHR;
diff --git a/src/monitor.ts b/src/monitor.ts
index c7107de..7c63a4d 100644
--- a/src/monitor.ts
+++ b/src/monitor.ts
@@ -22,13 +22,14 @@
const ClientMonitor = {
customOptions: {
- collector: '', // report serve
+ collector: location.origin, // report serve
jsErrors: true, // vue, js and promise errors
apiErrors: true,
resourceErrors: true,
autoTracePerf: true, // trace performance detail
useFmp: false, // use first meaningful paint
enableSPA: false,
+ traceSDKInternal: false,
} as CustomOptionsType,
register(configs: CustomOptionsType) {
diff --git a/src/services/report.ts b/src/services/report.ts
index 32949b3..263bf8e 100644
--- a/src/services/report.ts
+++ b/src/services/report.ts
@@ -41,7 +41,7 @@
fetch(sendRequest)
.then((response) => {
- if (response.status >= 400) {
+ if (response.status >= 400 || response.status === 0) {
throw new Error('Something went wrong on api server!');
}
})
diff --git a/src/trace/segment.ts b/src/trace/segment.ts
index 3f4cc2b..fbbd564 100644
--- a/src/trace/segment.ts
+++ b/src/trace/segment.ts
@@ -14,52 +14,76 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Base64 } from 'js-base64';
+import { encode } from 'js-base64';
import xhrInterceptor from '../interceptors/xhr';
import uuid from '../services/uuid';
import Report from '../services/report';
import { SegmentFeilds, SpanFeilds } from './type';
-import { SpanLayer, SpanType, ReadyStatus, ComponentId, ServiceTag } from '../services/constant';
+import { SpanLayer, SpanType, ReadyStatus, ComponentId, ServiceTag, ReportTypes } from '../services/constant';
import { CustomOptionsType } from '../types';
import windowFetch from '../interceptors/fetch';
export default function traceSegment(options: CustomOptionsType) {
- let segments = [] as any;
- const segCollector: { event: XMLHttpRequest; startTime: number }[] | any = [];
+ let segments = [] as SegmentFeilds[];
+ const segCollector: { event: XMLHttpRequest; startTime: number; traceId: string; traceSegmentId: string }[] = [];
// inject interceptor
xhrInterceptor();
windowFetch();
- window.addEventListener('xhrReadyStateChange', (event: CustomEvent) => {
- const segment = {
- traceId: uuid(),
+ window.addEventListener('xhrReadyStateChange', (event: CustomEvent<XMLHttpRequest & { getRequestConfig: any[] }>) => {
+ let segment = {
+ traceId: '',
service: options.service + ServiceTag,
spans: [],
serviceInstance: options.serviceVersion,
- traceSegmentId: uuid(),
+ traceSegmentId: '',
} as SegmentFeilds;
const xhrState = event.detail.readyState;
+ const config = event.detail.getRequestConfig;
+ let url = {} as URL;
+ if (config[1].includes('http://') || config[1].includes('https://')) {
+ url = new URL(config[1]);
+ } else {
+ url = config[1];
+ }
+ if (
+ ([ReportTypes.ERROR, ReportTypes.PERF, ReportTypes.SEGMENTS] as string[]).includes(url.pathname) &&
+ !options.traceSDKInternal
+ ) {
+ return;
+ }
// The values of xhrState are from https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
if (xhrState === ReadyStatus.OPENED) {
+ const traceId = uuid();
+ const traceSegmentId = uuid();
+
segCollector.push({
event: event.detail,
startTime: new Date().getTime(),
+ traceId,
+ traceSegmentId,
});
- const traceIdStr = String(Base64.encode(segment.traceId));
- const segmentId = String(Base64.encode(segment.traceSegmentId));
- const service = String(Base64.encode(segment.service + ServiceTag));
- const instance = String(Base64.encode(segment.serviceInstance));
- const endpoint = String(Base64.encode(options.pagePath));
- const peer = String(Base64.encode(location.host));
+
+ 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 peer = String(encode(url.host));
const index = segment.spans.length;
const values = `${1}-${traceIdStr}-${segmentId}-${index}-${service}-${instance}-${endpoint}-${peer}`;
event.detail.setRequestHeader('sw8', values);
}
+
if (xhrState === ReadyStatus.DONE) {
const endTime = new Date().getTime();
for (let i = 0; i < segCollector.length; i++) {
- if (segCollector[i].event.status) {
+ if (segCollector[i].event.readyState === ReadyStatus.DONE) {
+ let url = {} as URL;
+ if (segCollector[i].event.status) {
+ url = new URL(segCollector[i].event.responseURL);
+ }
const exitSpan: SpanFeilds = {
operationName: options.pagePath,
startTime: segCollector[i].startTime,
@@ -67,10 +91,15 @@
spanId: segment.spans.length,
spanLayer: SpanLayer,
spanType: SpanType,
- isError: event.detail.status >= 400 ? true : false,
+ isError: event.detail.status === 0 || event.detail.status >= 400 ? true : false, // when requests failed, the status is 0
parentSpanId: segment.spans.length - 1,
componentId: ComponentId,
- peer: segCollector[i].event.responseURL.split('://')[1],
+ peer: url.host,
+ };
+ segment = {
+ ...segment,
+ traceId: segCollector[i].traceId,
+ traceSegmentId: segCollector[i].traceSegmentId,
};
segment.spans.push(exitSpan);
segCollector.splice(i, 1);
@@ -85,11 +114,12 @@
}
new Report('SEGMENTS', options.collector).sendByXhr(segments);
};
+ //report per 5min
setInterval(() => {
if (!segments.length) {
return;
}
new Report('SEGMENTS', options.collector).sendByXhr(segments);
segments = [];
- }, 50000);
+ }, 300000);
}
diff --git a/src/types.d.ts b/src/types.d.ts
index 1deb6e3..7a21889 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -27,4 +27,5 @@
useFmp?: boolean;
enableSPA?: boolean;
vue?: any;
+ traceSDKInternal: boolean;
}