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/12/04 03:16:30 UTC

[skywalking-nodejs] branch master updated: Node 10 AsyncLocalStorage and Plugin loader (#7)

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


The following commit(s) were added to refs/heads/master by this push:
     new 7ee2ad7  Node 10 AsyncLocalStorage and Plugin loader (#7)
7ee2ad7 is described below

commit 7ee2ad7c4b0d44563924c6f92c28c46febabddcd
Author: Tomasz Pytel <to...@gmail.com>
AuthorDate: Fri Dec 4 00:16:23 2020 -0300

    Node 10 AsyncLocalStorage and Plugin loader (#7)
---
 .github/workflows/build.yaml        |  2 +-
 .github/workflows/test.yaml         |  2 +-
 jest.setup.js                       |  6 +++---
 package-lock.json                   |  3 +--
 src/core/PluginInstaller.ts         | 24 ++++++++++++++++++------
 src/plugins/HttpPlugin.ts           |  1 -
 src/trace/context/ContextManager.ts | 22 ++++++++++++++++++++--
 7 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index df8a24d..6df12d3 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -29,7 +29,7 @@ jobs:
     timeout-minutes: 30
     strategy:
       matrix:
-        node-version: [ 12, 14 ]
+        node-version: [ 10, 12, 14 ]
     steps:
       - uses: actions/checkout@v2
         with:
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 051fea3..38ecf3d 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -29,7 +29,7 @@ jobs:
     timeout-minutes: 30
     strategy:
       matrix:
-        node-version: [ 12, 14 ]
+        node-version: [ 10, 12, 14 ]
     steps:
       - uses: actions/checkout@v2
         with:
diff --git a/jest.setup.js b/jest.setup.js
index 29df171..39eff53 100644
--- a/jest.setup.js
+++ b/jest.setup.js
@@ -19,7 +19,7 @@
 
 const waitForExpect = require('wait-for-expect');
 
-jest.setTimeout(30000_000);
+jest.setTimeout(30000000);
 
-waitForExpect.defaults.interval = 10_000; // ms
-waitForExpect.defaults.timeout = 120_000; // ms
+waitForExpect.defaults.interval = 10000; // ms
+waitForExpect.defaults.timeout = 120000; // ms
diff --git a/package-lock.json b/package-lock.json
index 5138bfa..d8cb4dd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8298,8 +8298,7 @@
     "tslib": {
       "version": "2.0.3",
       "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-2.0.3.tgz?cache=0&sync_timestamp=1602286724979&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.0.3.tgz",
-      "integrity": "sha1-jgdBrEX8DCJuWKF7/D5kubxsphw=",
-      "dev": true
+      "integrity": "sha1-jgdBrEX8DCJuWKF7/D5kubxsphw="
     },
     "tslint": {
       "version": "6.1.2",
diff --git a/src/core/PluginInstaller.ts b/src/core/PluginInstaller.ts
index c0c34de..887cd6f 100644
--- a/src/core/PluginInstaller.ts
+++ b/src/core/PluginInstaller.ts
@@ -25,6 +25,11 @@ import * as semver from 'semver';
 
 const logger = createLogger(__filename);
 
+let topModule = module;
+for (; topModule.parent; topModule = topModule.parent);
+
+const topResolve = (request: string) => (module.constructor as any)._resolveFilename(request, topModule)
+
 class PluginInstaller {
   pluginDir: string;
 
@@ -32,18 +37,25 @@ class PluginInstaller {
     this.pluginDir = path.resolve(__dirname, '..', 'plugins');
   }
 
-  private isBuiltIn = (module: string): boolean => require.resolve(module) === module;
+  private isBuiltIn = (module: string): boolean => topResolve(module) === module;
 
   private checkModuleVersion = (plugin: SwPlugin): { version: string; isSupported: boolean } => {
-    if (this.isBuiltIn(plugin.module)) {
+    try {
+      if (this.isBuiltIn(plugin.module)) {
+        return {
+          version: '*',
+          isSupported: true,
+        };
+      }
+    } catch {  // module not found
       return {
-        version: '*',
-        isSupported: true,
+        version: 'not found,',
+        isSupported: false,
       };
     }
 
-    const packageJsonPath = require.resolve(`${plugin.module}/package.json`);
-    const version = require(packageJsonPath).version;
+    const packageJsonPath = topResolve(`${plugin.module}/package.json`);
+    const version = topModule.require(packageJsonPath).version;
 
     if (!semver.satisfies(version, plugin.versions)) {
       logger.info(`Plugin ${plugin.module} ${version} doesn't satisfy the supported version ${plugin.versions}`);
diff --git a/src/plugins/HttpPlugin.ts b/src/plugins/HttpPlugin.ts
index 3d8f569..0a1f1db 100644
--- a/src/plugins/HttpPlugin.ts
+++ b/src/plugins/HttpPlugin.ts
@@ -23,7 +23,6 @@ import { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from '
 import ContextManager from '../trace/context/ContextManager';
 import { Component } from '../trace/Component';
 import Tag from '../Tag';
-import Span from '../trace/span/Span';
 import { SpanLayer } from '../proto/language-agent/Tracing_pb';
 import { ContextCarrier } from '../trace/context/ContextCarrier';
 import { createLogger } from '../logging';
diff --git a/src/trace/context/ContextManager.ts b/src/trace/context/ContextManager.ts
index 6fd34e6..3ed253e 100644
--- a/src/trace/context/ContextManager.ts
+++ b/src/trace/context/ContextManager.ts
@@ -20,11 +20,29 @@
 import Context from '../../trace/context/Context';
 import Span from '../../trace/span/Span';
 import SpanContext from '../../trace/context/SpanContext';
-import { AsyncLocalStorage } from 'async_hooks';
 
 type AsyncState = {context: Context, spans: Span[]};
 
-const store = new AsyncLocalStorage<AsyncState>();
+const async_hooks = require('async_hooks');
+let   store: any;
+
+if (async_hooks.AsyncLocalStorage) {
+  store = new async_hooks.AsyncLocalStorage();
+
+} else {  // Node 10 doesn't have AsyncLocalStore, so recreate it
+  const executionAsyncId = async_hooks.executionAsyncId;
+  const asyncLocalStore: {[index: string]: any} = {};
+
+  store = new class {
+    getStore(): AsyncState | undefined { return asyncLocalStore[executionAsyncId()] as unknown as AsyncState; }
+    enterWith(store: AsyncState): void { asyncLocalStore[executionAsyncId()] = store; }
+  }();
+
+  async_hooks.createHook({
+    init(asyncId: number, type: string, triggerId: number) { asyncLocalStore[asyncId] = asyncLocalStore[triggerId]; },
+    destroy(asyncId: number) { delete asyncLocalStore[asyncId]; }
+  }).enable();
+}
 
 class ContextManager {
   get asyncState(): AsyncState {