iT邦幫忙

2022 iThome 鐵人賽

DAY 11
2
DevOps

淺談DevOps與Observability系列 第 11

淺談OpenTelemetry Specification - Trace Sampling

  • 分享至 

  • xImage
  •  

昨天聊API, 今天聊SDK

SDK重要的有Sampling, Span Creation, Processor, Exporter

Trace Samping


網路找的圖, 示意用
圖片來源Stratified Sampling | A Step-by-Step Guide with Examples

如果每個trace都要進行採樣紀錄, 能想想看, 每秒請求數幾千的小公司, 每天所產生的log容量得有多少? 對公司來說硬體存儲成本會很高.
如果能只需要採集一部分或需要的, 對我們來說是最好的.
當然這是一種tradeoff, 因為會沒辦法觀測到全部的請求.

Samping取樣, 這功能的目的是減少收集併發送到後端的trace樣本數量, 來控制
noice與開發的機制.

Samping的方式有兩種, Head-based Sampling與Tail-based Sampling

Head-based Sampling

在trace一開始就決定是否要採樣, 這策略有個問題, 就是事先沒辦法知道所有事情, 只能被迫做出任意的決定, 通常就是骰骰子隨機進行採樣.
甚至也沒辦法針對只有發生ERROR的span做採樣.

Tail-based Sampling

在整個請求流程結束時做出採樣的決定, 因為已經收集到了數據了. 就能在後半段決定是否要被存儲起來.
缺點就是一堆噪音還是要先被處理.

2種方法沒有一定好壞, 因為沒有一個策略能適合所有人.
第一種的好處是因為源頭就決定好了, 在網路中傳輸的數據個數就被大大減少了.
但決定要更新採樣機率時, 就很可能要重新佈署啟動程式.

如果選擇在後端或者是Collector中決定, 就會有網路傳輸成本, 以及Processor的處理成本要考慮.

OTel Sampler

Sampler的interface

// Sampler decides whether a trace should be sampled and exported.
type Sampler interface {
	// ShouldSample returns a SamplingResult based on a decision made from the
	// passed parameters.
	ShouldSample(parameters SamplingParameters) SamplingResult

	// Description returns information describing the Sampler.
	Description() string
}

Sampler採樣器, 需要在TraceProvider建立時就配置好

provider := sdktrace.NewTracerProvider(
	sdktrace.WithSampler(sdktrace.AlwaysSample()),
)

範例就是配置AlwaysSample採樣策略的採樣器
還有NeverSampleTraceIDRatioBasedParentBased

AlwaysSample

定義 : Sample every trace.
在Production環境尚要注意流量.

NeverSample

定義 : Sample no traces

TraceIDRatioBased

TraceIDRatioBased需要給[0,1]之間的fraction做參數.
如果給0.5, 則表示大概有一半的traceid的數據會被採樣.

ParentBased

根據Parent Span的策略做出採樣策略.
如果是Root Span, 則有默認的採樣策略. 通常是AlwaysSample或者TraceIDRatioBased.

Parent Type Default Sampler
RemoteParentSampled AlwaysOn
RemoteParentNotSampled AlwaysOff
LocalParentSample AlwaysOn
LocalParentNotSampled AlwaysOff
func ParentBased(root Sampler, samplers ...ParentBasedSamplerOption) Sampler {
	return parentBased{
		root:   root,
		config: configureSamplersForParentBased(samplers),
	}
}

func (pb parentBased) ShouldSample(p SamplingParameters) SamplingResult {
	psc := trace.SpanContextFromContext(p.ParentContext)
	if psc.IsValid() {
		if psc.IsRemote() {
			if psc.IsSampled() {
				return pb.config.remoteParentSampled.ShouldSample(p)
			}
			return pb.config.remoteParentNotSampled.ShouldSample(p)
		}

		if psc.IsSampled() {
			return pb.config.localParentSampled.ShouldSample(p)
		}
		return pb.config.localParentNotSampled.ShouldSample(p)
	}
	return pb.root.ShouldSample(p)
}

它的第一個參數是給Root Span用的.

所以Production環境上, 應該把TraceIDRatioBased與ParentBased採樣器一起使用.
RootSpan用Ratio決定, ChildSpan則根據Parent決定.

provider := sdktrace.NewTracerProvider(
    sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRationBased(0.5))),
)

參考資料

OTel specification - Trace SDK

OTel https://opentelemetry.io/docs/reference/specification/trace/tracestate-probability-sampling/


上一篇
淺談OpenTelemetry Specification - Trace
下一篇
淺談OpenTelemetry Specification - Trace Processor
系列文
淺談DevOps與Observability36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言