Add http.method to plugins (#26)


Co-authored-by: Zhenxu Ke <kezhenxu94@apache.org>
diff --git a/src/Tag.ts b/src/Tag.ts
index 229fea4..95e8ab3 100644
--- a/src/Tag.ts
+++ b/src/Tag.ts
@@ -24,23 +24,33 @@
 }
 
 export default {
-  httpStatusCode: (val: string | number | undefined): Tag => {
+  httpURLKey: 'http.url',
+  httpMethodKey: 'http.method',  // TODO: maybe find a better place to put these?
+
+  httpStatusCode(val: string | number | undefined): Tag {
     return {
       key: 'http.status.code',
       overridable: true,
       val: `${val}`,
     } as Tag;
   },
-  httpStatusMsg: (val: string | undefined): Tag => {
+  httpStatusMsg(val: string | undefined): Tag {
     return {
       key: 'http.status.msg',
       overridable: true,
       val: `${val}`,
     } as Tag;
   },
-  httpURL: (val: string | undefined): Tag => {
+  httpURL(val: string | undefined): Tag {
     return {
-      key: 'http.url',
+      key: this.httpURLKey,
+      overridable: true,
+      val: `${val}`,
+    } as Tag;
+  },
+  httpMethod(val: string | undefined): Tag {
+    return {
+      key: this.httpMethodKey,
       overridable: true,
       val: `${val}`,
     } as Tag;
diff --git a/src/plugins/ExpressPlugin.ts b/src/plugins/ExpressPlugin.ts
index 9d9a3e8..cd94ca3 100644
--- a/src/plugins/ExpressPlugin.ts
+++ b/src/plugins/ExpressPlugin.ts
@@ -71,8 +71,13 @@
       try {
         span.layer = SpanLayer.HTTP;
         span.component = Component.EXPRESS;
-        span.peer = req.headers.host || '';
-        span.tag(Tag.httpURL(span.peer + req.url));
+        span.peer =
+          (typeof req.headers['x-forwarded-for'] === 'string' && req.headers['x-forwarded-for'].split(',').shift())
+          || (req.connection.remoteFamily === 'IPv6'
+            ? `[${req.connection.remoteAddress}]:${req.connection.remotePort}`
+            : `${req.connection.remoteAddress}:${req.connection.remotePort}`);
+        span.tag(Tag.httpURL((req.headers.host || '') + req.url));
+        span.tag(Tag.httpMethod(req.method));
 
         const ret = _handle.call(this, req, res, (err: Error) => {
           if (err) {
diff --git a/src/plugins/HttpPlugin.ts b/src/plugins/HttpPlugin.ts
index ca01811..8c1e090 100644
--- a/src/plugins/HttpPlugin.ts
+++ b/src/plugins/HttpPlugin.ts
@@ -58,7 +58,9 @@
             host: (url.host || url.hostname || 'unknown') + ':' + (url.port || 80),
             pathname: url.path || '/',
           };
-      const operation = pathname.replace(/\?.*$/g, '');
+        const httpMethod = arguments[url instanceof URL || typeof url === 'string' ? 1 : 0]?.method || 'GET';
+        const httpURL = host + pathname;
+        const operation = pathname.replace(/\?.*$/g, '');
 
       let stopped = 0;  // compensating if request aborted right after creation 'close' is not emitted
       const stopIfNotStopped = () => !stopped++ ? span.stop() : null;  // make sure we stop only once
@@ -72,10 +74,12 @@
         if (!span.peer) {
           span.peer = host;
         }
-        const httpURL = host + pathname;
-        if (!span.hasTag(httpURL)) {
+        if (!span.hasTag(Tag.httpURLKey)) {  // only set if a higher level plugin with more info did not already set
           span.tag(Tag.httpURL(httpURL));
         }
+        if (!span.hasTag(Tag.httpMethodKey)) {
+          span.tag(Tag.httpMethod(httpMethod));
+        }
 
         const req: ClientRequest = _request.apply(this, arguments);
 
@@ -150,10 +154,13 @@
         try {
           span.component = Component.HTTP_SERVER;
           span.layer = SpanLayer.HTTP;
-          span.peer = req.connection.remoteFamily === 'IPv6'
-            ? `[${req.connection.remoteAddress}]:${req.connection.remotePort}`
-            : `${req.connection.remoteAddress}:${req.connection.remotePort}`;
+          span.peer =
+            (typeof req.headers['x-forwarded-for'] === 'string' && req.headers['x-forwarded-for'].split(',').shift())
+            || (req.connection.remoteFamily === 'IPv6'
+              ? `[${req.connection.remoteAddress}]:${req.connection.remotePort}`
+              : `${req.connection.remoteAddress}:${req.connection.remotePort}`);
           span.tag(Tag.httpURL((req.headers.host || '') + req.url));
+          span.tag(Tag.httpMethod(req.method));
 
           let ret = handler.call(this, req, res, ...reqArgs);
           const type = ret?.constructor;
diff --git a/tests/plugins/axios/expected.data.yaml b/tests/plugins/axios/expected.data.yaml
index 3ecd711..f5c66d3 100644
--- a/tests/plugins/axios/expected.data.yaml
+++ b/tests/plugins/axios/expected.data.yaml
@@ -34,7 +34,9 @@
             skipAnalysis: false
             tags:
               - key: http.url
-                value: httpbin.org:80/json
+                value: httpbin.org/json
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
@@ -53,6 +55,8 @@
             tags:
               - key: http.url
                 value: server:5000/axios
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
@@ -79,6 +83,8 @@
             tags:
               - key: http.url
                 value: server:5000/axios
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
@@ -97,6 +103,8 @@
             tags:
               - key: http.url
                 value: localhost:5001/axios
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
diff --git a/tests/plugins/express/expected.data.yaml b/tests/plugins/express/expected.data.yaml
index 009c233..23ba437 100644
--- a/tests/plugins/express/expected.data.yaml
+++ b/tests/plugins/express/expected.data.yaml
@@ -35,6 +35,8 @@
             tags:
               - key: http.url
                 value: httpbin.org/json
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
@@ -47,6 +49,8 @@
             tags:
               - key: http.url
                 value: server:5000/express
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
@@ -64,7 +68,7 @@
             endTime: gt 0
             componentId: 4002
             spanType: Entry
-            peer: server:5000
+            peer: not null
             skipAnalysis: false
   - serviceName: client
     segmentSize: 1
@@ -79,6 +83,8 @@
             tags:
               - key: http.url
                 value: server:5000/express
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
@@ -97,6 +103,8 @@
             tags:
               - key: http.url
                 value: localhost:5001/express
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
diff --git a/tests/plugins/http/expected.data.yaml b/tests/plugins/http/expected.data.yaml
index b498ff7..b7e241d 100644
--- a/tests/plugins/http/expected.data.yaml
+++ b/tests/plugins/http/expected.data.yaml
@@ -35,6 +35,8 @@
             tags:
               - key: http.url
                 value: server:5000/test
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
             refs:
@@ -60,6 +62,8 @@
             tags:
               - key: http.url
                 value: httpbin.org/json
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg
@@ -83,6 +87,8 @@
             tags:
               - key: http.url
                 value: localhost:5001/test
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
           - operationName: /test
@@ -99,6 +105,8 @@
             tags:
               - key: http.url
                 value: server:5000/test
+              - key: http.method
+                value: GET
               - key: http.status.code
                 value: '200'
               - key: http.status.msg