Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions sdk/lib/opentelemetry/sdk/configurator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ def fields

attr_writer :propagators, :error_handler, :id_generator

Components = Struct.new(:tracer_provider, :propagators, keyword_init: true)
Config = Struct.new(:propagator, :tracer_provider, keyword_init: true)

def initialize
@instrumentation_names = []
@instrumentation_config_map = {}
Expand Down Expand Up @@ -142,12 +145,12 @@ def add_log_record_processor(log_record_processor); end
# - setup tracer_provider, meter_provider, and logger_provider
# - install instrumentation
def configure
configuration = parse(ENV.fetch('OTEL_CONFIG_FILE', ''))
OpenTelemetry.logger = logger
OpenTelemetry.error_handler = error_handler
configure_propagation
configure_span_processors
tracer_provider.id_generator = @id_generator
OpenTelemetry.tracer_provider = tracer_provider
components = create(configuration)
OpenTelemetry.propagation = Context::Propagation::CompositeTextMapPropagator.compose_propagators(components.propagators.compact)
OpenTelemetry.tracer_provider = components.tracer_provider
metrics_configuration_hook
logs_configuration_hook
install_instrumentation
Expand All @@ -160,7 +163,7 @@ def metrics_configuration_hook; end
def logs_configuration_hook; end

def tracer_provider
@tracer_provider ||= Trace::TracerProvider.new(resource: @resource)
@tracer_provider ||= Trace::TracerProviderConfig.new
end

def check_use_mode!(mode)
Expand All @@ -178,8 +181,8 @@ def install_instrumentation
end

def configure_span_processors
processors = @span_processors.empty? ? wrapped_exporters_from_env.compact : @span_processors
processors.each { |p| tracer_provider.add_span_processor(p) }
@span_processors += tracer_provider&.span_processors || []
@span_processors.empty? ? wrapped_exporters_from_env.compact : @span_processors
end

def wrapped_exporters_from_env # rubocop:disable Metrics/CyclomaticComplexity
Expand All @@ -206,8 +209,20 @@ def wrapped_exporters_from_env # rubocop:disable Metrics/CyclomaticComplexity
end
end

def configure_propagation # rubocop:disable Metrics/CyclomaticComplexity
propagators = ENV.fetch('OTEL_PROPAGATORS', 'tracecontext,baggage').split(',').uniq.collect do |propagator|
def configure_propagation(propagator_config)
if propagator_config
propagator_list = propagator_config.composite_list&.split(',') || []
Array(propagator_config.composite&.instance_variables).each do |propagator|
propagatorList << propagator.to_s.delete_prefix('@').strip
end
else
propagator_list = ENV.fetch('OTEL_PROPAGATORS', 'tracecontext,baggage').split(',')
end
build_propagators(propagator_list)
end

def build_propagators(propagator_list) # rubocop:disable Metrics/CyclomaticComplexity
propagator_list.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
Expand All @@ -222,7 +237,6 @@ def configure_propagation # rubocop:disable Metrics/CyclomaticComplexity
NoopTextMapPropagator.new
end
end
OpenTelemetry.propagation = Context::Propagation::CompositeTextMapPropagator.compose_propagators((@propagators || propagators).compact)
end

def fetch_propagator(name, class_name, gem_suffix = name)
Expand All @@ -238,6 +252,24 @@ def fetch_exporter(name, class_name)
OpenTelemetry.logger.warn "The #{name} exporter cannot be configured - please add opentelemetry-exporter-#{name} to your Gemfile, spans will not be exported"
nil
end

def parse(filepath)
Config.new
end

def create(config)
Components.new.tap do |c|
c.tracer_provider = Trace::TracerProvider.new(
sampler: tracer_provider&.sampler,
resource: @resource,
id_generator: @id_generator || tracer_provider&.id_generator,
span_limits: tracer_provider&.span_limits,
span_processors: configure_span_processors,
tracer_provider_config: config&.tracer_provider
)
c.propagators = @propagators || configure_propagation(config&.propagator)
end
end
end
end
end
1 change: 1 addition & 0 deletions sdk/lib/opentelemetry/sdk/trace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ module Trace
require 'opentelemetry/sdk/trace/span'
require 'opentelemetry/sdk/trace/tracer'
require 'opentelemetry/sdk/trace/tracer_provider'
require 'opentelemetry/sdk/trace/tracer_provider_config'
12 changes: 6 additions & 6 deletions sdk/lib/opentelemetry/sdk/trace/samplers/parent_based.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ module Samplers
# * Local parent (!SpanContext.remote? with trace_flags.sampled?)
# * Local parent (!SpanContext.remote? with !trace_flags.sampled?)
class ParentBased
def initialize(root, remote_parent_sampled, remote_parent_not_sampled, local_parent_sampled, local_parent_not_sampled)
@root = root
@remote_parent_sampled = remote_parent_sampled
@remote_parent_not_sampled = remote_parent_not_sampled
@local_parent_sampled = local_parent_sampled
@local_parent_not_sampled = local_parent_not_sampled
def initialize(root = nil, remote_parent_sampled = nil, remote_parent_not_sampled = nil, local_parent_sampled = nil, local_parent_not_sampled = nil)
@root = root || Samplers::ALWAYS_ON
@remote_parent_sampled = remote_parent_sampled || Samplers::ALWAYS_ON
@remote_parent_not_sampled = remote_parent_not_sampled || Samplers::ALWAYS_OFF
@local_parent_sampled = local_parent_sampled || Samplers::ALWAYS_ON
@local_parent_not_sampled = local_parent_not_sampled || Samplers::ALWAYS_OFF
end

def ==(other)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ module Samplers
class TraceIdRatioBased
attr_reader :description

def initialize(probability)
@probability = probability
def initialize(probability = nil)
@probability = probability || Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0))
raise ArgumentError, 'ratio must be in range [0.0, 1.0]' unless (0.0..1.0).cover?(@probability)

@id_upper_bound = (probability * (2**64 - 1)).ceil
@description = format('TraceIdRatioBased{%.6f}', probability)
end
Expand Down
48 changes: 39 additions & 9 deletions sdk/lib/opentelemetry/sdk/trace/tracer_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,28 @@ class TracerProvider < OpenTelemetry::Trace::TracerProvider # rubocop:disable Me
# @param [optional SpanLimits] span_limits The limits to apply to attribute,
# event and link counts for Spans created by Tracers created by this
# TracerProvider
# @param [optional SpanProcessors] span_processors The span span processors to be used to,
# process & export traces to a backend.
# @param [optional TracerProviderConfig] tracer_provider_config The configuration block used to
# configure the tracer provider which includes the config for tracers as well as plugins.
#
# @return [TracerProvider]
def initialize(sampler: sampler_from_environment(Samplers.parent_based(root: Samplers::ALWAYS_ON)),
def initialize(sampler: nil,
resource: OpenTelemetry::SDK::Resources::Resource.create,
id_generator: OpenTelemetry::Trace,
span_limits: SpanLimits::DEFAULT)
id_generator: nil,
span_limits: nil,
span_processors: nil,
tracer_provider_config: nil)
@mutex = Mutex.new
@registry = {}
@registry_mutex = Mutex.new
@span_processors = []
@span_limits = span_limits
@sampler = sampler
@id_generator = id_generator
@span_limits = span_limits || tracer_provider_config&.limits || SpanLimits::DEFAULT
@sampler = sampler || tracer_provider_config&.samplar ? sampler_from_config(tracer_provider_config&.sampler) : sampler_from_environment
@id_generator = id_generator || OpenTelemetry::Trace
@stopped = false
@resource = resource
Array(span_processors).each { |p| add_span_processor(p) }
end

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

private

def sampler_from_environment(default_sampler)
case ENV.fetch('OTEL_TRACES_SAMPLER', nil)
def sampler_from_config(sampler_config) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
ivar = sampler_config.instance_variables.first
sampler_name = ivar.to_s.delete_prefix('@')
config = obj.instance_variable_get(ivar)

if sampler_config.parent_based&.root&.always_off
root = Samplers::ALWAYS_OFF
elsif sampler_config.parent_based&.root&.always_on
root = Samplers::ALWAYS_ON
elsif sampler_config.parent_based # this acts as a default
root = TraceIdRatioBased.new(probability: sampler_config.parent_based.root&.trace_id_ratio_based&.ratio || 1.0)
end

build_sampler(sampler_name, config, root)
end # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity

def sampler_from_environment
build_sampler(ENV.fetch('OTEL_TRACES_SAMPLER', nil))
end

def build_sampler(sampler, config = nil, root = nil) # rubocop:disable Metrics/CyclomaticComplexity
default_sampler = Samplers.parent_based(root: Samplers::ALWAYS_ON)
case sampler
when 'always_on' then Samplers::ALWAYS_ON
when 'always_off' then Samplers::ALWAYS_OFF
when 'trace_id_ratio_based' then TraceIdRatioBased.new(probability: config&.ratio || 1.0)
when 'parent_based' then ParentBased.new(root)
when 'traceidratio' then Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0)))
when 'parentbased_always_on' then Samplers.parent_based(root: Samplers::ALWAYS_ON)
when 'parentbased_always_off' then Samplers.parent_based(root: Samplers::ALWAYS_OFF)
Expand All @@ -182,7 +212,7 @@ def sampler_from_environment(default_sampler)
rescue StandardError => e
OpenTelemetry.handle_error(exception: e, message: "installing default sampler #{default_sampler.description}")
default_sampler
end
end # rubocop:enable Metrics/CyclomaticComplexity
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions sdk/lib/opentelemetry/sdk/trace/tracer_provider_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
module SDK
module Trace
# The manually specified tracer provider configuring for the SDK to use.
class TracerProviderConfig
attr_accessor :sampler, :id_generator, :span_limits, :span_processors

def initialize
@span_processors = []
end

def add_span_processor(processor)
@span_processors << processor
end
end
end
end
end
Loading