This is an automated email from the ASF dual-hosted git repository.

qiuxiafan 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 0dc374c  feat: support adding custom tags to spans (#101)
0dc374c is described below

commit 0dc374ca0ced78d22e51be635c37f5fabe6ed410
Author: Fine0830 <[email protected]>
AuthorDate: Mon Oct 10 15:16:50 2022 +0800

    feat: support adding custom tags to spans (#101)
---
 README.md                       | 12 ++++++++++++
 src/monitor.ts                  | 32 +++++++++++++++++++++++++++++++-
 src/trace/interceptors/fetch.ts | 23 +++++++++++++----------
 src/trace/interceptors/xhr.ts   | 24 +++++++++++++-----------
 src/types.d.ts                  |  6 ++++++
 5 files changed, 75 insertions(+), 22 deletions(-)

diff --git a/README.md b/README.md
index ce4a7cd..8feb2af 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,7 @@ The register method supports the following parameters.
 |detailMode|Boolean|Support tracing http method and url as tags in 
spans.|false|true|
 |noTraceOrigins|(string \| RegExp)[]|Origin in the `noTraceOrigins` list will 
not be traced.|false|[]|
 |traceTimeInterval|Number|Support setting time interval to report 
segments.|false|60000|
+|customTags|Array|Custom Tags|false|-|
 
 ## Collect Metrics Manually
 Use the `setPerformance` method to report metrics at the moment of page loaded 
or any other moment meaningful.
@@ -180,6 +181,17 @@ Vue.config.errorHandler = (error) => {
 }
 ```
 
+## According to different pages or modules, add custom tags to spans.
+
+```js
+app.on('routeChange', function () {
+  ClientMonitor.setCustomTags([
+    { key: 'key1', value: 'value1' },
+    { key: 'key2', value: 'value2' },
+  ]);
+});
+```
+
 # Security Notice
 The SkyWalking client-js agent would be deployed and running outside of your 
datacenter. This means when you introduce this component you should be aware of 
the security impliciations.
 There are various kinds of telemetry relative data would be reported to 
backend separately or through your original HTTP requests.
diff --git a/src/monitor.ts b/src/monitor.ts
index 6c12d7d..3993ecf 100644
--- a/src/monitor.ts
+++ b/src/monitor.ts
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import { CustomOptionsType, CustomReportOptions } from './types';
+import { CustomOptionsType, CustomReportOptions, TagOption } from './types';
 import { JSErrors, PromiseErrors, AjaxErrors, ResourceErrors, VueErrors, 
FrameErrors } from './errors/index';
 import tracePerf from './performance/index';
 import traceSegment, { setConfig } from './trace/segment';
@@ -40,6 +40,7 @@ const ClientMonitor = {
       ...this.customOptions,
       ...configs,
     };
+    this.validation();
     this.catchErrors(this.customOptions);
     if (!this.customOptions.enableSPA) {
       this.performance(this.customOptions);
@@ -106,6 +107,35 @@ const ClientMonitor = {
   reportFrameErrors(configs: CustomReportOptions, error: Error) {
     FrameErrors.handleErrors(configs, error);
   },
+  validation(customTags: TagOption[]) {
+    // const { customTags } = this.customOptions;
+    if (!customTags) {
+      return false;
+    }
+    if (!Array.isArray(customTags)) {
+      this.customOptions.customTags = undefined;
+      console.error('customTags error');
+      return false;
+    }
+    let isTags = true;
+    for (const ele of this.customOptions.customTags) {
+      if (!(ele && ele.key && ele.value)) {
+        isTags = false;
+      }
+    }
+    if (!isTags) {
+      this.customOptions.customTags = undefined;
+      console.error('customTags error');
+      return false;
+    }
+    return true;
+  },
+  setCustomTags(tags: TagOption[]) {
+    const opt = { ...this.customOptions, customTags: tags };
+    if (this.validation(tags)) {
+      setConfig(opt);
+    }
+  },
 };
 
 export default ClientMonitor;
diff --git a/src/trace/interceptors/fetch.ts b/src/trace/interceptors/fetch.ts
index bc231e8..6de8e32 100644
--- a/src/trace/interceptors/fetch.ts
+++ b/src/trace/interceptors/fetch.ts
@@ -102,6 +102,16 @@ export default function windowFetch(options: 
CustomOptionsType, segments: Segmen
         new Base().traceInfo(logInfo);
       }
       if (hasTrace) {
+        const tags = [
+          {
+            key: 'http.method',
+            value: args[1].method || 'GET',
+          },
+          {
+            key: 'url',
+            value: (response && response.url) || 
`${url.protocol}//${url.host}${url.pathname}`,
+          },
+        ];
         const endTime = new Date().getTime();
         const exitSpan: SpanFields = {
           operationName: customConfig.pagePath,
@@ -115,16 +125,9 @@ export default function windowFetch(options: 
CustomOptionsType, segments: Segmen
           componentId: ComponentId,
           peer: url.host,
           tags: customConfig.detailMode
-            ? [
-                {
-                  key: 'http.method',
-                  value: args[1].method || 'GET',
-                },
-                {
-                  key: 'url',
-                  value: (response && response.url) || 
`${url.protocol}//${url.host}${url.pathname}`,
-                },
-              ]
+            ? customConfig.customTags
+              ? [...tags, ...customConfig.customTags]
+              : tags
             : undefined,
         };
         segment = {
diff --git a/src/trace/interceptors/xhr.ts b/src/trace/interceptors/xhr.ts
index 8074f0b..791c2ec 100644
--- a/src/trace/interceptors/xhr.ts
+++ b/src/trace/interceptors/xhr.ts
@@ -148,7 +148,16 @@ export default function xhrInterceptor(options: 
CustomOptionsType, segments: Seg
           if (segCollector[i].event.status) {
             responseURL = new URL(segCollector[i].event.responseURL);
           }
-
+          const tags = [
+            {
+              key: 'http.method',
+              value: config[0],
+            },
+            {
+              key: 'url',
+              value: segCollector[i].event.responseURL || 
`${url.protocol}//${url.host}${url.pathname}`,
+            },
+          ];
           const exitSpan: SpanFields = {
             operationName: customConfig.pagePath,
             startTime: segCollector[i].startTime,
@@ -161,16 +170,9 @@ export default function xhrInterceptor(options: 
CustomOptionsType, segments: Seg
             componentId: ComponentId,
             peer: responseURL.host,
             tags: customConfig.detailMode
-              ? [
-                  {
-                    key: 'http.method',
-                    value: config[0],
-                  },
-                  {
-                    key: 'url',
-                    value: segCollector[i].event.responseURL || 
`${url.protocol}//${url.host}${url.pathname}`,
-                  },
-                ]
+              ? customConfig.customTags
+                ? [...tags, ...customConfig.customTags]
+                : tags
               : undefined,
           };
           segment = {
diff --git a/src/types.d.ts b/src/types.d.ts
index 6c158e0..764639c 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -27,6 +27,7 @@ export interface CustomOptionsType extends 
CustomReportOptions {
   detailMode?: boolean;
   noTraceOrigins?: (string | RegExp)[];
   traceTimeInterval?: number;
+  customTags?: TagOption[];
 }
 
 export interface CustomReportOptions {
@@ -35,3 +36,8 @@ export interface CustomReportOptions {
   pagePath: string;
   serviceVersion: string;
 }
+
+export type TagOption = {
+  key: string;
+  value: string;
+};

Reply via email to