対数犬度関数

140字以上のことを書きます

OpenTelemetryのTracingについてまとめる JavaScriptにおけるAuto Instrumentation編

これは何

OpenTelemetryのTracingについて理解するため,JavaScriptで実装されたアプリケーションに対するauto instrumentationにおいて以下について調査した結果をまとめる記事です.

  • Auto instrumentationの実行方法
  • Auto instrumentationの実装

まとめ

  • nodeコマンドの--require flagを用いてアプリケーションの実行前にInstrumentationを行っている
  • Instrumentationの実際の処理では最終的にObject.definePropertyを用いてwrapされたメソッドと本来のメソッドを差し替えている
    • shimmerを用いている(他のメソッドをラップし,前後に処理を差し込めるライブラリ)

nodeコマンド実行 -> instrumentationまでの流れは以下のようになっています(ノードをクリックすることで実装リポジトリに遷移できます)

graph LR
    node["node --require @opentelemetry/auto-instrumentations-node/register app.js"]
    reg["register.ts(Auto instrumentationのエントリーポイント)"]
    contrib["https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node"]
    experimental["https://github.com/open-telemetry/opentelemetry-js/tree/v1.25.1/experimental/packages"]

    node --> reg
    reg --> contrib
    reg--> experimental

    click reg href "https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/metapackages/auto-instrumentations-node/src/register.ts"
    click contrib href "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node"
    click experimental href "https://github.com/open-telemetry/opentelemetry-js/tree/v1.25.1/experimental/packages"

Auto instrumentationの実行方法

OpenTelemetry公式のドキュメントを見てみると nodeコマンドの--require flagを用いています.

env OTEL_TRACES_EXPORTER=otlp OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=your-endpoint \
node --require @opentelemetry/auto-instrumentations-node/register app.js

opentelemetry.io

この--requireflagは アプリケーションの実行前に指定したmoduleを実行できる引数です.

実行順がわかりやすい例

このことからアプリケーションの実行前のinstrumentation処理を実装したmoduleを--requireflagで指定することによりアプリケーションのAuto instrumentationを行うことが可能と考えられます.

Auto instrumentationの実装

ここからは実際のAuto Instrumentationの実装について調査していきます.

@opentelemetry/auto-instrumentations-node Package

Auto Instrumentation実行時のコマンドを見ると,@opentelemetry/auto-instrumentations-nodePackage内のスクリプトを実行していることがわかります.

env OTEL_TRACES_EXPORTER=otlp OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=your-endpoint \
node --require @opentelemetry/auto-instrumentations-node/register app.js

opentelemetry.io

このPackageのREADME.mdを見ると,Auto Instrumentationのためのスクリプトなどを公開しているPackageであることがわかります.

依存するPackageの一覧を見てもJavaScript向けに提供されているAuto instrumentation用Packageがおおよそ含まれていること,また--requireflagで指定していたregister.tsの処理を追っていくとgetNodeAutoInstrumentations関数の定義元でこれらのPackageからClassをimportしているため,このPackageを起点に各Package毎のAuto Instrumentatin用の処理が呼び出されていそうです.

各Package毎のAuto Instrumentatin用の処理を追う

ここからはhttp moduleに対する計装の処理を追いながら具体的な計装の処理を追っていきます.

http moduleに対する計装の処理は以下のリポジトリで実装されています.

github.com

getNodeAutoInstrumentations関数でNodeSDKクラスに渡されているHttpInstrumentationクラスの実装について確認します.

github.com

ここでは InstrumentationBase クラスで定義された_wrapメソッドが呼ばれています.このメソッドの実装をみるとshimmermoduleのwrapメソッドが呼ばれています.

github.com

サンプルの通り,shimmermoduleのwrapメソッドはユーザーが第3引数で渡したラッパー関数を渡すことで本来の処理と差し替えるメソッドです.

www.npmjs.com

実際の処理を見てみると,ラップされた処理(wraped変数の値)をObject.definePropertyを用いてwrap前のメソッドと差し替えていることがわかります.

github.com

まとめ

  • Node.jsの自動計装ではObject.definePropertyを用いてwrapされたメソッドと本来のメソッドを差し替えている