このトピックでは、Node.jsランタイム環境でのトレース分析機能について説明します。
背景
Alibaba Cloud Tracing AnalysisはOpenTracing標準を採用しており、オープンソースコミュニティと互換性があります。 Tracing Analysisは、分散アプリケーションの開発者にさまざまな機能を提供します。 たとえば、開発者は分散トレースのクエリと診断、分散トポロジの動的な検出、アプリケーションのパフォーマンスのリアルタイムな要約を行うことができます。
Function ComputeはTracing Analysisと統合します。 Jaeger SDKまたはOpenTelemetryを使用してトレース情報をアップロードし、関数の呼び出しを追跡できます。 Tracing Analysisは、サーバーレスアーキテクチャのパフォーマンスボトルネックの分析と診断に役立ちます。 これにより、サーバーレスシナリオでの開発と診断の効率が向上します。
概要
Tracing Analysisは、Function Computeコンソールで設定できます。 詳細については、「トレース分析の有効化」をご参照ください。
サービスのTracing Analysisを有効にすると、Function Computeはシステムで消費された時間を自動的に記録します。 時間は、コールドスタート時間、イニシャライザ関数の実行時間、及び関数の実行時間を含む。 次の図のシステムスパンの詳細については、「スパン名の説明」をご参照ください。
ビジネス側の関数で消費された時間を記録できます。 たとえば、[カスタムスパンの作成] を使用して、関数内でApsaraDB RDSやApsara File Storage NASなどのサービスにアクセスするのにかかる時間を記録できます。
サンプルコード
Node.jsランタイム環境でのFunction Computeのトレース分析では、OpenTracing仕様のJaeger実装に基づいて、次の方法を使用してカスタムスパンを作成できます。
OpenTelemetry用SDKの使用 (推奨)
Node.jsコードでは、SDK for OpenTelemetryを使用してコードのインストルメンテーションを実行し、データをTracing Analysisに報告できます。 完全なサンプルコードについては、「nodejs-tracing-openTelemetry」をご参照ください。
サンプルコードの詳細を次に示します。
プロジェクトディレクトリにpackage.jsonの依存関係ファイルを設定します。
"dependencies": { "@opentelemetry/api": "^1.0.2", "@opentelemetry/exporter-jaeger": "0.25.0", "@opentelemetry/exporter-zipkin": "0.25.0", "@opentelemetry/instrumentation": "0.25.0", "@opentelemetry/instrumentation-http": "0.25.0", "@opentelemetry/resources": "0.25.0", "@opentelemetry/semantic-conventions": "0.25.0", "@opentelemetry/sdk-trace-node": "0.25.0", "@opentelemetry/sdk-trace-base": "0.25.0" }
データをTracing Analysisに報告します。
module.exports.handler = function(event, context, callback) { tracer = require('./tracer')('fc-tracer',context.tracing.jaegerEndpoint); var spanContext = contextFromString( context.tracing.openTracingSpanContext); startMySpan(spanContext); callback(null,'success'); }
スパンの作成に使用する
トレーサー
オブジェクトを作成します。module.exports = (serviceName,endpoint) => { const provider = new NodeTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: serviceName, }), }); let exporter = new JaegerExporter({endpoint:endpoint}); provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); provider.register(); registerInstrumentations({ instrumentations: [ new HttpInstrumentation(), ], }); return opentelemetry.trace.getTracer('http-example'); };
Function ComputeでContextのトレース情報を取得し、トレース情報をSpanContextに変換します。
function contextFromString(value){ const arr = value.split(`:`); const spanContext={ traceId:`0000000000000000`+arr[0], spanId:arr[1], traceFlags:api.TraceFlags.SAMPLED, isRemote:true } return spanContext; }
トレーサー
を作成し、変換されたコンテキストを使用して子スパンを作成します。 スパンは、呼び出しトレースで名前が付けられ、時間が設定された継続的に実行可能なコードスニペットを表します。 スパンに基づいて子スパンを作成することもできます。function startMySpan(spanContext){ var FcSpan=api.trace.wrapSpanContext(spanContext); var ctx = api.trace.setSpan(api.ROOT_CONTEXT,FcSpan); tracer.startActiveSpan("fc-operation",undefined,ctx,parentSpan => { parentSpan.setAttribute("version","fc-v1"); sleep(150); child(); parentSpan.end() }) } function child(){ tracer.startActiveSpan("fc-operation-child",span =>{ sleep(100); span.addEvent("timeout"); span.end(); }) }
JaegerのSDKを使用する
JaegerのSDKを使用して、コードのインストルメンテーションを実行し、データをTracing Analysisに報告できます。 完全なサンプルコードについては、「nodejs-tracing」をご参照ください。
サンプルコードの詳細を次に示します。
プロジェクトディレクトリにpackage.jsonの依存関係ファイルを設定します。
"dependencies": { "jaeger-client": "^3.19.0" }
データをTracing Analysisに報告します。
module.exports.handler = function(event, context, callback) { tracer=newTracer(context); var invokeSpanContext = spanContext.fromString(context.tracing.openTracingSpanContext); startMySpan(invokeSpanContext); callback(null,'success') }
コンテキストのトレース情報に基づいて、
トレーサー
オブジェクトを作成します。function newTracer(context){ var config = { serviceName: 'fc-tracer', reporter: { // Provide the traces endpoint; this forces the client to connect directly to the Collector and send spans over HTTP collectorEndpoint: context.tracing.jaegerEndpoint, flushIntervalMs: 10, }, sampler: { type: "const", param: 1 }, }; var options = { tags: { 'version': 'fc-v1', }, }; var tracer = initTracer(config, options); return tracer }
SpanContextを変換し、カスタムスパンを作成します。 スパンに基づいて子スパンを作成することもできます。
function startMySpan(spanContext){ var parentSpan = tracer.startSpan("fc-operation", { childOf: spanContext }); sleep(150); child(parentSpan.context()) parentSpan.finish(); } function child(spanContext){ var childSpan = tracer.startSpan("fc-operation-child", { childOf: spanContext }); childSpan.log({event:"timeout"}); sleep(100); childSpan.finish(); }