Skip to content

Commit 6709d03

Browse files
committed
Scaffold out declarative config
1 parent fd3b31c commit 6709d03

6 files changed

Lines changed: 116 additions & 27 deletions

File tree

sdk/lib/opentelemetry/sdk/configurator.rb

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ def fields
3333

3434
attr_writer :propagators, :error_handler, :id_generator
3535

36+
Components = Struct.new(:tracer_provider, :propagators, keyword_init: true)
37+
Config = Struct.new(:propagator, :tracer_provider, keyword_init: true)
38+
3639
def initialize
3740
@instrumentation_names = []
3841
@instrumentation_config_map = {}
@@ -142,12 +145,12 @@ def add_log_record_processor(log_record_processor); end
142145
# - setup tracer_provider, meter_provider, and logger_provider
143146
# - install instrumentation
144147
def configure
148+
configuration = parse(ENV.fetch('OTEL_CONFIG_FILE', ''))
145149
OpenTelemetry.logger = logger
146150
OpenTelemetry.error_handler = error_handler
147-
configure_propagation
148-
configure_span_processors
149-
tracer_provider.id_generator = @id_generator
150-
OpenTelemetry.tracer_provider = tracer_provider
151+
components = create(configuration)
152+
OpenTelemetry.propagation = Context::Propagation::CompositeTextMapPropagator.compose_propagators(components.propagators.compact)
153+
OpenTelemetry.tracer_provider = components.tracer_provider
151154
metrics_configuration_hook
152155
logs_configuration_hook
153156
install_instrumentation
@@ -160,7 +163,7 @@ def metrics_configuration_hook; end
160163
def logs_configuration_hook; end
161164

162165
def tracer_provider
163-
@tracer_provider ||= Trace::TracerProvider.new(resource: @resource)
166+
@tracer_provider ||= Trace::TracerProviderConfig.new
164167
end
165168

166169
def check_use_mode!(mode)
@@ -178,8 +181,8 @@ def install_instrumentation
178181
end
179182

180183
def configure_span_processors
181-
processors = @span_processors.empty? ? wrapped_exporters_from_env.compact : @span_processors
182-
processors.each { |p| tracer_provider.add_span_processor(p) }
184+
@span_processors += tracer_provider&.span_processors || []
185+
@span_processors.empty? ? wrapped_exporters_from_env.compact : @span_processors
183186
end
184187

185188
def wrapped_exporters_from_env # rubocop:disable Metrics/CyclomaticComplexity
@@ -206,8 +209,20 @@ def wrapped_exporters_from_env # rubocop:disable Metrics/CyclomaticComplexity
206209
end
207210
end
208211

209-
def configure_propagation # rubocop:disable Metrics/CyclomaticComplexity
210-
propagators = ENV.fetch('OTEL_PROPAGATORS', 'tracecontext,baggage').split(',').uniq.collect do |propagator|
212+
def configure_propagation(propagator_config)
213+
if propagator_config
214+
propagator_list = propagator_config.composite_list&.split(',') || []
215+
Array(propagator_config.composite&.instance_variables).each do |propagator|
216+
propagatorList << propagator.to_s.delete_prefix('@').strip
217+
end
218+
else
219+
propagator_list = ENV.fetch('OTEL_PROPAGATORS', 'tracecontext,baggage').split(',')
220+
end
221+
build_propagators(propagator_list)
222+
end
223+
224+
def build_propagators(propagator_list) # rubocop:disable Metrics/CyclomaticComplexity
225+
propagator_list.uniq.collect do |propagator|
211226
case propagator
212227
when 'tracecontext' then OpenTelemetry::Trace::Propagation::TraceContext.text_map_propagator
213228
when 'baggage' then OpenTelemetry::Baggage::Propagation.text_map_propagator
@@ -222,7 +237,6 @@ def configure_propagation # rubocop:disable Metrics/CyclomaticComplexity
222237
NoopTextMapPropagator.new
223238
end
224239
end
225-
OpenTelemetry.propagation = Context::Propagation::CompositeTextMapPropagator.compose_propagators((@propagators || propagators).compact)
226240
end
227241

228242
def fetch_propagator(name, class_name, gem_suffix = name)
@@ -238,6 +252,24 @@ def fetch_exporter(name, class_name)
238252
OpenTelemetry.logger.warn "The #{name} exporter cannot be configured - please add opentelemetry-exporter-#{name} to your Gemfile, spans will not be exported"
239253
nil
240254
end
255+
256+
def parse(filepath)
257+
Config.new
258+
end
259+
260+
def create(config)
261+
Components.new.tap do |c|
262+
c.tracer_provider = Trace::TracerProvider.new(
263+
sampler: tracer_provider&.sampler,
264+
resource: @resource,
265+
id_generator: @id_generator || tracer_provider&.id_generator,
266+
span_limits: tracer_provider&.span_limits,
267+
span_processors: configure_span_processors,
268+
tracer_provider_config: config&.tracer_provider
269+
)
270+
c.propagators = @propagators || configure_propagation(config&.propagator)
271+
end
272+
end
241273
end
242274
end
243275
end

sdk/lib/opentelemetry/sdk/trace.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ module Trace
2222
require 'opentelemetry/sdk/trace/span'
2323
require 'opentelemetry/sdk/trace/tracer'
2424
require 'opentelemetry/sdk/trace/tracer_provider'
25+
require 'opentelemetry/sdk/trace/tracer_provider_config'

sdk/lib/opentelemetry/sdk/trace/samplers/parent_based.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ module Samplers
1818
# * Local parent (!SpanContext.remote? with trace_flags.sampled?)
1919
# * Local parent (!SpanContext.remote? with !trace_flags.sampled?)
2020
class ParentBased
21-
def initialize(root, remote_parent_sampled, remote_parent_not_sampled, local_parent_sampled, local_parent_not_sampled)
22-
@root = root
23-
@remote_parent_sampled = remote_parent_sampled
24-
@remote_parent_not_sampled = remote_parent_not_sampled
25-
@local_parent_sampled = local_parent_sampled
26-
@local_parent_not_sampled = local_parent_not_sampled
21+
def initialize(root = nil, remote_parent_sampled = nil, remote_parent_not_sampled = nil, local_parent_sampled = nil, local_parent_not_sampled = nil)
22+
@root = root || Samplers::ALWAYS_ON
23+
@remote_parent_sampled = remote_parent_sampled || Samplers::ALWAYS_ON
24+
@remote_parent_not_sampled = remote_parent_not_sampled || Samplers::ALWAYS_OFF
25+
@local_parent_sampled = local_parent_sampled || Samplers::ALWAYS_ON
26+
@local_parent_not_sampled = local_parent_not_sampled || Samplers::ALWAYS_OFF
2727
end
2828

2929
def ==(other)

sdk/lib/opentelemetry/sdk/trace/samplers/trace_id_ratio_based.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ module Samplers
1414
class TraceIdRatioBased
1515
attr_reader :description
1616

17-
def initialize(probability)
18-
@probability = probability
17+
def initialize(probability = nil)
18+
@probability = probability || Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0))
19+
raise ArgumentError, 'ratio must be in range [0.0, 1.0]' unless (0.0..1.0).cover?(@probability)
20+
1921
@id_upper_bound = (probability * (2**64 - 1)).ceil
2022
@description = format('TraceIdRatioBased{%.6f}', probability)
2123
end

sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,28 @@ class TracerProvider < OpenTelemetry::Trace::TracerProvider # rubocop:disable Me
2525
# @param [optional SpanLimits] span_limits The limits to apply to attribute,
2626
# event and link counts for Spans created by Tracers created by this
2727
# TracerProvider
28+
# @param [optional SpanProcessors] span_processors The span span processors to be used to,
29+
# process & export traces to a backend.
30+
# @param [optional TracerProviderConfig] tracer_provider_config The configuration block used to
31+
# configure the tracer provider which includes the config for tracers as well as plugins.
2832
#
2933
# @return [TracerProvider]
30-
def initialize(sampler: sampler_from_environment(Samplers.parent_based(root: Samplers::ALWAYS_ON)),
34+
def initialize(sampler: nil,
3135
resource: OpenTelemetry::SDK::Resources::Resource.create,
32-
id_generator: OpenTelemetry::Trace,
33-
span_limits: SpanLimits::DEFAULT)
36+
id_generator: nil,
37+
span_limits: nil,
38+
span_processors: nil,
39+
tracer_provider_config: nil)
3440
@mutex = Mutex.new
3541
@registry = {}
3642
@registry_mutex = Mutex.new
3743
@span_processors = []
38-
@span_limits = span_limits
39-
@sampler = sampler
40-
@id_generator = id_generator
44+
@span_limits = span_limits || tracer_provider_config&.limits || SpanLimits::DEFAULT
45+
@sampler = sampler || tracer_provider_config&.samplar ? sampler_from_config(tracer_provider_config&.sampler) : sampler_from_environment
46+
@id_generator = id_generator || OpenTelemetry::Trace
4147
@stopped = false
4248
@resource = resource
49+
Array(span_processors).each { |p| add_span_processor(p) }
4350
end
4451

4552
# Returns a {Tracer} instance.
@@ -169,10 +176,33 @@ def internal_start_span(name, kind, attributes, links, start_timestamp, parent_c
169176

170177
private
171178

172-
def sampler_from_environment(default_sampler)
173-
case ENV.fetch('OTEL_TRACES_SAMPLER', nil)
179+
def sampler_from_config(sampler_config) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
180+
ivar = sampler_config.instance_variables.first
181+
sampler_name = ivar.to_s.delete_prefix('@')
182+
config = obj.instance_variable_get(ivar)
183+
184+
if sampler_config.parent_based&.root&.always_off
185+
root = Samplers::ALWAYS_OFF
186+
elsif sampler_config&.parent_based&.root&.always_on
187+
root = Samplers::ALWAYS_ON
188+
elsif sampler_config.parent_based # this acts as a default
189+
root = TraceIdRatioBased.new(probability: sampler_config.parent_based.root&.trace_id_ratio_based&.ratio || 1.0)
190+
end
191+
192+
build_sampler(sampler_name, config, root)
193+
end # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
194+
195+
def sampler_from_environment
196+
build_sampler(ENV.fetch('OTEL_TRACES_SAMPLER', nil))
197+
end
198+
199+
def build_sampler(sampler, config = nil, root = nil) # rubocop:disable Metrics/CyclomaticComplexity
200+
default_sampler = Samplers.parent_based(root: Samplers::ALWAYS_ON)
201+
case sampler
174202
when 'always_on' then Samplers::ALWAYS_ON
175203
when 'always_off' then Samplers::ALWAYS_OFF
204+
when 'trace_id_ratio_based' then TraceIdRatioBased.new(probability: config&.ratio || 1.0)
205+
when 'parent_based' then ParentBased.new(root)
176206
when 'traceidratio' then Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0)))
177207
when 'parentbased_always_on' then Samplers.parent_based(root: Samplers::ALWAYS_ON)
178208
when 'parentbased_always_off' then Samplers.parent_based(root: Samplers::ALWAYS_OFF)
@@ -182,7 +212,7 @@ def sampler_from_environment(default_sampler)
182212
rescue StandardError => e
183213
OpenTelemetry.handle_error(exception: e, message: "installing default sampler #{default_sampler.description}")
184214
default_sampler
185-
end
215+
end # rubocop:enable Metrics/CyclomaticComplexity
186216
end
187217
end
188218
end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
module OpenTelemetry
8+
module SDK
9+
module Trace
10+
# The manually specified tracer provider configuring for the SDK to use.
11+
class TracerProviderConfig
12+
attr_accessor :sampler, :id_generator, :span_limits, :span_processors
13+
14+
def initialize
15+
@span_processors = []
16+
end
17+
18+
def add_span_processor(processor)
19+
@span_processors << processor
20+
end
21+
end
22+
end
23+
end
24+
end

0 commit comments

Comments
 (0)