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
commit 3c0ee0bb3bb03d73e7907c809e2de87d5230870e Author: Qiuxia Fan <fine0...@outlook.com> AuthorDate: Wed Jan 8 11:15:27 2020 +0800 feat: support ajax and promise error for trace --- src/errors/ajax.ts | 66 ++++++++++++++++++++++++++++++++++ src/{types.d.ts => errors/index.ts} | 19 ++++------ src/errors/{jsErrors.ts => js.ts} | 7 ++-- src/errors/{jsErrors.ts => promise.ts} | 43 ++++++++++++---------- src/monitor.ts | 35 ++++++++++-------- src/services/base.ts | 2 +- src/services/report.ts | 5 +-- src/services/types.d.ts | 6 ++-- src/types.d.ts | 6 ++-- 9 files changed, 129 insertions(+), 60 deletions(-) diff --git a/src/errors/ajax.ts b/src/errors/ajax.ts new file mode 100644 index 0000000..9727339 --- /dev/null +++ b/src/errors/ajax.ts @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Base from '../services/base'; +import { GradeTypeEnum, ErrorsCategory } from '../services/constant'; + +class AjaxErrors extends Base { + public handleError(options: {reportUrl: string}) { + if (!window.XMLHttpRequest) { + return; + } + const xhrSend = XMLHttpRequest.prototype.send; + const xhrEvent = (event: any) => { + try { + if (event && event.currentTarget && event.currentTarget.status !== 200) { + this.logInfo = { + reportUrl: options.reportUrl, + category: ErrorsCategory.AJAX_ERROR, + grade: GradeTypeEnum.ERROR, + errorUrl: event.target.responseURL, + message: event.target.response, + errorInfo: { + status: event.target.status, + statusText: event.target.statusText, + }, + }; + this.traceInfo(); + } + } catch (error) { + console.log(error); + } + }; + XMLHttpRequest.prototype.send = function() { + if (this.addEventListener) { + this.addEventListener('error', xhrEvent); + this.addEventListener('load', xhrEvent); + this.addEventListener('abort', xhrEvent); + } else { + const tempStateChange = this.onreadystatechange; + this.onreadystatechange = function(event: any) { + tempStateChange.apply(this, arguments); + if (this.readyState === 4) { + xhrEvent(event); + } + }; + } + return xhrSend.apply(this, arguments); + }; + } +} + +export default new AjaxErrors(); diff --git a/src/types.d.ts b/src/errors/index.ts similarity index 73% copy from src/types.d.ts copy to src/errors/index.ts index b7f6058..b213fd0 100644 --- a/src/types.d.ts +++ b/src/errors/index.ts @@ -14,17 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export interface TClientMonitor { - reportUrl: string; - modulesName?: string; -} +import JSErrors from './js'; +import PromiseErrors from './promise'; +import AjaxErrors from './ajax'; -export interface TErrorsType { - jsErrors: boolean; - promiseErrors: boolean; - consoleErrors: boolean; - vueErrors: boolean; - reactErrors: boolean; - ajaxErrors: boolean; - resourceErrors: boolean; -} +export { + JSErrors, PromiseErrors, AjaxErrors, +}; diff --git a/src/errors/jsErrors.ts b/src/errors/js.ts similarity index 86% copy from src/errors/jsErrors.ts copy to src/errors/js.ts index cb7756d..121d19f 100644 --- a/src/errors/jsErrors.ts +++ b/src/errors/js.ts @@ -15,11 +15,10 @@ * limitations under the License. */ -import BaseMonitor from '../services/base'; -import { GradeTypeEnum } from '../services/constant'; -import { ErrorsCategory } from '../services/constant'; +import Base from '../services/base'; +import { GradeTypeEnum, ErrorsCategory } from '../services/constant'; -class JSErrors extends BaseMonitor { +class JSErrors extends Base { public handleErrors(options: {reportUrl: string}) { window.onerror = (message, url, line, col, error) => { this.logInfo = { diff --git a/src/errors/jsErrors.ts b/src/errors/promise.ts similarity index 52% rename from src/errors/jsErrors.ts rename to src/errors/promise.ts index cb7756d..e8ae5c7 100644 --- a/src/errors/jsErrors.ts +++ b/src/errors/promise.ts @@ -15,25 +15,32 @@ * limitations under the License. */ -import BaseMonitor from '../services/base'; -import { GradeTypeEnum } from '../services/constant'; -import { ErrorsCategory } from '../services/constant'; +import Base from '../services/base'; +import { GradeTypeEnum, ErrorsCategory } from '../services/constant'; -class JSErrors extends BaseMonitor { +class PromiseErrors extends Base { public handleErrors(options: {reportUrl: string}) { - window.onerror = (message, url, line, col, error) => { - this.logInfo = { - reportUrl: options.reportUrl, - category: ErrorsCategory.JS_ERROR, - grade: GradeTypeEnum.ERROR, - errorUrl: url, - line, - col, - errorInfo: error, - message, - }; - this.traceInfo(); - }; + window.addEventListener('unhandledrejection', (event) => { + try { + let url = ''; + if (!event || !event.reason) { + return; + } + if (event.reason.config && event.reason.config.url) { + url = event.reason.config.url; + } + this.logInfo = { + reportUrl: options.reportUrl, + category: ErrorsCategory.PROMISE_ERROR, + grade: GradeTypeEnum.ERROR, + errorUrl: url, + message: event.reason, + }; + this.traceInfo(); + } catch (error) { + console.log(error); + } + }); } } -export default new JSErrors(); +export default new PromiseErrors(); diff --git a/src/monitor.ts b/src/monitor.ts index b24faf0..582f1b4 100644 --- a/src/monitor.ts +++ b/src/monitor.ts @@ -14,11 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import JSErrors from './errors/jsErrors'; -import { TClientMonitor, TErrorsType } from './types'; + +import { CustomOptionsType } from './types'; +import { JSErrors, PromiseErrors, AjaxErrors } from './errors/index'; const ClientMonitor = { - errorTypes: { + customOptions: { jsErrors: true, promiseErrors: true, consoleErrors: false, @@ -26,22 +27,26 @@ const ClientMonitor = { reactErrors: false, ajaxErrors: true, resourceErrors: true, - } as TErrorsType, + } as CustomOptionsType, + + register(options: CustomOptionsType) { + const reportUrl = options.reportUrl; - register(options: TClientMonitor & TErrorsType) { - this.errorTypes = options; - if (this.errorTypes.jsErrors) { - this.errorTypes.jsErrors = options.jsErrors; - JSErrors.handleErrors({reportUrl: options.reportUrl}); + this.customOptions = options; + if (this.customOptions.jsErrors) { + this.customOptions.jsErrors = options.jsErrors; + JSErrors.handleErrors({reportUrl}); } - if (this.errorTypes.promiseErrors) { - this.errorTypes.promiseErrors = options.promiseErrors || this.errorTypes.promiseErrors; + if (this.customOptions.promiseErrors) { + this.customOptions.promiseErrors = options.promiseErrors || this.customOptions.promiseErrors; + PromiseErrors.handleErrors({reportUrl}); } - if (this.errorTypes.resourceErrors) { - this.errorTypes.resourceErrors = options.resourceErrors; + if (this.customOptions.resourceErrors) { + this.customOptions.resourceErrors = options.resourceErrors; } - if (this.errorTypes.ajaxErrors) { - this.errorTypes.ajaxErrors = options.ajaxErrors || this.errorTypes.ajaxErrors; + if (this.customOptions.ajaxErrors) { + this.customOptions.ajaxErrors = options.ajaxErrors || this.customOptions.ajaxErrors; + AjaxErrors.handleError({reportUrl}); } }, }; diff --git a/src/services/base.ts b/src/services/base.ts index 5437912..a8b0c6f 100644 --- a/src/services/base.ts +++ b/src/services/base.ts @@ -18,7 +18,7 @@ import Task from './task'; import { ErrorsCategory, GradeTypeEnum } from './constant'; import { errorInfoFeilds } from './types'; -export default class BaseMonitor { +export default class Base { public logInfo: errorInfoFeilds & {reportUrl: string} = { category: ErrorsCategory.UNKNOW_ERROR, grade: GradeTypeEnum.INFO, diff --git a/src/services/report.ts b/src/services/report.ts index a6e080a..81b4a70 100644 --- a/src/services/report.ts +++ b/src/services/report.ts @@ -27,14 +27,15 @@ class Report { if (!this.checkUrl(this.url)) { return; } + console.log(data); + delete data.reportUrl; try { const xhr = new XMLHttpRequest(); xhr.open('POST', this.url, true); xhr.setRequestHeader('Content-Type', 'application/json'); - console.log(data); xhr.send(JSON.stringify(data)); } catch (error) { - // console.log(error); + console.log(error); } } diff --git a/src/services/types.d.ts b/src/services/types.d.ts index d296077..b027d5e 100644 --- a/src/services/types.d.ts +++ b/src/services/types.d.ts @@ -38,7 +38,7 @@ export interface errorInfoFeilds { grade: string; message: any; errorUrl: string; - line: number; - col: number; - errorInfo: any; + line?: number; + col?: number; + errorInfo?: any; } diff --git a/src/types.d.ts b/src/types.d.ts index b7f6058..0d6b2c3 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -14,12 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export interface TClientMonitor { + +export interface CustomOptionsType { reportUrl: string; modulesName?: string; -} - -export interface TErrorsType { jsErrors: boolean; promiseErrors: boolean; consoleErrors: boolean;