opentelemetry-ruby分布式跟踪
opentelemetry #distributed-tracing #ruby
利用到分布式跟踪的库
- [[opentelemetry-instrumentation-http浅析]]
- [[opentelemetry-instrumentation-rack浅析]]
- [[opentelemetry-instrumentation-active_job浅析]]
配置
可通过环境变量
OTEL_PROPAGATORS
设置传递格式搜索该环境变量,可见默认使用tracecontext和baggage方式传递,会组装成
Context::Propagation::CompositeTextMapPropagator
# opentelemetry-sdk-1.2.0/lib/opentelemetry/sdk/configurator.rb
def configure_propagation
propagators = ENV.fetch('OTEL_PROPAGATORS', 'tracecontext,baggage').split(',').uniq.collect do |propagator|
case propagator
when 'tracecontext' then OpenTelemetry::Trace::Propagation::TraceContext.text_map_propagator
when 'baggage' then OpenTelemetry::Baggage::Propagation.text_map_propagator
when 'b3' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::B3::Single')
when 'b3multi' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::B3::Multi', 'b3')
when 'jaeger' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::Jaeger')
when 'xray' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::XRay')
when 'ottrace' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::OTTrace')
when 'none' then NoopTextMapPropagator.new
else
OpenTelemetry.logger.warn "The #{propagator} propagator is unknown and cannot be configured"
NoopTextMapPropagator.new
end
end
OpenTelemetry.propagation = Context::Propagation::CompositeTextMapPropagator.compose_propagators((@propagators || propagators).compact)
end
tracecontext和baggage以外的,需要另外引入gem
# opentelemetry-sdk-1.2.0/lib/opentelemetry/sdk/configurator.rb
def fetch_propagator(name, class_name, gem_suffix = name)
Kernel.const_get(class_name).text_map_propagator
rescue NameError
OpenTelemetry.logger.warn "The #{name} propagator cannot be configured - please add opentelemetry-propagator-#{gem_suffix} to your Gemfile"
nil
end
另外可见优先使用
@propagators
,而这是可以在SDK.configure
中设置的,例如OpenTelemetry::SDK.configure do |c|
c.propagators = [
OpenTelemetry::Trace::Propagation::TraceContext.text_map_propagator,
OpenTelemetry::Baggage::Propagation.text_map_propagator,
Sentry::OpenTelemetry::Propagator.new
]
end
使用propagator注入traceid和spanid
调用方使用
inject
方法将context注入到carrier(消息结构的消息头,例如http头,grpc的metadata……)中接收方从中还原出context
例如
OpenTelemetry::Trace:: Propagation::TraceContext::TextMapPropagator
,他将traceid和spanid拼接,以TRACEPARENT_KEY
标识,塞到carrier中# opentelemetry-api-1.1.0/lib/opentelemetry/trace/propagation/trace_context/text_map_propagator.rb
def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
span_context = Trace.current_span(context).context
return unless span_context.valid?
setter.set(carrier, TRACEPARENT_KEY, TraceParent.from_span_context(span_context).to_s)
setter.set(carrier, TRACESTATE_KEY, span_context.tracestate.to_s) unless span_context.tracestate.empty?
nil
end
def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)
return context unless trace_parent_value
tp = TraceParent.from_string(trace_parent_value)
tracestate = Tracestate.from_string(getter.get(carrier, TRACESTATE_KEY))
span_context = Trace::SpanContext.new(trace_id: tp.trace_id,
span_id: tp.span_id,
trace_flags: tp.flags,
tracestate: tracestate,
remote: true)
span = OpenTelemetry::Trace.non_recording_span(span_context)
OpenTelemetry::Trace.context_with_span(span, parent_context: context)
rescue OpenTelemetry::Error
context
end
又例如
OpenTelemetry::Context::Propagation::CompositeTextMapPropagator
,它可以组合多种propagator,使上下游兼容不同的协议# opentelemetry-api-1.1.0/lib/opentelemetry/context/propagation/composite_text_map_propagator.rb
def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
injectors = @injectors || @propagators
injectors.each do |injector|
injector.inject(carrier, context: context, setter: setter)
rescue StandardError => e
OpenTelemetry.logger.warn "Error in CompositePropagator#inject #{e.message}"
end
nil
end
def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
extractors = @extractors || @propagators
extractors.inject(context) do |ctx, extractor|
extractor.extract(carrier, context: ctx, getter: getter)
rescue StandardError => e
OpenTelemetry.logger.warn "Error in CompositePropagator#extract #{e.message}"
ctx
end
end
生成trace_id
?
相关模块
如下
- OpenTelemetry {:kla=>Module}
├─ - Baggage {:kla=>Module}
│ └─ - Propagation {:kla=>Module}
│ ├─ ContextKeys {:kla=>Module}
│ └─ TextMapPropagator {:kla=>Class}
├─ - Common {:kla=>Module}
│ └─ - Propagation {:kla=>Module}
│ ├─ RackEnvGetter {:kla=>Class}
│ └─ SymbolKeyGetter {:kla=>Class}
├─ - Context {:kla=>Class}
│ └─ - Propagation {:kla=>Module}
│ ├─ CompositeTextMapPropagator {:kla=>Class}
│ ├─ NoopTextMapPropagator {:kla=>Class}
│ ├─ RackEnvGetter {:kla=>Class}
│ ├─ TextMapGetter {:kla=>Class}
│ ├─ TextMapPropagator {:kla=>Class}
│ └─ TextMapSetter {:kla=>Class}
├─ - SDK {:kla=>Module}
│ └─ - Configurator {:kla=>Class}
│ └─ NoopTextMapPropagator {:kla=>Class}
└─ - Trace {:kla=>Module}
└─ - Propagation {:kla=>Module}
└─ - TraceContext {:kla=>Module}
├─ TextMapPropagator {:kla=>Class}
└─ + TraceParent {:kla=>Class}