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 2021/04/09 11:54:35 UTC

[skywalking-client-js] branch master updated: feat: catch frames errors (#47)

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 0720663  feat: catch frames errors (#47)
0720663 is described below

commit 0720663d2f554a02b23edccade6725f417b6f44e
Author: Qiuxia Fan <fi...@outlook.com>
AuthorDate: Fri Apr 9 19:54:27 2021 +0800

    feat: catch frames errors (#47)
---
 README.md                            | 74 +++++++++++++++++++++++++++++++++++-
 package-lock.json                    |  2 +-
 src/{types.d.ts => errors/frames.ts} | 39 +++++++++++--------
 src/errors/index.ts                  |  5 +--
 src/monitor.ts                       | 11 ++++--
 src/performance/index.ts             |  2 +-
 src/types.d.ts                       | 13 ++++---
 7 files changed, 116 insertions(+), 30 deletions(-)

diff --git a/README.md b/README.md
index bbbaf8d..849ac9e 100644
--- a/README.md
+++ b/README.md
@@ -87,7 +87,7 @@ In the initialized configuration item, set enableSPA to true, which will turn on
 2. Manual reporting  
 This method can be used in all single page application scenarios. This method can be used if the first method is invalid.    
 The SDK provides a set page method to manually update the page name when data is reported. When this method is called, the page PV will be re reported by default. For details, see setPerformance().  
-```
+```js
 app.on('routeChange', function (next) {
   ClientMonitor.setPerformance({
     collector: 'http://127.0.0.1:8080',
@@ -103,6 +103,78 @@ app.on('routeChange', function (next) {
 
 Support tracking these([XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) and [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)) two modes of data requests. At the same time, Support tracking libraries and tools that base on XMLHttpRequest and fetch, such as [Axios](https://github.com/axios/axios), [SuperAgent](https://github.com/visionmedia/superagent), [OpenApi](https://www.openapis.org/) and so on.
 
+## Catching errors in frames, including React, Angular, Vue.
+
+```js
+// Angular
+import { ErrorHandler } from '@angular/core';
+import ClientMonitor from 'skywalking-client-js';
+export class AppGlobalErrorhandler implements ErrorHandler {
+  handleError(error) {
+    ClientMonitor.reportFrameErrors({
+      collector: 'http://127.0.0.1',
+      service: 'angular-demo',
+      pagePath: '/app',
+      serviceVersion: 'v1.0.0',
+    }, error);
+  }
+}
+@NgModule({
+  ...
+  providers: [{provide: ErrorHandler, useClass: AppGlobalErrorhandler}]
+})
+class AppModule {}
+```
+
+```js
+// React
+class ErrorBoundary extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = { hasError: false };
+  }
+
+  static getDerivedStateFromError(error) {
+    // Update state so the next render will show the fallback UI.
+    return { hasError: true };
+  }
+
+  componentDidCatch(error, errorInfo) {
+    // You can also log the error to an error reporting service
+    ClientMonitor.reportFrameErrors({
+      collector: 'http://127.0.0.1',
+      service: 'react-demo',
+      pagePath: '/app',
+      serviceVersion: 'v1.0.0',
+    }, error);
+  }
+
+  render() {
+    if (this.state.hasError) {
+      // You can render any custom fallback UI
+      return <h1>Something went wrong.</h1>;
+    }
+
+    return this.props.children; 
+  }
+}
+<ErrorBoundary>
+  <MyWidget />
+</ErrorBoundary>
+```
+
+```js
+// Vue
+Vue.config.errorHandler = (error) => {
+  ClientMonitor.reportFrameErrors({
+    collector: 'http://127.0.0.1',
+    service: 'vue-demo',
+    pagePath: '/app',
+    serviceVersion: 'v1.0.0',
+  }, error);
+}
+```
+
 # Demo project
 
 Demo project provides instrumented web application with necessary environment, you could just simple use it to see the data SkyWalking collected and how SkyWalking visualizes on the UI. 
diff --git a/package-lock.json b/package-lock.json
index 065ca61..d02c275 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "skywalking-client-js",
-  "version": "0.3.0",
+  "version": "0.5.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/src/types.d.ts b/src/errors/frames.ts
similarity index 50%
copy from src/types.d.ts
copy to src/errors/frames.ts
index f98546b..7471a8d 100644
--- a/src/types.d.ts
+++ b/src/errors/frames.ts
@@ -15,19 +15,28 @@
  * limitations under the License.
  */
 
-export interface CustomOptionsType {
-  collector?: string;
-  service: string;
-  pagePath: string;
-  serviceVersion: string;
-  jsErrors?: boolean;
-  apiErrors?: boolean;
-  resourceErrors?: boolean;
-  autoTracePerf?: boolean;
-  useFmp?: boolean;
-  enableSPA?: boolean;
-  vue?: any;
-  traceSDKInternal?: boolean;
-  detailMode?: boolean;
-  noTraceOrigins?: (string | RegExp)[];
+import uuid from '../services/uuid';
+import Base from '../services/base';
+import { GradeTypeEnum, ErrorsCategory } from '../services/constant';
+
+class FrameErrors extends Base {
+  public handleErrors(
+    options: { service: string; serviceVersion: string; pagePath: string; collector?: string },
+    error: Error,
+  ) {
+    this.logInfo = {
+      uniqueId: uuid(),
+      service: options.service,
+      serviceVersion: options.serviceVersion,
+      pagePath: options.pagePath,
+      category: ErrorsCategory.JS_ERROR,
+      grade: GradeTypeEnum.ERROR,
+      errorUrl: error.name || location.href,
+      message: error.message,
+      collector: options.collector || location.origin,
+      stack: error.stack,
+    };
+    this.traceInfo();
+  }
 }
+export default new FrameErrors();
diff --git a/src/errors/index.ts b/src/errors/index.ts
index 180a7ba..4fd6eec 100644
--- a/src/errors/index.ts
+++ b/src/errors/index.ts
@@ -20,7 +20,6 @@ import PromiseErrors from './promise';
 import AjaxErrors from './ajax';
 import ResourceErrors from './resource';
 import VueErrors from './vue';
+import FrameErrors from './frames';
 
-export {
-  JSErrors, PromiseErrors, AjaxErrors, ResourceErrors, VueErrors,
-};
+export { JSErrors, PromiseErrors, AjaxErrors, ResourceErrors, VueErrors, FrameErrors };
diff --git a/src/monitor.ts b/src/monitor.ts
index 8844305..c2cea24 100644
--- a/src/monitor.ts
+++ b/src/monitor.ts
@@ -15,8 +15,8 @@
  * limitations under the License.
  */
 
-import { CustomOptionsType } from './types';
-import { JSErrors, PromiseErrors, AjaxErrors, ResourceErrors, VueErrors } from './errors/index';
+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';
 
@@ -39,7 +39,7 @@ const ClientMonitor = {
       ...this.customOptions,
       ...configs,
     };
-    this.errors(this.customOptions);
+    this.catchErrors(this.customOptions);
     if (!this.customOptions.enableSPA) {
       this.performance(this.customOptions);
     }
@@ -70,7 +70,7 @@ const ClientMonitor = {
       );
     }
   },
-  errors(options: CustomOptionsType) {
+  catchErrors(options: CustomOptionsType) {
     const { service, pagePath, serviceVersion, collector } = options;
 
     if (options.jsErrors) {
@@ -95,6 +95,9 @@ const ClientMonitor = {
     };
     this.performance(this.customOptions);
   },
+  reportFrameErrors(configs: CustomReportOptions, error: Error) {
+    FrameErrors.handleErrors(configs, error);
+  },
 };
 
 export default ClientMonitor;
diff --git a/src/performance/index.ts b/src/performance/index.ts
index 9c5d8ef..4cb068c 100644
--- a/src/performance/index.ts
+++ b/src/performance/index.ts
@@ -51,7 +51,7 @@ class TracePerf {
       new Report('PERF', options.collector).sendByXhr(perfInfo);
       // clear perf data
       this.clearPerf();
-    }, 30000);
+    }, 6000);
   }
 
   private clearPerf() {
diff --git a/src/types.d.ts b/src/types.d.ts
index f98546b..b22714e 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -15,11 +15,7 @@
  * limitations under the License.
  */
 
-export interface CustomOptionsType {
-  collector?: string;
-  service: string;
-  pagePath: string;
-  serviceVersion: string;
+export interface CustomOptionsType extends CustomReportOptions {
   jsErrors?: boolean;
   apiErrors?: boolean;
   resourceErrors?: boolean;
@@ -31,3 +27,10 @@ export interface CustomOptionsType {
   detailMode?: boolean;
   noTraceOrigins?: (string | RegExp)[];
 }
+
+export interface CustomReportOptions {
+  collector?: string;
+  service: string;
+  pagePath: string;
+  serviceVersion: string;
+}