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 6d5ccebf75747400b8e1a0e81e00dc8a1a7e9f3e Author: Qiuxia Fan <[email protected]> AuthorDate: Sat Dec 14 16:42:38 2019 +0800 feat: add monitor --- .gitignore | 2 +- src/errors/ajaxErrors.ts | 63 ------------- src/errors/jsErrors.ts | 65 ++++++------- src/monitor.ts | 4 +- src/services/TaskQueue.ts | 33 ------- src/services/baseMonitor.ts | 152 ------------------------------- src/services/config.ts | 28 ------ src/{types.d.ts => services/constant.ts} | 26 +++--- src/services/report.ts | 68 ++++++++++++++ src/services/reportLog.ts | 89 ------------------ src/{types.d.ts => services/task.ts} | 32 ++++--- src/services/trace.ts | 78 ++++++++++++++++ src/services/type.d.ts | 0 src/{ => services}/types.d.ts | 19 ++-- src/services/utils.ts | 38 -------- src/types.d.ts | 3 +- 16 files changed, 229 insertions(+), 471 deletions(-) diff --git a/.gitignore b/.gitignore index a6f6049..4abf3c4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ # misc .DS_Store - +.vscode/* npm-debug.log* yarn-debug.log* yarn-error.log* diff --git a/src/errors/ajaxErrors.ts b/src/errors/ajaxErrors.ts deleted file mode 100644 index 6333430..0000000 --- a/src/errors/ajaxErrors.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** -* 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 { ErrorsCategory } from '../services/config'; -export default class XHRError { - - constructor() { - this.handleError(); - } - - handleError(){ - if(!window.XMLHttpRequest){ - return; - } - let xhrSend = XMLHttpRequest.prototype.send; - let _handleEvent = (event: Event) => { - try { - if (event && event.currentTarget && event.currentTarget.status !== 200) { - // this.category = ErrorsCategory.AJAX_ERROR; - // this.msg = event.target.response; - // this.url = event.target.responseURL; - // this.error = { - // status: event.target.status, - // statusText: event.target.statusText - // }; - // this.recordError(); - } - } catch (error) { - console.log(error); - } - }; - XMLHttpRequest.prototype.send = function(){ - if (this.addEventListener){ - this.addEventListener('error', _handleEvent); - this.addEventListener('load', _handleEvent); - this.addEventListener('abort', _handleEvent); - } else { - let tempStateChange = this.onreadystatechange; - this.onreadystatechange = function(event: any){ - tempStateChange.apply(this,arguments); - if (this.readyState === 4) { - _handleEvent(event); - } - } - } - return xhrSend.apply(this,arguments); - } - } - -} \ No newline at end of file diff --git a/src/errors/jsErrors.ts b/src/errors/jsErrors.ts index b16035f..29e9b79 100644 --- a/src/errors/jsErrors.ts +++ b/src/errors/jsErrors.ts @@ -1,36 +1,39 @@ /** -* 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. -*/ + * 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. + */ -export default class JSErrors{ +import Trace from '../services/trace'; +import { GradeTypeEnum } from '../services/constant'; +import { ErrorsCategory } from '../services/constant'; - constructor() { - this.handleErrors(); - } - - private handleErrors() { - window.onerror = (msg, url, line, col, error) => { - try { - console.log('msg', msg); - console.log(url); - console.log(line); - console.log(error); - } catch(error) { - console.log("js errors",error); - } - } +class JSErrors extends Trace { + public handleErrors(options: {reportUrl: string}) { + window.onerror = (message, url, line, col, error) => { + this.logInfo = { + reportUrl: options.reportUrl, + category: ErrorsCategory.JS_ERROR, + grade: GradeTypeEnum.WARNING, + url, + line, + col, + errorInfo: error, + message, + }; + this.traceInfo(); + }; } } +export default new JSErrors(); diff --git a/src/monitor.ts b/src/monitor.ts index 5b0b817..8a1cb61 100644 --- a/src/monitor.ts +++ b/src/monitor.ts @@ -29,11 +29,11 @@ export default class ClientMonitor { resourceErrors: true, }; - public init(options: TClientMonitor) { + public init(options: TClientMonitor & TErrorsType) { this.errorTypes = options; if (this.errorTypes.jsErrors) { this.errorTypes.jsErrors = options.jsErrors; - new JSErrors(); + JSErrors.handleErrors({reportUrl: options.reportUrl}); } if (this.errorTypes.promiseErrors) { this.errorTypes.promiseErrors = options.promiseErrors || this.errorTypes.promiseErrors; diff --git a/src/services/TaskQueue.ts b/src/services/TaskQueue.ts deleted file mode 100644 index 4c8e516..0000000 --- a/src/services/TaskQueue.ts +++ /dev/null @@ -1,33 +0,0 @@ -import API from "./api.js"; - -/** - * 消息队列 - */ -var TaskQueue = { - - queues:[], //待处理消息列表 - - /** - * 添加消息 - * @param {*} reportUrl 上报url - * @param {*} data 上报数据 - */ - add:function(reportUrl,data){ - this.queues.push({reportUrl,data}); - }, - - /** - * 统一上报 - */ - fire:function(){ - if(!this.queues || this.queues.length === 0){ - return; - } - let item = this.queues[0]; - item.reportUrl && new API(item.reportUrl).report(item.data); - this.queues.splice(0,1); - this.fire(); //递归 - } -}; - -export default TaskQueue; \ No newline at end of file diff --git a/src/services/baseMonitor.ts b/src/services/baseMonitor.ts deleted file mode 100644 index cd04dc9..0000000 --- a/src/services/baseMonitor.ts +++ /dev/null @@ -1,152 +0,0 @@ -/** -* 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 { ErrorLevelEnum,ErrorCategoryEnum } from "./config"; -import utils from "./utils"; -import TaskQueue from "./TaskQueue" - -/** - * 监控基类 - */ -class BaseMonitor { - - /** - * 上报错误地址 - * @param {*} params { reportUrl,extendsInfo } - */ - constructor(params){ - this.category = ErrorCategoryEnum.UNKNOW_ERROR; //错误类型 - this.level = ErrorLevelEnum.INFO; //错误等级 - this.msg = ""; //错误信息 - this.url = ""; //错误信息地址 - this.line = ""; //行数 - this.col = ""; //列数 - this.errorObj = ""; //错误堆栈 - - this.reportUrl = params.reportUrl; //上报错误地址 - this.extendsInfo = params.extendsInfo; //扩展信息 - } - - /** - * 记录错误信息 - */ - recordError(){ - this.handleRecordError(); - //延迟记录日志 - setTimeout(()=>{ - TaskQueue.fire(); - },100); - } - - /** - * 处理记录日志 - */ - handleRecordError(){ - try { - if(!this.msg){ - return; - } - //过滤掉错误上报地址 - if( this.reportUrl && this.url && this.url.toLowerCase().indexOf(this.reportUrl.toLowerCase())>=0 ){ - console.log("统计错误接口异常",this.msg); - return; - } - let errorInfo = this.handleErrorInfo(); - - console.log("\n````````````````````` "+this.category+" `````````````````````\n",errorInfo) - - //记录日志 - TaskQueue.add(this.reportUrl,errorInfo); - - } catch (error) { - console.log(error); - } - } - - /** - * 处理错误信息 - * @param {*} extendsInfo - */ - handleErrorInfo(){ - let txt = "错误类别: " + this.category + "\r\n"; - txt += "日志信息: " + this.msg + "\r\n"; - txt += "url: " + this.url + "\r\n"; - switch(this.category){ - case ErrorCategoryEnum.JS_ERROR: - txt += "错误行号: " + this.line + "\r\n"; - txt += "错误列号: " + this.col + "\r\n"; - if (this.errorObj && this.errorObj.stack) { - txt += "错误栈: " + this.errorObj.stack + "\r\n"; - } - break; - default: - txt += "其他错误: " + JSON.stringify(this.errorObj) + "\r\n"; - break; - } - let deviceInfo = this.getDeviceInfo(); - txt += "设备信息: " + deviceInfo; //设备信息 - let extendsInfo = this.getExtendsInfo(); - let recordInfo = extendsInfo; - recordInfo.category = this.category; //错误分类 - recordInfo.logType = this.level; //错误级别 - recordInfo.logInfo = txt; //错误信息 - recordInfo.deviceInfo = deviceInfo; //设备信息 - return recordInfo; - } - - /** - * 获取扩展信息 - */ - getExtendsInfo(){ - try { - let ret = {}; - let extendsInfo = this.extendsInfo || {}; - let dynamicParams; - if(utils.isFunction(extendsInfo.getDynamic)){ - dynamicParams = extendsInfo.getDynamic(); //获取动态参数 - } - //判断动态方法返回的参数是否是对象 - if(utils.isObject(dynamicParams)){ - extendsInfo = {...extendsInfo,...dynamicParams}; - } - //遍历扩展信息,排除动态方法 - for(var key in extendsInfo){ - if(!utils.isFunction(extendsInfo[key])){ //排除获取动态方法 - ret[key] = extendsInfo[key]; - } - } - return ret; - } catch (error) { - console.log('call getExtendsInfo error',error); - return {}; - } - } - - /** - * 获取设备信息 - */ - getDeviceInfo(){ - try { - let deviceInfo = DeviceInfo.getDeviceInfo(); - return JSON.stringify(deviceInfo); - } catch (error) { - console.log(error); - return ""; - } - } - -} -export default BaseMonitor; diff --git a/src/services/config.ts b/src/services/config.ts deleted file mode 100644 index a2c420a..0000000 --- a/src/services/config.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** -* 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. -*/ -export enum ErrorsCategory { - AJAX_ERROR = 'ajaxError', - RESOURCE_ERROR = 'resourceError', - VUE_ERROR = 'vueError', - PROMISE_ERROR = 'promiseError', - JS_ERROR = 'jsError', - CONSOLE_INFO = 'consoleInfo', - CONSOLE_WARN = 'consoleWarn', - CONSOLE_ERROR = 'consoleError', - CROSS_SCRIPT_ERROR = 'crossSrciptError', - UNKNOW_ERROR = 'unknowError' -} diff --git a/src/types.d.ts b/src/services/constant.ts similarity index 64% copy from src/types.d.ts copy to src/services/constant.ts index 12f8276..8a1b711 100644 --- a/src/types.d.ts +++ b/src/services/constant.ts @@ -14,16 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export interface TClientMonitor extends TErrorsType { - reportUrl: string; +export enum ErrorsCategory { + AJAX_ERROR = 'ajaxError', + RESOURCE_ERROR = 'resourceError', + VUE_ERROR = 'vueError', + PROMISE_ERROR = 'promiseError', + JS_ERROR = 'jsError', + CONSOLE_INFO = 'consoleInfo', + CONSOLE_WARN = 'consoleWarn', + CONSOLE_ERROR = 'consoleError', + CROSS_SCRIPT_ERROR = 'crossSrciptError', + UNKNOW_ERROR = 'unknowError', } - -export interface TErrorsType { - jsErrors: boolean; - promiseErrors: boolean; - consoleErrors: boolean; - vueErrors: boolean; - reactErrors: boolean; - ajaxErrors: boolean; - resourceErrors: boolean; +export enum GradeTypeEnum { + INFO = 'Info', + WARNING = 'Warning', + ERROR = 'Error', } diff --git a/src/services/report.ts b/src/services/report.ts new file mode 100644 index 0000000..a6e080a --- /dev/null +++ b/src/services/report.ts @@ -0,0 +1,68 @@ +/** + * 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. + */ + +class Report { + + private url: string = ''; + + constructor(url: string) { + this.url = url; + } + + public sendByXhr(data: any) { + if (!this.checkUrl(this.url)) { + return; + } + 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); + } + } + + private reportByImg(data: any) { + if (!this.checkUrl(this.url)) { + return; + } + try { + const imgObj = new Image(); + + imgObj.src = `${this.url}?v=${new Date().getTime()}&${this.formatParams(data)}`; + } catch (error) { + // console.log(error); + } + } + + private formatParams(data: any) { + return Object.keys(data).map((name: string) => + `${encodeURIComponent(name)}=${encodeURIComponent(data[name])}`, + ).join('&'); + } + + private checkUrl(url: string) { + if (!url) { + return; + } + const urlRule = /^[hH][tT][tT][pP]([sS]?):\/\//; + return urlRule.test(url); + } +} +export default Report; diff --git a/src/services/reportLog.ts b/src/services/reportLog.ts deleted file mode 100644 index 1425f97..0000000 --- a/src/services/reportLog.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** -* 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. -*/ -class API { - - constructor(url){ - this.url = url; - } - - /** - * 上报信息 (默认方式) - */ - report(data){ - if(!this.checkUrl(this.url)){ - console.log("上报信息url地址格式不正确,url=",this.url); - return; - } - console.log("上报地址:"+this.url); - this.sendInfo(data); - } - - /** - * 发送消息 - */ - sendInfo(data){ - try { - var xhr = new XMLHttpRequest(); - xhr.open("POST",this.url,true); - //xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.send(JSON.stringify(data)); - } catch (error) { - console.log(error); - } - } - - /** - * 通过img方式上报信息 - */ - reportByImg(data){ - if(!this.checkUrl(this.url)){ - console.log("上报信息url地址格式不正确,url=",this.url); - return; - } - try { - var img = new Image(); - img.src = this.url+'?v='+new Date().getTime()+'&' + this.formatParams(data); - } catch (error) { - console.log(error); - } - } - - /* - *格式化参数 - */ - formatParams(data) { - var arr = []; - for (var name in data) { - arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name])); - } - return arr.join("&"); - } - - /** - * 检测URL - */ - checkUrl(url){ - if(!url){ - return false; - } - var urlRule =/^[hH][tT][tT][pP]([sS]?):\/\//; - return urlRule.test(url); - } - -} -export default API; \ No newline at end of file diff --git a/src/types.d.ts b/src/services/task.ts similarity index 62% copy from src/types.d.ts copy to src/services/task.ts index 12f8276..4f51a17 100644 --- a/src/types.d.ts +++ b/src/services/task.ts @@ -14,16 +14,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export interface TClientMonitor extends TErrorsType { - reportUrl: string; -} +import Report from './report'; + +class TaskQueue { + private queues: any[] = []; -export interface TErrorsType { - jsErrors: boolean; - promiseErrors: boolean; - consoleErrors: boolean; - vueErrors: boolean; - reactErrors: boolean; - ajaxErrors: boolean; - resourceErrors: boolean; + public addTask(reportUrl: string, data: any) { + this.queues.push({reportUrl, data}); + } + + public fireTasks() { + if (!this.queues || !this.queues.length) { + return; + } + const item = this.queues[0]; + if (item.reportUrl) { + new Report(item.reportUrl).sendByXhr(item.data); + } + this.queues.splice(0, 1); + this.fireTasks(); + } } + +export default new TaskQueue(); diff --git a/src/services/trace.ts b/src/services/trace.ts new file mode 100644 index 0000000..7bc6f4a --- /dev/null +++ b/src/services/trace.ts @@ -0,0 +1,78 @@ +/** + * 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 Task from './task'; +import { ErrorsCategory, GradeTypeEnum } from './constant'; +import { TraceFields } from './types'; + +export default class Trace { + public logInfo: TraceFields = { + category: ErrorsCategory.UNKNOW_ERROR, + grade: GradeTypeEnum.INFO, + url: '', + line: 0, + col: 0, + errorInfo: '', + reportUrl: '', + message: '', + }; + + public traceInfo() { + this.handleRecordError(); + setTimeout(() => { + Task.fireTasks(); + }, 100); + } + + private handleRecordError() { + try { + if (!this.logInfo.message) { + return; + } + if (this.logInfo.reportUrl && this.logInfo.url && + this.logInfo.url.toLowerCase().includes(this.logInfo.reportUrl.toLowerCase())) { + return; + } + const errorInfo = this.handleErrorInfo(); + + Task.addTask(this.logInfo.reportUrl, errorInfo); + + } catch (error) { + // console.log(error); + } + } + + private handleErrorInfo() { + let message = `error category:${this.logInfo.category}\r\n log info:${this.logInfo.message}\r\n + error url: ${this.logInfo.url}\r\n `; + switch (this.logInfo.category) { + case ErrorsCategory.JS_ERROR: + message += `error line number: ${this.logInfo.line}\r\n error col number:${this.logInfo.col}\r\n`; + if (this.logInfo.errorInfo && this.logInfo.errorInfo.stack) { + message += `error stack: ${this.logInfo.errorInfo.stack}\r\n`; + } + break; + default: + message += `other error: ${this.logInfo.errorInfo}\r\n`; + break; + } + const recordInfo = { + ...this.logInfo, + message, + }; + return recordInfo; + } +} diff --git a/src/services/type.d.ts b/src/services/type.d.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/types.d.ts b/src/services/types.d.ts similarity index 76% copy from src/types.d.ts copy to src/services/types.d.ts index 12f8276..0c30fdd 100644 --- a/src/types.d.ts +++ b/src/services/types.d.ts @@ -14,16 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export interface TClientMonitor extends TErrorsType { +export interface TraceFields { + category: string; + grade: string; + message: any; + url: string; + line: number; + col: number; + errorInfo: any; reportUrl: string; } - -export interface TErrorsType { - jsErrors: boolean; - promiseErrors: boolean; - consoleErrors: boolean; - vueErrors: boolean; - reactErrors: boolean; - ajaxErrors: boolean; - resourceErrors: boolean; -} diff --git a/src/services/utils.ts b/src/services/utils.ts deleted file mode 100644 index cdab32d..0000000 --- a/src/services/utils.ts +++ /dev/null @@ -1,38 +0,0 @@ -export default { - - type(obj) { - return Object.prototype.toString.call(obj).replace(/\[object\s|\]/g, ''); - }, - - isFunction(func) { - return this.type(func) === "Function"; - }, - - isArray(list) { - return this.type(list) === 'Array'; - }, - - /** - * 是否为null - * @param {String} str - */ - isNull(str) { - return str == undefined || str == '' || str == null; - }, - - /** - * 对象是否为空 - * @param {*} obj - */ - objectIsNull(obj) { - return JSON.stringify(obj) === "{}"; - }, - - /** - * 是否是对象 - * @param {*} obj - */ - isObject(obj){ - return this.type(obj) === "Object"; - } -} \ No newline at end of file diff --git a/src/types.d.ts b/src/types.d.ts index 12f8276..b7f6058 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -14,8 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export interface TClientMonitor extends TErrorsType { +export interface TClientMonitor { reportUrl: string; + modulesName?: string; } export interface TErrorsType {
