diff --git a/config.example.yaml b/config.example.yaml index d6656f9..01dea1e 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -105,3 +105,7 @@ worker: # linuxDo linuxDo: api_key: "" + +# OpenTelemetry 配置 +otel: + sampling_rate: 0.1 # 采样率 0.0-1.0 diff --git a/internal/config/model.go b/internal/config/model.go index 4b5bc2a..f4e0f1f 100644 --- a/internal/config/model.go +++ b/internal/config/model.go @@ -35,6 +35,7 @@ type configModel struct { Worker workerConfig `mapstructure:"worker"` ClickHouse clickHouseConfig `mapstructure:"clickhouse"` LinuxDo linuxDoConfig `mapstructure:"linuxdo"` + Otel otelConfig `mapstructure:"otel"` } // appConfig 应用基本配置 @@ -141,3 +142,8 @@ type workerConfig struct { type linuxDoConfig struct { ApiKey string `mapstructure:"api_key"` } + +// otelConfig OpenTelemetry 配置 +type otelConfig struct { + SamplingRate float64 `mapstructure:"sampling_rate"` +} diff --git a/internal/otel_trace/sampler.go b/internal/otel_trace/sampler.go new file mode 100644 index 0000000..256cc23 --- /dev/null +++ b/internal/otel_trace/sampler.go @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (c) 2025 linux.do + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package otel_trace + +import ( + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +// ParentBasedErrorAwareSampler 创建父级感知的概率采样器 +// - 如果父 Span 已采样,则子 Span 也采样 +// - 如果父 Span 未采样,则子 Span 也不采样 +// - 如果是根 Span,按 samplingRate 概率采样 +func ParentBasedErrorAwareSampler(samplingRate float64) sdktrace.Sampler { + return sdktrace.ParentBased( + sdktrace.TraceIDRatioBased(samplingRate), + ) +} diff --git a/internal/otel_trace/trace_provider.go b/internal/otel_trace/trace_provider.go index 4c25911..4fef5fd 100644 --- a/internal/otel_trace/trace_provider.go +++ b/internal/otel_trace/trace_provider.go @@ -26,6 +26,7 @@ package otel_trace import ( "context" + "github.com/linux-do/cdk/internal/config" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/sdk/resource" @@ -56,6 +57,7 @@ func newTracerProvider() (*sdktrace.TracerProvider, error) { tracerProvider := sdktrace.NewTracerProvider( sdktrace.WithBatcher(traceExporter), sdktrace.WithResource(r), + sdktrace.WithSampler(ParentBasedErrorAwareSampler(config.Config.Otel.SamplingRate)), ) return tracerProvider, nil }