リソース

アプリケーションの環境に関する詳細情報をテレメトリに追加する

リソースは、リソース属性としてテレメトリーを生成するエンティティを表します。 たとえば、Kubernetes上のコンテナで実行されているテレメトリーを生成するプロセスは、プロセス名、ポッド名、ネームスペース、および場合によってはデプロイメント名を持ちます。 これらの4つの属性すべてをリソースに含まれることができます。

オブザーバビリティバックエンドでは、リソース情報を使用して興味深い動作をより詳細に調査できます。 たとえば、トレースまたはメトリクスデータがシステムのレイテンシーを示している場合、それを特定のコンテナ、ポッド、またはKubernetesデプロイメントに絞り込むことができます。

以下では、Node.js SDKでリソース検出を設定する方法について説明します。

セットアップ

Getting Started - Node.jsの手順に従って、package.jsonapp.jstracing.jsファイルを用意してください。

プロセスおよび環境リソースの検出

Node.js SDKは、初期設定でプロセスとプロセスランタイムリソースを検出し、環境変数OTEL_RESOURCE_ATTRIBUTESから属性を取得します。 tracing.jsで診断ログを有効にすることで、何が検出されているかを確認できます。

// トラブルシューティングのため、ログレベルをDiagLogLevel.DEBUGに設定
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);

OTEL_RESOURCE_ATTRIBUTESにいくつかの値を設定してアプリケーションを実行します。 たとえば、Hostを識別するためにhost.nameを設定します。

$ env OTEL_RESOURCE_ATTRIBUTES="host.name=localhost" \
  node --require ./tracing.js app.js
@opentelemetry/api: Registered a global for diag v1.2.0.
...
Listening for requests on http://localhost:8080
EnvDetector found resource. Resource { attributes: { 'host.name': 'localhost' } }
ProcessDetector found resource. Resource {
  attributes: {
    'process.pid': 12345,
    'process.executable.name': 'node',
    'process.command': '/app.js',
    'process.command_line': '/bin/node /app.js',
    'process.runtime.version': '16.17.0',
    'process.runtime.name': 'nodejs',
    'process.runtime.description': 'Node.js'
  }
}
...

環境変数でリソースを追加

上記の例では、SDKがプロセスを検出し、環境変数で設定されたhost.name=localhost属性も自動的に追加されています。

以下では、リソースを自動検出する手順を説明します。 ただし、必要なリソースに対応する検出器が存在しない場合があります。 その場合は、環境変数OTEL_RESOURCE_ATTRIBUTESを使用して必要な情報を追加してください。 また、環境変数OTEL_SERVICE_NAMEを使用してservice.nameリソース属性の値を設定することもできます。 たとえば、以下のスクリプトはServiceHostOSリソース属性を追加します。

$ env OTEL_SERVICE_NAME="app.js" OTEL_RESOURCE_ATTRIBUTES="service.namespace=tutorial,service.version=1.0,service.instance.id=`uuidgen`,host.name=${HOSTNAME},host.type=`uname -m`,os.name=`uname -s`,os.version=`uname -r`" \
  node --require ./tracing.js app.js
...
EnvDetector found resource. Resource {
  attributes: {
    'service.name': 'app.js',
    'service.namespace': 'tutorial',
    'service.version': '1.0',
    'service.instance.id': '46D99F44-27AB-4006-9F57-3B7C9032827B',
    'host.name': 'myhost',
    'host.type': 'arm64',
    'os.name': 'linux',
    'os.version': '6.0'
  }
}
...

コードでリソースを追加

カスタムリソースはコードでも設定できます。 NodeSDKでは設定オプションが提供されており、ここでリソースを設定できます。 たとえば、以下のようにtracing.jsを更新してservice.*属性を設定できます。

...
const { resourceFromAttributes } = require('@opentelemetry/resources');
const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } = require('@opentelemetry/semantic-conventions');
...
const sdk = new opentelemetry.NodeSDK({
  ...
  resource: resourceFromAttributes({
    [ ATTR_SERVICE_NAME ]: "yourServiceName",
    [ ATTR_SERVICE_VERSION ]: "1.0",
  })
  ...
});
...

コンテナリソースの検出

同じセットアップ(package.jsonapp.js、デバッグを有効にしたtracing.js)を使用し、同じディレクトリに以下の内容のDockerfileを作成します。

FROM node:latest
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "node", "--require", "./tracing.js", "app.js" ]

Ctrl + CSIGINT)でDockerコンテナを停止できるようにするため、app.jsの最後に以下を追加します。

process.on('SIGINT', function () {
  process.exit();
});

コンテナのIDを自動検出するため、以下の追加依存関係をインストールします。

npm install @opentelemetry/resource-detector-docker

次に、tracing.jsを以下のように更新します。

const opentelemetry = require('@opentelemetry/sdk-node');
const {
  getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');
const {
  dockerCGroupV1Detector,
} = require('@opentelemetry/resource-detector-docker');

// トラブルシューティングのため、ログレベルをDiagLogLevel.DEBUGに設定
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);

const sdk = new opentelemetry.NodeSDK({
  traceExporter: new opentelemetry.tracing.ConsoleSpanExporter(),
  instrumentations: [getNodeAutoInstrumentations()],
  resourceDetectors: [dockerCGroupV1Detector],
});

sdk.start();

Dockerイメージをビルドします。

docker build . -t nodejs-otel-getting-started

Dockerコンテナを実行します。

$ docker run --rm -p 8080:8080 nodejs-otel-getting-started
@opentelemetry/api: Registered a global for diag v1.2.0.
...
Listening for requests on http://localhost:8080
DockerCGroupV1Detector found resource. Resource {
  attributes: {
    'container.id': 'fffbeaf682f32ef86916f306ff9a7f88cc58048ab78f7de464da3c3201db5c54'
  }
}

検出器がcontainer.idを抽出しました。 ただし、この例ではプロセス属性と環境変数で設定された属性が不足していることに気づくでしょう。 これを解決するには、resourceDetectorsリストを設定する際にenvDetectorprocessDetector検出器も指定する必要があります。

const opentelemetry = require('@opentelemetry/sdk-node');
const {
  getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');
const {
  dockerCGroupV1Detector,
} = require('@opentelemetry/resource-detector-docker');
const { envDetector, processDetector } = require('@opentelemetry/resources');

// トラブルシューティングのため、ログレベルをDiagLogLevel.DEBUGに設定
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);

const sdk = new opentelemetry.NodeSDK({
  traceExporter: new opentelemetry.tracing.ConsoleSpanExporter(),
  instrumentations: [getNodeAutoInstrumentations()],
  // 必要なすべての検出器をここに追加してください!
  resourceDetectors: [envDetector, processDetector, dockerCGroupV1Detector],
});

sdk.start();

イメージを再ビルドして、コンテナを再度実行します。

docker run --rm -p 8080:8080 nodejs-otel-getting-started
@opentelemetry/api: Registered a global for diag v1.2.0.
...
Listening for requests on http://localhost:8080
EnvDetector found resource. Resource { attributes: {} }
ProcessDetector found resource. Resource {
  attributes: {
    'process.pid': 1,
    'process.executable.name': 'node',
    'process.command': '/usr/src/app/app.js',
    'process.command_line': '/usr/local/bin/node /usr/src/app/app.js',
    'process.runtime.version': '18.9.0',
    'process.runtime.name': 'nodejs',
    'process.runtime.description': 'Node.js'
  }
}
DockerCGroupV1Detector found resource. Resource {
  attributes: {
    'container.id': '654d0670317b9a2d3fc70cbe021c80ea15339c4711fb8e8b3aa674143148d84e'
  }
}
...

次のステップ

設定に追加できるリソース検出器は他にもあります。 たとえば、Cloud環境やDeploymentの詳細を取得するものがあります。 詳細については、検出器の完全なリストを参照してください。