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:32 UTC

[skywalking-nodejs] 07/23: Enhance http plugin and add validation of carrier

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 f34f4be8f5e66951bb662daf3d7dec35c16af595
Author: kezhenxu94 <ke...@163.com>
AuthorDate: Tue Jun 23 20:55:06 2020 +0800

    Enhance http plugin and add validation of carrier
---
 src/core/PluginInstaller.ts         |  2 +-
 src/logging/index.ts                | 21 +++++++++-------
 src/plugins/HttpPlugin.ts           | 50 ++++++++++++++++++++-----------------
 src/trace/context/ContextCarrier.ts | 11 ++++++++
 src/trace/context/SpanContext.ts    |  7 +++---
 src/tsconfig.json                   |  3 ++-
 6 files changed, 56 insertions(+), 38 deletions(-)

diff --git a/src/core/PluginInstaller.ts b/src/core/PluginInstaller.ts
index 301849b..6ac4e08 100644
--- a/src/core/PluginInstaller.ts
+++ b/src/core/PluginInstaller.ts
@@ -33,7 +33,7 @@ class PluginInstaller {
 
   install(): void {
     fs.readdirSync(this.pluginDir)
-      .filter((file) => !file.endsWith('.d.ts'))
+      .filter((file) => file.endsWith('.js'))
       .forEach((file) => {
         const plugin = require(path.join(this.pluginDir, file)).default as SwPlugin;
         logger.info(`Installing plugin ${plugin.module} ${plugin.versions}`);
diff --git a/src/logging/index.ts b/src/logging/index.ts
index a779cfe..63fa15f 100644
--- a/src/logging/index.ts
+++ b/src/logging/index.ts
@@ -26,8 +26,7 @@ type LoggerLevelAware = Logger & {
 };
 
 export function createLogger(name: string): LoggerLevelAware {
-  const loggingLevel = process.env.LOGGING_LEVEL
-    || (process.env.NODE_ENV !== 'production' ? 'debug' : 'info');
+  const loggingLevel = process.env.LOGGING_LEVEL || (process.env.NODE_ENV !== 'production' ? 'debug' : 'info');
 
   const logger = winston.createLogger({
     level: loggingLevel,
@@ -36,14 +35,18 @@ export function createLogger(name: string): LoggerLevelAware {
       file: name,
     },
   });
-  if (process.env.NODE_ENV !== 'production') {
-    logger.add(new winston.transports.Console({
-      format: winston.format.prettyPrint(),
-    }));
+  if (process.env.NODE_ENV !== 'production' || process.env.LOGGING_TARGET === 'console') {
+    logger.add(
+      new winston.transports.Console({
+        format: winston.format.prettyPrint(),
+      }),
+    );
   } else {
-    logger.add(new winston.transports.File({
-      filename: 'skywalking.log',
-    }));
+    logger.add(
+      new winston.transports.File({
+        filename: 'skywalking.log',
+      }),
+    );
   }
 
   const isDebugEnabled = (): boolean => logger.levels[logger.level] > logger.levels.debug;
diff --git a/src/plugins/HttpPlugin.ts b/src/plugins/HttpPlugin.ts
index 246f546..ce60d27 100644
--- a/src/plugins/HttpPlugin.ts
+++ b/src/plugins/HttpPlugin.ts
@@ -25,13 +25,16 @@ import { Component } from '../trace/Component';
 import Tag from '../Tag';
 import { SpanLayer } from '../proto/language-agent/Tracing_pb';
 import { ContextCarrier } from '../trace/context/ContextCarrier';
+import { createLogger } from '../logging';
 
 type RequestFunctionType = (
-  url: string | URL,
+  url: string | URL | RequestOptions,
   options: RequestOptions,
   callback?: (res: IncomingMessage) => void,
 ) => ClientRequest;
 
+const logger = createLogger(__filename);
+
 class HttpPlugin implements SwPlugin {
   readonly module = 'http';
   readonly versions = '';
@@ -41,10 +44,12 @@ class HttpPlugin implements SwPlugin {
 
     const http = require('http');
 
-    (original => {
-      http.Server.prototype.emit = function(event: string | symbol, ...args: any[]): boolean {
+    ((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;
@@ -58,7 +63,7 @@ class HttpPlugin implements SwPlugin {
           }
 
           const carrier = new ContextCarrier();
-          carrier.items.forEach(item => {
+          carrier.items.forEach((item) => {
             if (headersMap.hasOwnProperty(item.key)) {
               item.value = headersMap[item.key];
             }
@@ -70,10 +75,7 @@ class HttpPlugin implements SwPlugin {
           span.layer = SpanLayer.HTTP;
 
           res.on('finish', () => {
-            span
-              .tag(Tag.httpStatusCode(res.statusCode))
-              .tag(Tag.httpStatusMsg(res.statusMessage))
-              .stop();
+            span.tag(Tag.httpStatusCode(res.statusCode)).tag(Tag.httpStatusMsg(res.statusMessage)).stop();
           });
         }
         return original.apply(this, arguments);
@@ -93,14 +95,21 @@ class HttpPlugin implements SwPlugin {
 
   private wrapHttpClientRequest(originalRequest: RequestFunctionType): RequestFunctionType {
     return (
-      url: string | URL,
+      url: string | URL | RequestOptions,
       options: RequestOptions,
       callback?: (res: IncomingMessage) => void,
     ): ClientRequest => {
-      const {
-        host: peer,
-        pathname: operation,
-      } = url instanceof URL ? url : new URL(url);
+      logger.debug(`url is ${typeof url}: ${url}`);
+
+      const { host: peer, pathname: operation } =
+        url instanceof URL
+          ? url
+          : typeof url === 'string'
+          ? new URL(url)
+          : {
+              host: url.host || url.hostname || 'unknown',
+              pathname: url.path || '/',
+            };
 
       const span = ContextManager.current.newExitSpan(operation, peer).start();
       span.component = Component.HTTP;
@@ -108,10 +117,8 @@ class HttpPlugin implements SwPlugin {
 
       const snapshot = ContextManager.current.capture();
 
-      const request = originalRequest(url, options, res => {
-        span
-          .tag(Tag.httpStatusCode(res.statusCode))
-          .tag(Tag.httpStatusMsg(res.statusMessage));
+      const request = originalRequest(url, options, (res) => {
+        span.tag(Tag.httpStatusCode(res.statusCode)).tag(Tag.httpStatusMsg(res.statusMessage));
 
         const callbackSpan = ContextManager.current.newLocalSpan('callback').start();
         callbackSpan.layer = SpanLayer.HTTP;
@@ -126,12 +133,9 @@ class HttpPlugin implements SwPlugin {
         callbackSpan.stop();
       });
 
-      span
-        .extract()
-        .items
-        .forEach(item => {
-          request.setHeader(item.key, item.value);
-        });
+      span.extract().items.forEach((item) => {
+        request.setHeader(item.key, item.value);
+      });
 
       span.stop();
 
diff --git a/src/trace/context/ContextCarrier.ts b/src/trace/context/ContextCarrier.ts
index 466db95..684ccf3 100644
--- a/src/trace/context/ContextCarrier.ts
+++ b/src/trace/context/ContextCarrier.ts
@@ -66,4 +66,15 @@ export class ContextCarrier extends CarrierItem {
     this.endpoint = this.decode(parts[6]);
     this.clientAddress = this.decode(parts[7]);
   }
+
+  isValid(): boolean {
+    return (
+      this.traceId !== undefined &&
+      this.segmentId !== undefined &&
+      this.spanId !== undefined &&
+      this.service !== undefined &&
+      this.endpoint !== undefined &&
+      this.clientAddress !== undefined
+    );
+  }
 }
diff --git a/src/trace/context/SpanContext.ts b/src/trace/context/SpanContext.ts
index e53a24a..55131e0 100644
--- a/src/trace/context/SpanContext.ts
+++ b/src/trace/context/SpanContext.ts
@@ -38,8 +38,7 @@ export default class SpanContext implements Context {
   spans: Span[] = [];
   segment: Segment = new Segment();
 
-  constructor(public asyncId: number) {
-  }
+  constructor(public asyncId: number) {}
 
   get parent(): Span | null {
     if (this.spans.length > 0) {
@@ -67,7 +66,7 @@ export default class SpanContext implements Context {
       operation,
     });
 
-    if (carrier) {
+    if (carrier && carrier.isValid()) {
       span.inject(carrier);
     }
 
@@ -107,7 +106,7 @@ export default class SpanContext implements Context {
   }
 
   start(span: Span): Context {
-    if (this.spans.every(s => s.id !== span.id)) {
+    if (this.spans.every((s) => s.id !== span.id)) {
       this.spans.push(span);
     }
 
diff --git a/src/tsconfig.json b/src/tsconfig.json
index fe65fba..c362071 100644
--- a/src/tsconfig.json
+++ b/src/tsconfig.json
@@ -13,7 +13,8 @@
     "baseUrl": ".",
     "resolveJsonModule": true,
     "declaration": true,
-    "allowJs": true
+    "allowJs": true,
+    "sourceMap": true
   },
   "references": [
     {