Experimental feature in GraalVM

Insight 追踪

可以使用 GraalVM Insight 通过标准 OpenTracing API 实现流畅、声明式、即时(ad hoc)的追踪。追踪可以添加到运行中的应用程序中,并可即时自定义以提取调查任何异常行为事件所需的正确信息。

以下示例将演示 GraalVM Insight 的追踪功能。首先,安装适用于 Node.js 的 Jaeger 客户端端检测库。

./bin/npm install jaeger-client@3.17.1

现在,你可以在你的检测工具 agent.js 中通过 tracer 对象使用由 jaeger-client 模块提供的 OpenTracing API(一旦它可用,将在本指南后面讨论)。

let initialize = function(tracer) {
    var counter = 0;

    insight.on('enter', function(ctx, frame) {
        const args = frame.args;
        if ('request' !== frame.type || args.length !== 2 || typeof args[0] !== 'object' || typeof args[1] !== 'object') {
            return;
        }
        const req = args[0];
        const res = args[1];
        const span = tracer.startSpan("request");
        span.setTag("span.kind", "server");
        span.setTag("http.url", req.url);
        span.setTag("http.method", req.method);
        res.id = ++counter;
        res.span = span;
        console.log(`agent: handling #${res.id} request for ${req.url}`);
    }, {
        roots: true,
        rootNameFilter: 'emit',
        at: {
            sourcePath: '.*events.js'
        }
    });

    insight.on('return', function(ctx, frame) {
        var res = frame['this'];
        if (res.span) {
            res.span.finish();
            console.log(`agent: finished #${res.id} request`);
        } else {
            //Caused, for example, by Tracer itself connecting to the Jaeger server
        }
    }, {
        roots: true,
        rootNameFilter: 'end',
        at: {
            sourcePath: '.*_http_outgoing.js'
        }
    });
    console.log('agent: ready');
};

系统会挂钩到 emit('request', ...)res.end() 函数,这些函数用于初始化 HTTP 请求的响应并结束它。由于 res 对象是动态 JavaScript 对象,因此可以在源 events.jsemit 函数的 enter 处理程序中向其添加 idspan 属性。然后可以在 end 函数的 return 处理程序中使用这些属性。

GraalVM Insight 提供了对 frame 变量及其字段的访问权限。因此,检测工具可以读取 req.urlreq.method 的值,并将它们作为 span.setTag 值提供给 OpenTracing 服务器。

有了这个检测工具,只需在正确的时间启用它即可。请查看 将 Insight 嵌入到 Node.js 应用程序中 部分,了解如何创建管理服务器并在需要时动态应用任何追踪脚本(包括基于 OpenTracing 的脚本)。为了本指南的目的,将使用更简单的方法。

jaeger 对象提供给检测工具时启用它

let initializeJaeger = function (ctx, frame) {
    insight.off('enter', initializeJaeger);

    let jaeger = frame.jaeger;

    var initTracer = jaeger.initTracer;
    console.log('agent: Jaeger tracer obtained');

    // See schema https://github.com/jaegertracing/jaeger-client-node/blob/master/src/configuration.js#L37
    var config = {
      serviceName: 'insight-demo',
      reporter: {
        // Provide the traces endpoint. This forces the client to connect directly to the Collector and send
        // spans over HTTP
        collectorEndpoint: 'https://:14268/api/traces',
        // Provide username and password if authentication is enabled in the Collector
        // username: '',
        // password: '',
      },
      sampler: {
          type : 'const',
          param : 1
      }
    };
    var options = {
      tags: {
        'insight-demo.version': '1.1.2',
      },
    //  metrics: metrics,
      logger: console,
      sampler: {
          type : 'const',
          param : 1
      }
    };

    var tracer = initTracer(config, options);
    initialize(tracer);
};

insight.on('return', initializeJaeger, {
  roots: true,
  rootNameFilter: 'jaegerAvailable'
});

此检测工具需要主服务器脚本的帮助。让 server.js 获取 jaeger-client 模块并通过 jaegerAvailable 函数将其传递给代理。然后它会创建一个典型的 HTTP 服务器。server.js 的内容如下:

function jaegerAvailable(jaeger) {
    console.log("Providing Jaeger object to the agent");
}
jaegerAvailable(require("jaeger-client"));

const http = require("http");
const srv = http.createServer((req, res) => {
    console.log(`server: obtained request ${res.id}`);
    setTimeout(() => {
        res.write(`OK# ${res.id}`);
        console.log(`server: replied to request ${res.id}`);
        res.end();
    }, 5);
});
srv.listen(8080);

有了这两个文件,你就可以启动 Node 应用程序和代理了。但是,首先,启动 Jaeger 服务器:

docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
-p 5775:5775/udp   -p 6831:6831/udp   -p 6832:6832/udp \
-p 5778:5778   -p 16686:16686   -p 14268:14268   -p 9411:9411 \
jaegertracing/all-in-one:latest

./bin/node --insight=agent.js server.js
Providing Jaeger object to the agent
agent: Jaeger tracer obtained
Initializing Jaeger Tracer with RemoteReporter and ConstSampler(always)
agent: ready

现在你可以连接到 Jaeger UI,地址是 https://:16686/ 并对服务器施加一些负载。

ab -c 10 -n 10000 https://:8080/

服务器在处理请求时会向控制台打印详细信息,而 Jaeger UI 则会显示追踪数据。

Jaeger UI

本指南到此结束,介绍了如何使用追踪功能增强普通的 Node.js 应用程序。追踪数据保留在其独立的 agent.js 文件中,可以在启动时应用(此处演示)或在需要时 动态 应用。

要了解更多关于 Insight 的信息并找到一些具有挑战性的任务,请参阅 Insight 手册

联系我们