メインコンテンツへスキップ
メインコンテンツへスキップ

トレースサンプリング

高スループットのサービスでは、1 秒あたり数百万ものスパンが生成されることがあります。すべてのスパンを保存するのは高コストなため、通常、チームは OpenTelemetry Collector の tail-sampling processor を使用して、N 件に 1 件のスパンだけを保持します。保持された各スパンには、N を記録する SampleRate 属性が付与されます。

データがサンプリングされると、単純な集計では正しい結果が得られません。count() は実際に発生したイベント数より N 倍少ない値を返し、sum()avg() には偏りが生じ、パーセンタイルもずれます。その結果、ダッシュボードには、実際より少ないリクエスト数、処理量、エラー率が表示されてしまいます。

ClickStack は、サンプリングを考慮したクエリエンジンによってこの問題を解決します。トレースソースにサンプルレート式を設定すると、クエリビルダーは SQL の集計を書き換え、各スパンがそのサンプルレートに応じて重み付けされるようにします。これは、ダッシュボード、アラート、アドホック検索全体にわたって適用されます。

仕組み

トレースソースに sampleRateExpression が設定されている場合、ClickStack は次のようにラップします:

greatest(toUInt64OrZero(toString(expr)), 1)

SampleRate 属性を持たないスパンの重みはデフォルトで 1 になるため、サンプリングされていないデータでは元のクエリと同じ結果になります。

その後、クエリビルダーが集計を書き換えます。

集計変更前変更後 (サンプリング補正後)
countcount()sum(weight)
count + conditioncountIf(cond)sumIf(weight, cond)
avgavg(col)sum(col * weight) / sum(weight)
sumsum(col)sum(col * weight)
quantile(p)quantile(p)(col)quantileTDigestWeighted(p)(col, weight)
min / max変更なし変更なし
count_distinct変更なし変更なし
注記

サンプリング時のパーセンタイルには、近似的な T-Digest スケッチである quantileTDigestWeighted を使用します。結果は近似値であり、完全に一致するわけではありません。

サンプルレート式の設定

Source Settings でトレースソースを開き、Sample Rate Expression フィールドに、スパンごとのサンプルレートを返す ClickHouse 式を入力します。

たとえば、OpenTelemetry の tail-sampling プロセッサがそのレートを SpanAttributes['SampleRate'] に書き込む場合:

ClickStack の Source Settings にある Sample Rate Expression フィールド

設定が完了すると、すべてのチャート、ダッシュボード、アラート、サービスダッシュボードのパネルに、サンプルレートを重み付けに用いた集計が自動的に適用されます。個々のクエリを変更する必要はありません。