You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2020/07/26 03:51:38 UTC

[skywalking-nodejs] 13/23: Refactor http plugin and add http.url tag

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

kezhenxu94 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-nodejs.git

commit af8c42871b7cb6966dd117a6118b4573d68be877
Author: kezhenxu94 <ke...@163.com>
AuthorDate: Wed Jun 24 20:36:09 2020 +0800

    Refactor http plugin and add http.url tag
---
 src/Tag.ts                |  7 ++++
 src/plugins/HttpPlugin.ts | 88 +++++++++++++++++++++++++----------------------
 2 files changed, 54 insertions(+), 41 deletions(-)

diff --git a/src/Tag.ts b/src/Tag.ts
index a64cb73..229fea4 100644
--- a/src/Tag.ts
+++ b/src/Tag.ts
@@ -38,4 +38,11 @@ export default {
       val: `${val}`,
     } as Tag;
   },
+  httpURL: (val: string | undefined): Tag => {
+    return {
+      key: 'http.url',
+      overridable: true,
+      val: `${val}`,
+    } as Tag;
+  },
 };
diff --git a/src/plugins/HttpPlugin.ts b/src/plugins/HttpPlugin.ts
index ce60d27..097929a 100644
--- a/src/plugins/HttpPlugin.ts
+++ b/src/plugins/HttpPlugin.ts
@@ -41,46 +41,7 @@ class HttpPlugin implements SwPlugin {
 
   install(): void {
     this.interceptClientRequest();
-
-    const http = require('http');
-
-    ((original) => {
-      http.Server.prototype.emit = function (event: string | symbol, ...args: any[]): boolean {
-        logger.debug('Intercepting http.Server.prototype.emit');
-        if (event === 'request') {
-          if (!(args[0] instanceof IncomingMessage) && !(args[1] instanceof ServerResponse)) {
-            logger.debug('args[0] is not IncomingMessage or args[1] is not ServerResponse');
-            return original.apply(this, arguments);
-          }
-          const req = args[0] as IncomingMessage;
-          const res = args[1] as ServerResponse;
-
-          const headers = req.rawHeaders;
-          const headersMap: { [key: string]: string } = {};
-
-          for (let i = 0; i < headers.length / 2; i += 2) {
-            headersMap[headers[i]] = headers[i + 1];
-          }
-
-          const carrier = new ContextCarrier();
-          carrier.items.forEach((item) => {
-            if (headersMap.hasOwnProperty(item.key)) {
-              item.value = headersMap[item.key];
-            }
-          });
-
-          const span = ContextManager.current.newEntrySpan('/', carrier).start();
-          span.operation = req.url || '/';
-          span.component = Component.HTTP_SERVER;
-          span.layer = SpanLayer.HTTP;
-
-          res.on('finish', () => {
-            span.tag(Tag.httpStatusCode(res.statusCode)).tag(Tag.httpStatusMsg(res.statusMessage)).stop();
-          });
-        }
-        return original.apply(this, arguments);
-      };
-    })(http.Server.prototype.emit);
+    this.interceptServerRequest();
   }
 
   private interceptClientRequest() {
@@ -101,7 +62,7 @@ class HttpPlugin implements SwPlugin {
     ): ClientRequest => {
       logger.debug(`url is ${typeof url}: ${url}`);
 
-      const { host: peer, pathname: operation } =
+      const { host: peer, pathname } =
         url instanceof URL
           ? url
           : typeof url === 'string'
@@ -110,10 +71,12 @@ class HttpPlugin implements SwPlugin {
               host: url.host || url.hostname || 'unknown',
               pathname: url.path || '/',
             };
+      const operation = (pathname || '/').replace(/\?.*$/g, '');
 
       const span = ContextManager.current.newExitSpan(operation, peer).start();
       span.component = Component.HTTP;
       span.layer = SpanLayer.HTTP;
+      span.tag(Tag.httpURL(peer + pathname));
 
       const snapshot = ContextManager.current.capture();
 
@@ -142,6 +105,49 @@ class HttpPlugin implements SwPlugin {
       return request;
     };
   }
+
+  private interceptServerRequest() {
+    const http = require('http');
+
+    ((original) => {
+      http.Server.prototype.emit = function (event: string | symbol, ...args: any[]): boolean {
+        logger.debug('Intercepting http.Server.prototype.emit');
+        if (event === 'request') {
+          if (!(args[0] instanceof IncomingMessage) && !(args[1] instanceof ServerResponse)) {
+            logger.debug('args[0] is not IncomingMessage or args[1] is not ServerResponse');
+            return original.apply(this, arguments);
+          }
+          const req = args[0] as IncomingMessage;
+          const res = args[1] as ServerResponse;
+
+          const headers = req.rawHeaders;
+          const headersMap: { [key: string]: string } = {};
+
+          for (let i = 0; i < headers.length / 2; i += 2) {
+            headersMap[headers[i]] = headers[i + 1];
+          }
+
+          const carrier = new ContextCarrier();
+          carrier.items.forEach((item) => {
+            if (headersMap.hasOwnProperty(item.key)) {
+              item.value = headersMap[item.key];
+            }
+          });
+
+          const span = ContextManager.current.newEntrySpan('/', carrier).start();
+          span.operation = (req.url || '/').replace(/\?.*/g, '');
+          span.component = Component.HTTP_SERVER;
+          span.layer = SpanLayer.HTTP;
+          span.tag(Tag.httpURL(req.url));
+
+          res.on('finish', () => {
+            span.tag(Tag.httpStatusCode(res.statusCode)).tag(Tag.httpStatusMsg(res.statusMessage)).stop();
+          });
+        }
+        return original.apply(this, arguments);
+      };
+    })(http.Server.prototype.emit);
+  }
 }
 
 // noinspection JSUnusedGlobalSymbols