Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Tracer.non_recording_span to API #799

Merged
merged 8 commits into from
Jun 8, 2021
6 changes: 4 additions & 2 deletions api/benchmarks/span_bench.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
# SPDX-License-Identifier: Apache-2.0

require 'benchmark/ipsa'
require 'opentelemetry'
require 'opentelemetry/sdk'

span = OpenTelemetry::Trace::Span.new
OpenTelemetry::SDK.configure
tracer = OpenTelemetry.tracer_provider.tracer('bench')
span = tracer.start_root_span('bench')

attributes = {
'component' => 'rack',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ module OpenTelemetry
module Trace
module Propagation
module TraceContext
# Propagates baggage using the W3C Trace Context format
# Propagates trace context using the W3C Trace Context format
class TextMapPropagator
TRACEPARENT_KEY = 'traceparent'
TRACESTATE_KEY = 'tracestate'
FIELDS = [TRACEPARENT_KEY, TRACESTATE_KEY].freeze

private_constant :TRACEPARENT_KEY, :TRACESTATE_KEY, :FIELDS

# Returns a new TextMapPropagator.
def initialize
@tracer = nil # Lazily initialized to avoid a circular dependency during API initialization.
end

# Inject trace context into the supplied carrier.
#
# @param [Carrier] carrier The mutable carrier to inject trace context into
Expand Down Expand Up @@ -53,7 +58,7 @@ def extract(carrier, context: Context.current, getter: Context::Propagation.text
trace_flags: tp.flags,
tracestate: tracestate,
remote: true)
span = Trace::Span.new(span_context: span_context)
span = tracer.non_recording_span(span_context)
OpenTelemetry::Trace.context_with_span(span)
rescue OpenTelemetry::Error
context
Expand All @@ -66,6 +71,12 @@ def extract(carrier, context: Context.current, getter: Context::Propagation.text
def fields
FIELDS
end

private

def tracer
@tracer ||= OpenTelemetry.tracer_provider.tracer('w3c-trace-context-propagator')
end
end
end
end
Expand Down
10 changes: 10 additions & 0 deletions api/lib/opentelemetry/trace/tracer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ def start_span(name, with_parent: nil, attributes: nil, links: nil, start_timest
Span::INVALID
end
end

# Wraps a SpanContext with an object implementing the Span interface. This is done in order
# to expose a SpanContext as a Span in operations such as in-process Span propagation.
#
# @param [SpanContext] span_context SpanContext to be wrapped
#
# @return [Span]
def non_recording_span(span_context)
Span.new(span_context: span_context)
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@
tracestate_key => tracestate_header
}
end
let(:tracer) { OpenTelemetry.tracer_provider.tracer(__FILE__) }
let(:context) { Context.empty }
let(:context_with_tracestate) do
span_context = SpanContext.new(trace_id: ("\xff" * 16).b, span_id: ("\x11" * 8).b,
tracestate: tracestate_header)
span = Span.new(span_context: span_context)
span = tracer.non_recording_span(span_context)
OpenTelemetry::Trace.context_with_span(span, parent_context: Context.empty)
end
let(:context_without_tracestate) do
span_context = SpanContext.new(trace_id: ("\xff" * 16).b, span_id: ("\x11" * 8).b)
span = Span.new(span_context: span_context)
span = tracer.non_recording_span(span_context)
OpenTelemetry::Trace.context_with_span(span, parent_context: Context.empty)
end

Expand Down
2 changes: 1 addition & 1 deletion api/test/opentelemetry/trace/tracer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def start_span(*)
let(:parent_span_context) { OpenTelemetry::Trace::SpanContext.new }
let(:parent_context) do
OpenTelemetry::Trace.context_with_span(
OpenTelemetry::Trace::Span.new(span_context: parent_span_context),
tracer.non_recording_span(parent_span_context),
parent_context: OpenTelemetry::Context.empty
)
end
Expand Down
2 changes: 1 addition & 1 deletion api/test/opentelemetry/trace_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
end

it 'returns the current span from the provided context' do
span = OpenTelemetry::Trace::Span.new(span_context: OpenTelemetry::Trace::SpanContext.new)
span = tracer.non_recording_span(OpenTelemetry::Trace::SpanContext.new)
context = OpenTelemetry::Trace.context_with_span(span, parent_context: Context.empty)
_(OpenTelemetry::Trace.current_span).wont_equal(span)
_(OpenTelemetry::Trace.current_span(context)).must_equal(span)
Expand Down
32 changes: 16 additions & 16 deletions api/test/opentelemetry_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@
require 'tempfile'

describe OpenTelemetry do
class CustomSpan < OpenTelemetry::Trace::Span
end

class CustomTracer < OpenTelemetry::Trace::Tracer
def start_root_span(*)
CustomSpan.new
end
end

class CustomTracerProvider < OpenTelemetry::Trace::TracerProvider
def tracer(name = nil, version = nil)
CustomTracer.new
end
end

describe '.tracer_provider' do
after do
# Ensure we don't leak custom tracer factories and tracers to other tests
Expand All @@ -24,27 +39,12 @@
end

it 'returns user specified tracer provider' do
custom_tracer_provider = 'a custom tracer provider'
custom_tracer_provider = CustomTracerProvider.new
OpenTelemetry.tracer_provider = custom_tracer_provider
_(OpenTelemetry.tracer_provider).must_equal(custom_tracer_provider)
end
end

class CustomSpan < OpenTelemetry::Trace::Span
end

class CustomTracer < OpenTelemetry::Trace::Tracer
def start_root_span(*)
CustomSpan.new
end
end

class CustomTracerProvider < OpenTelemetry::Trace::TracerProvider
def tracer(name = nil, version = nil)
CustomTracer.new
end
end

describe '.tracer_provider=' do
after do
# Ensure we don't leak custom tracer factories and tracers to other tests
Expand Down
5 changes: 4 additions & 1 deletion common/lib/opentelemetry/common/utilities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ module Utilities

STRING_PLACEHOLDER = ''.encode(::Encoding::UTF_8).freeze

TRACER = OpenTelemetry.tracer_provider.tracer('opentelemetry-common-utilities', VERSION)
private_constant :TRACER

# Returns nil if timeout is nil, 0 if timeout has expired,
# or the remaining (positive) time left in seconds.
#
Expand Down Expand Up @@ -73,7 +76,7 @@ def truncate(string, size)
end

def untraced
OpenTelemetry::Trace.with_span(OpenTelemetry::Trace::Span.new) { yield }
OpenTelemetry::Trace.with_span(TRACER.non_recording_span(OpenTelemetry::Trace::SpanContext.new)) { yield }
end

# Returns a URL string with userinfo removed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

describe OpenTelemetry::Instrumentation::Rack do
let(:instrumentation) { OpenTelemetry::Instrumentation::Rack::Instrumentation.instance }
let(:tracer) { OpenTelemetry.tracer_provider.tracer(__FILE__) }
fbogsany marked this conversation as resolved.
Show resolved Hide resolved

it 'has #name' do
_(instrumentation.name).must_equal 'OpenTelemetry::Instrumentation::Rack'
Expand All @@ -32,16 +33,16 @@
end

it 'returns the span when set' do
test_span = OpenTelemetry::Trace::Span.new
test_span = new_span
context = OpenTelemetry::Instrumentation::Rack.context_with_span(test_span)
_(OpenTelemetry::Instrumentation::Rack.current_span(context)).must_equal(test_span)
end
end

describe '#with_span' do
it 'respects context nesting' do
test_span = OpenTelemetry::Trace::Span.new
test_span2 = OpenTelemetry::Trace::Span.new
test_span = new_span
test_span2 = new_span
OpenTelemetry::Instrumentation::Rack.with_span(test_span) do
_(OpenTelemetry::Instrumentation::Rack.current_span).must_equal(test_span)

Expand All @@ -53,4 +54,8 @@
end
end
end

def new_span
tracer.non_recording_span(OpenTelemetry::Trace::SpanContext.new)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ module TextMapExtractor
B3_SAMPLED_KEY = 'X-B3-Sampled'
B3_FLAGS_KEY = 'X-B3-Flags'

TRACER = OpenTelemetry.tracer_provider.tracer('b3-propagator')

private_constant :B3_CONTEXT_REGEX, :B3_TRACE_ID_REGEX, :B3_SPAN_ID_REGEX, :SAMPLED_VALUES
private_constant :B3_CONTEXT_KEY, :B3_TRACE_ID_KEY, :B3_SPAN_ID_KEY, :B3_SAMPLED_KEY, :B3_FLAGS_KEY
private_constant :TRACER

# Extract trace context from the supplied carrier. The b3 single header takes
# precedence over the multi-header format.
Expand Down Expand Up @@ -82,7 +85,7 @@ def extracted_context(trace_id_hex, span_id_hex, sampled, debug, context)
remote: true
)

span = Trace::Span.new(span_context: span_context)
span = TRACER.non_recording_span(span_context)
context = B3.context_with_debug(context) if debug
Trace.context_with_span(span, parent_context: context)
end
Expand Down
5 changes: 3 additions & 2 deletions propagator/b3/test/multi/text_map_propagator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
let(:sampled_key) { 'X-B3-Sampled' }
let(:flags_key) { 'X-B3-Flags' }
let(:all_keys) { [trace_id_key, span_id_key, parent_span_id_key, sampled_key, flags_key] }
let(:tracer) { OpenTelemetry.tracer_provider.tracer }

describe('#extract') do
it 'extracts context with trace id, span id, sampling flag, parent span id' do
Expand Down Expand Up @@ -199,8 +200,8 @@ def create_context(trace_id:,
trace_flags: OpenTelemetry::Trace::TraceFlags::DEFAULT,
b3_debug: false)
context = OpenTelemetry::Trace.context_with_span(
OpenTelemetry::Trace::Span.new(
span_context: OpenTelemetry::Trace::SpanContext.new(
tracer.non_recording_span(
OpenTelemetry::Trace::SpanContext.new(
trace_id: Array(trace_id).pack('H*'),
span_id: Array(span_id).pack('H*'),
trace_flags: trace_flags
Expand Down
5 changes: 3 additions & 2 deletions propagator/b3/test/single/text_map_propagator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

describe OpenTelemetry::Propagator::B3::Single::TextMapPropagator do
let(:propagator) { OpenTelemetry::Propagator::B3::Single::TextMapPropagator.new }
let(:tracer) { OpenTelemetry.tracer_provider.tracer }

describe('#extract') do
it 'extracts context with trace id, span id, sampling flag, parent span id' do
Expand Down Expand Up @@ -161,8 +162,8 @@ def create_context(trace_id:,
trace_flags: OpenTelemetry::Trace::TraceFlags::DEFAULT,
b3_debug: false)
context = OpenTelemetry::Trace.context_with_span(
OpenTelemetry::Trace::Span.new(
span_context: OpenTelemetry::Trace::SpanContext.new(
tracer.non_recording_span(
OpenTelemetry::Trace::SpanContext.new(
trace_id: Array(trace_id).pack('H*'),
span_id: Array(span_id).pack('H*'),
trace_flags: trace_flags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ class TextMapPropagator
FIELDS = [IDENTITY_KEY].freeze
TRACE_SPAN_IDENTITY_REGEX = /\A(?<trace_id>(?:[0-9a-f]){1,32}):(?<span_id>([0-9a-f]){1,16}):[0-9a-f]{1,16}:(?<sampling_flags>[0-9a-f]{1,2})\z/.freeze
ZERO_ID_REGEX = /^0+$/.freeze
TRACER = OpenTelemetry.tracer_provider.tracer('jaeger-propagator')

private_constant \
:IDENTITY_KEY, :DEFAULT_FLAG_BIT, :SAMPLED_FLAG_BIT, :DEBUG_FLAG_BIT,
:FIELDS, :TRACE_SPAN_IDENTITY_REGEX, :ZERO_ID_REGEX
:FIELDS, :TRACE_SPAN_IDENTITY_REGEX, :ZERO_ID_REGEX, :TRACER

# Extract trace context from the supplied carrier.
# If extraction fails, the original context will be returned
Expand Down Expand Up @@ -98,7 +99,7 @@ def build_span(match, sampling_flags)
trace_flags: to_trace_flags(sampling_flags),
remote: true
)
Trace::Span.new(span_context: span_context)
TRACER.non_recording_span(span_context)
end

def context_with_extracted_baggage(carrier, context, getter)
Expand Down
5 changes: 3 additions & 2 deletions propagator/jaeger/test/text_map_propagator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

describe OpenTelemetry::Propagator::Jaeger::TextMapPropagator do
let(:propagator) { OpenTelemetry::Propagator::Jaeger::TextMapPropagator.new }
let(:tracer) { OpenTelemetry.tracer_provider.tracer }

before do
OpenTelemetry::SDK::Configurator.new.configure
Expand Down Expand Up @@ -166,8 +167,8 @@ def create_context(trace_id:,
trace_flags: OpenTelemetry::Trace::TraceFlags::DEFAULT,
jaeger_debug: false)
context = OpenTelemetry::Trace.context_with_span(
OpenTelemetry::Trace::Span.new(
span_context: OpenTelemetry::Trace::SpanContext.new(
tracer.non_recording_span(
OpenTelemetry::Trace::SpanContext.new(
trace_id: Array(trace_id).pack('H*'),
span_id: Array(span_id).pack('H*'),
trace_flags: trace_flags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ class TextMapPropagator
VALID_BAGGAGE_HEADER_NAME_CHARS = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/.freeze
INVALID_BAGGAGE_HEADER_VALUE_CHARS = /[^\t\u0020-\u007E\u0080-\u00FF]/.freeze

TRACER = OpenTelemetry.tracer_provider.tracer('ottrace-propagator')

private_constant :PADDING, :VALID_TRACE_ID_REGEX, :VALID_SPAN_ID_REGEX, :TRACE_ID_64_BIT_WIDTH, :TRACE_ID_HEADER,
:SPAN_ID_HEADER, :SAMPLED_HEADER, :BAGGAGE_HEADER_PREFIX, :FIELDS, :VALID_BAGGAGE_HEADER_NAME_CHARS,
:INVALID_BAGGAGE_HEADER_VALUE_CHARS
:INVALID_BAGGAGE_HEADER_VALUE_CHARS, :TRACER

# Extract OTTrace context from the supplied carrier and set the active span
# in the given context. The original context will be returned if OTTrace
Expand All @@ -60,7 +62,7 @@ def extract(carrier, context: Context.current, getter: Context::Propagation.text
remote: true
)

span = Trace::Span.new(span_context: span_context)
span = TRACER.non_recording_span(span_context)
Trace.context_with_span(span, parent_context: set_baggage(carrier: carrier, context: context, getter: getter))
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ def set(carrier, key, value)
OpenTelemetry::Trace::TraceFlags::DEFAULT
end

let(:tracer) { OpenTelemetry.tracer_provider.tracer }

let(:context) do
OpenTelemetry::Trace.context_with_span(
OpenTelemetry::Trace::Span.new(
span_context: OpenTelemetry::Trace::SpanContext.new(
tracer.non_recording_span(
OpenTelemetry::Trace::SpanContext.new(
trace_id: Array(trace_id).pack('H*'),
span_id: Array(span_id).pack('H*'),
trace_flags: trace_flags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class TextMapPropagator
XRAY_CONTEXT_REGEX = /\ARoot=(?<trace_id>([a-z0-9\-]{35}))(?:;Parent=(?<span_id>([a-z0-9]{16})))?(?:;Sampled=(?<sampling_state>[01d](?![0-9a-f])))?(?:;(?<trace_state>.*))?\Z/.freeze
SAMPLED_VALUES = %w[1 d].freeze
FIELDS = [XRAY_CONTEXT_KEY].freeze
TRACER = OpenTelemetry.tracer_provider.tracer('xray-propagator')

private_constant :XRAY_CONTEXT_KEY, :XRAY_CONTEXT_REGEX, :SAMPLED_VALUES, :FIELDS

Expand Down Expand Up @@ -49,7 +50,7 @@ def extract(carrier, context: Context.current, getter: Context::Propagation.text
remote: true
)

span = Trace::Span.new(span_context: span_context)
span = TRACER.non_recording_span(span_context)
context = XRay.context_with_debug(context) if match['sampling_state'] == 'd'
Trace.context_with_span(span, parent_context: context)
rescue OpenTelemetry::Error
Expand Down
5 changes: 3 additions & 2 deletions propagator/xray/test/text_map_propagator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
SpanContext = OpenTelemetry::Trace::SpanContext
TraceFlags = OpenTelemetry::Trace::TraceFlags

let(:tracer) { OpenTelemetry.tracer_provider.tracer }
let(:propagator) { OpenTelemetry::Propagator::XRay::TextMapPropagator.new }

describe('#extract') do
Expand Down Expand Up @@ -156,8 +157,8 @@ def create_context(trace_id:,
trace_flags: TraceFlags::DEFAULT,
xray_debug: false)
context = OpenTelemetry::Trace.context_with_span(
Span.new(
span_context: SpanContext.new(
tracer.non_recording_span(
SpanContext.new(
trace_id: Array(trace_id).pack('H*'),
span_id: Array(span_id).pack('H*'),
trace_flags: trace_flags
Expand Down
Loading