フロントエンド
フロントエンドは、ユーザーに UI を提供するとともに、UI やその他のクライアントが利用する API を提供する役割を担います。 このアプリケーションは Next.JS をベースにしており、React ベースのウェブ UI と API ルートを提供します。
サーバー計装
Node.js アプリケーションの起動時に Node の required モジュールを使って SDK と自動計装を初期化することが推奨されます。
OpenTelemetry Node.js SDK を初期化する際に、利用する自動計装ライブラリをオプションで指定するか、主要なフレームワークを網羅する getNodeAutoInstrumentations() 関数を使用できます。
utils/telemetry/Instrumentation.js ファイルには、OTLP エクスポート、リソース属性、サービス名に関する標準の OpenTelemetry 環境変数に基づいて SDK と自動計装を初期化するために必要なすべてのコードが含まれています。
const FrontendTracer = async () => {
const { ZoneContextManager } = await import('@opentelemetry/context-zone');
let resource = resourceFromAttributes({
[ATTR_SERVICE_NAME]: NEXT_PUBLIC_OTEL_SERVICE_NAME,
});
const detectedResources = detectResources({ detectors: [browserDetector] });
resource = resource.merge(detectedResources);
const provider = new TracerProvider({
resource,
spanProcessors: [
new SessionIdProcessor(),
new BatchSpanProcessor({
exporter: new OTLPTraceExporter({
url:
NEXT_PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||
'http://localhost:4318/v1/traces',
}),
scheduledDelayMillis: 500,
}),
],
});
context.setGlobalContextManager(new ZoneContextManager().enable());
propagation.setGlobalPropagator(
new CompositePropagator({
propagators: [
new W3CBaggagePropagator(),
new W3CTraceContextPropagator(),
],
}),
);
trace.setGlobalTracerProvider(provider);
registerInstrumentations({
tracerProvider: trace.getTracerProvider(),
instrumentations: [
getWebAutoInstrumentations({
'@opentelemetry/instrumentation-fetch': {
propagateTraceHeaderCorsUrls: /.*/,
clearTimingResources: true,
applyCustomAttributesOnSpan(span) {
span.setAttribute('demo.synthetic_request', IS_SYNTHETIC_REQUEST);
},
},
}),
],
});
};
Node の required モジュールは --require コマンドライン引数を使って読み込まれます。
これは package.json の scripts.start セクションで設定し、npm start でアプリケーションを起動することで実現できます。
"scripts": {
"start": "node --require ./Instrumentation.js server.js",
},
トレース
スパンの例外とステータス
スパンオブジェクトの recordException 関数を使用して、処理済みのエラーの完全なスタックトレースを含むスパンイベントを作成できます。
例外を記録する際は、スパンのステータスも適切に設定するようにしてください。
これは utils/telemetry/InstrumentationMiddleware.ts ファイルの NextApiHandler 関数の catch ブロックで確認できます。
span.recordException(error as Exception);
span.setStatus({ code: SpanStatusCode.ERROR });
新しいスパンの作成
新しいスパンは Tracer.startSpan("spanName", options) を使って作成・開始できます。
スパンの作成方法を指定するために、いくつかのオプションが使用できます。
root: trueは新しいトレースを作成し、このスパンをルートとして設定します。linksは参照すべき他のスパン(別のトレース内のものも含む)へのリンクを指定するために使用します。attributesはスパンに追加されるキー/バリューのペアで、通常はアプリケーションのコンテキストに使用します。
span = tracer.startSpan(`${method}`, {
root: true,
kind: SpanKind.SERVER,
links: [{ context: syntheticSpan.spanContext() }],
attributes: {
'app.synthetic_request': true,
[ATTR_HTTP_RESPONSE_STATUS_CODE]: response.statusCode,
[ATTR_HTTP_REQUEST_METHOD]: method,
[ATTR_USER_AGENT_ORIGINAL]: headers['user-agent'] || '',
[ATTR_URL_PATH]: target,
[ATTR_URL_FULL]: `${headers.host}${url}`,
[ATTR_NETWORK_PROTOCOL_VERSION]: httpVersion,
},
});
ブラウザー計装
フロントエンドが提供するウェブベースの UI も、ウェブブラウザー向けに計装されています。
OpenTelemetry の計装は pages/_app.tsx の Next.js App コンポーネントの一部として含まれています。
ここで計装がインポートされ、初期化されます。
import FrontendTracer from '../utils/telemetry/FrontendTracer';
if (typeof window !== 'undefined') FrontendTracer();
utils/telemetry/FrontendTracer.ts ファイルには、TracerProvider の初期化、OTLP エクスポートの確立、context、propagation、trace API を通じたコンテキストマネージャーとトレースコンテキストプロパゲーターのグローバル登録、ウェブ固有の自動計装ライブラリの登録を行うコードが含まれています。
ブラウザーは別のドメインにある可能性が高い OpenTelemetry Collector にデータを送信するため、CORS ヘッダーも適切に設定されています。
バックエンドサービスに synthetic_request 属性フラグを引き継ぐための変更の一環として、applyCustomAttributesOnSpan 設定関数が instrumentation-fetch ライブラリのカスタムスパン属性ロジックに追加されており、これによりすべてのブラウザー側のスパンにこの属性が含まれます。
import { context, propagation, trace } from '@opentelemetry/api';
import {
CompositePropagator,
W3CBaggagePropagator,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import { SimpleSpanProcessor, TracerProvider } from '@opentelemetry/sdk-trace';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
const FrontendTracer = async () => {
const { ZoneContextManager } = await import('@opentelemetry/context-zone');
const provider = new TracerProvider({
resource: resourceFromAttributes({
[ATTR_SERVICE_NAME]: process.env.NEXT_PUBLIC_OTEL_SERVICE_NAME,
}),
spanProcessors: [
new SimpleSpanProcessor({ exporter: new OTLPTraceExporter() }),
],
});
context.setGlobalContextManager(new ZoneContextManager().enable());
propagation.setGlobalPropagator(
new CompositePropagator({
propagators: [
new W3CBaggagePropagator(),
new W3CTraceContextPropagator(),
],
}),
);
trace.setGlobalTracerProvider(provider);
registerInstrumentations({
tracerProvider: trace.getTracerProvider(),
instrumentations: [
getWebAutoInstrumentations({
'@opentelemetry/instrumentation-fetch': {
propagateTraceHeaderCorsUrls: /.*/,
clearTimingResources: true,
applyCustomAttributesOnSpan(span) {
span.setAttribute('demo.synthetic_request', 'false');
},
},
}),
],
});
};
export default FrontendTracer;
メトリクス
TBD
ログ
TBD
バゲージ
OpenTelemetry のバゲージは、リクエストがシンセティック(負荷生成ツールからのもの)かどうかを確認するためにフロントエンドで活用されています。 シンセティックリクエストは新しいトレースの作成を強制します。 新しいトレースのルートスパンには、HTTP リクエストの計装スパンと同じ属性の多くが含まれます。
バゲージアイテムが設定されているかどうかを判定するには、propagation API を使ってバゲージヘッダーを解析し、baggage API を使ってエントリーを取得または設定します。
const baggage = propagation.getBaggage(context.active());
if (baggage?.getEntry("synthetic_request")?.value == "true") {...}
フィードバック
このページは役に立ちましたか?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!