トレーシング¶
トレーシングは、分散システムの監視とデバッグのための強力なツールです。Vaporのトレーシング APIを使用すると、開発者はリクエストのライフサイクルを簡単に追跡し、メタデータを伝播し、OpenTelemetryなどの人気のあるバックエンドと統合できます。
Vaporのトレーシング APIはswift-distributed-tracingの上に構築されているため、swift-distributed-tracingのすべてのバックエンド実装と互換性があります。
Swiftでのトレーシングとスパンに馴染みがない場合は、OpenTelemetryトレースドキュメントとswift-distributed-tracingドキュメントを確認してください。
TracingMiddleware¶
各リクエストに対して完全に注釈付きのスパンを自動的に作成するには、アプリケーションにTracingMiddleware
を追加します。
app.middleware.use(TracingMiddleware())
正確なスパン測定を取得し、トレーシング識別子が他のサービスに正しく渡されるようにするには、このミドルウェアを他のミドルウェアの前に追加してください。
スパンの追加¶
ルートハンドラーにスパンを追加する場合、それらをトップレベルのリクエストスパンに関連付けることが理想的です。これは「スパン伝播」と呼ばれ、自動または手動の2つの方法で処理できます。
自動伝播¶
Vaporは、ミドルウェアとルートコールバック間でスパンを自動的に伝播する機能をサポートしています。これを行うには、設定時にApplication.traceAutoPropagation
プロパティをtrueに設定します。
app.traceAutoPropagation = true
Note
自動伝播を有効にすると、スパンが作成されるかどうかに関係なく、すべてのルートハンドラーでリクエストスパンメタデータを復元する必要があるため、最小限のトレーシングニーズを持つ高スループットAPIではパフォーマンスが低下する可能性があります。
その後、通常の分散トレーシング構文を使用してルートクロージャでスパンを作成できます。
app.get("fetchAndProcess") { req in
let result = try await fetch()
return try await withSpan("getNameParameter") { _ in
try await process(result)
}
}
手動伝播¶
自動伝播のパフォーマンスへの影響を避けるために、必要に応じて手動でスパンメタデータを復元できます。TracingMiddleware
は自動的にRequest.serviceContext
プロパティを設定し、これをwithSpan
のcontext
パラメータで直接使用できます。
app.get("fetchAndProcess") { req in
let result = try await fetch()
return try await withSpan("getNameParameter", context: req.serviceContext) { _ in
try await process(result)
}
}
スパンを作成せずにスパンメタデータを復元するには、ServiceContext.withValue
を使用します。これは、ダウンストリームの非同期ライブラリが独自のトレーシングスパンを発行し、それらが親リクエストスパンの下にネストされるべきであることがわかっている場合に有用です。
app.get("fetchAndProcess") { req in
try await ServiceContext.withValue(req.serviceContext) {
try await fetch()
return try await process(result)
}
}
NIOに関する考慮事項¶
swift-distributed-tracing
はTaskLocalプロパティ
を使用して伝播するため、スパンが正しくリンクされるようにするには、NIO EventLoopFuture
の境界を越えるたびに手動でコンテキストを再復元する必要があります。これは自動伝播が有効かどうかに関係なく必要です。
app.get("fetchAndProcessNIO") { req in
withSpan("fetch", context: req.serviceContext) { span in
fetchSomething().map { result in
withSpan("process", context: span.context) { _ in
process(result)
}
}
}
}