Insightでのトレース
GraalVM Insightを使用して、標準のOpenTracing API
を介して、スムーズで宣言的な非定型トレースを実装できます。トレースを実行中のアプリケーションに追加し、その場でカスタマイズして、不正行為のインシデントを調査するために必要な正しい情報を抽出できます。
次の例は、GraalVM Insightを使用したトレース機能を示しています。開始するには、Node.js用のJaegerのクライアント側インストゥルメンテーション・ライブラリをインストールします:
graalvm/bin/npm install jaeger-client@3.17.1
これで、tracer
オブジェクトを介してインストゥルメントagent.js
の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');
};
システムは、HTTPリクエストへのレスポンスを初期化して終了するために使用するemit('request', ...)
およびres.end()
関数にフックします。res
オブジェクトは動的JavaScriptオブジェクトであるため、ソースevents.js
のemit
関数のenter
ハンドラにid
およびspan
属性を追加できます。その後、end
関数のreturn
ハンドラでこれらの属性を使用できます。
GraalVM Insightでは、frame
変数とそのフィールドにアクセスできます。そのため、インストゥルメントはreq.url
またはreq.method
の値を読み取り、OpenTracingサーバーにspan.setTag
値として提供できます。
このインストゥルメントでは、それを適切なタイミングで有効にできるかどうかだけが問題です。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: 'http://localhost: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);
これら2つのファイルを使用すると、ノード・アプリケーションおよびエージェントを起動できます。ただし、まず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
graalvm/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
これで、http://localhost:16686/で入手可能なJaeger UIに接続し、サーバーに負荷をかけることができるようになりました:
ab -c 10 -n 10000 http://localhost:8080/
サーバーは、リクエストの処理中にコンソールの詳細情報を出力し、Jaeger UIではトレースが表示されます:
これで、トレースを使用したプレーンなNode.jsアプリケーションを拡張する方法のガイドは完了です。トレースは独自のagent.js
ファイルに分離されたままであり、開始時に(ここで説明)、または必要に応じて動的に適用できます。
次に読むもの
Insightの詳細および難しいタスクについては、Insightのマニュアルを参照してください。