diff --git a/benchmarks/tracing_trace.rb b/benchmarks/tracing_trace.rb index 35d1ec8bfae..a34c39089de 100644 --- a/benchmarks/tracing_trace.rb +++ b/benchmarks/tracing_trace.rb @@ -78,13 +78,13 @@ def trace(x, depth) end end - def benchmark_to_digest + def benchmark_propagate! Datadog::Tracing.trace('op.name') do |span, trace| Benchmark.ips do |x| x.config(**benchmark_time) - x.report("trace.to_digest") do - trace.to_digest + x.report("trace.propagate!") do + trace.propagate! end x.save! "#{File.basename(__FILE__)}-results.json" unless VALIDATE_BENCHMARK_MODE @@ -108,13 +108,13 @@ def benchmark_log_correlation end end - def benchmark_to_digest_continue + def benchmark_propagate_continue Datadog::Tracing.trace('op.name') do |span, trace| Benchmark.ips do |x| x.config(**benchmark_time) - x.report("trace.to_digest - Continue") do - digest = trace.to_digest + x.report("trace.propagate! - Continue") do + digest = trace.propagate! Datadog::Tracing.continue_trace!(digest) end @@ -136,7 +136,7 @@ def benchmark_propagation_datadog end Datadog::Tracing.trace('op.name') do |span, trace| - injected_trace_digest = trace.to_digest + injected_trace_digest = trace.propagate! Benchmark.ips do |x| x.config(**benchmark_time) @@ -159,7 +159,7 @@ def benchmark_propagation_trace_context end Datadog::Tracing.trace('op.name') do |span, trace| - injected_trace_digest = trace.to_digest + injected_trace_digest = trace.propagate! Benchmark.ips do |x| x.config(**benchmark_time) @@ -190,9 +190,9 @@ def run_benchmark(&block) TracingTraceBenchmark.new.instance_exec do run_benchmark { benchmark_no_writer } run_benchmark { benchmark_no_network } - run_benchmark { benchmark_to_digest } + run_benchmark { benchmark_propagate! } run_benchmark { benchmark_log_correlation } - run_benchmark { benchmark_to_digest_continue } + run_benchmark { benchmark_propagate_continue } run_benchmark { benchmark_propagation_datadog } run_benchmark { benchmark_propagation_trace_context } end diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index 98cade51313..e5bc9ba9667 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -2418,7 +2418,7 @@ On the client: ```ruby Datadog::Tracing.trace('web.call') do |span, trace| # Inject trace headers into request headers (`env` must be a Hash) - Datadog::Tracing::Contrib::HTTP.inject(trace.to_digest, env) + Datadog::Tracing::Contrib::HTTP.inject(trace.propagate!, env) end ``` diff --git a/lib/datadog/opentelemetry/trace.rb b/lib/datadog/opentelemetry/trace.rb index e05dd6cb176..32f12d5e470 100644 --- a/lib/datadog/opentelemetry/trace.rb +++ b/lib/datadog/opentelemetry/trace.rb @@ -17,7 +17,7 @@ def start_trace_copy(trace, parent_span: nil) digest = if parent_span digest_with_parent_span(trace, parent_span) else - trace.to_digest + trace.to_digest_without_propagate end # Create a new TraceOperation, attached to the current Datadog Tracer. @@ -30,7 +30,8 @@ def start_trace_copy(trace, parent_span: nil) # This supports the implementation of `OpenTelemetry::Trace.context_with_span`, # which allows you to specific any span as the arbitrary parent of a new span. def digest_with_parent_span(trace, parent_span) - digest = trace.to_digest + # sampling_priority added here right upon otel span creation + digest = trace.to_digest_without_propagate Tracing::TraceDigest.new( span_id: parent_span.id, diff --git a/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb b/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb index e80baca6cf0..5ab6c126d70 100644 --- a/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +++ b/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb @@ -19,7 +19,7 @@ def initialize(composited_executor) # post method runs the task within composited executor - in a different thread. The original arguments are # captured to be propagated to the composited executor post method def post(*args, &task) - digest = Tracing.active_trace && Tracing.active_trace.to_digest + digest = Tracing.active_trace && Tracing.active_trace.propagate! executor = @composited_executor.is_a?(Symbol) ? Concurrent.executor(@composited_executor) : @composited_executor # Pass the original arguments to the composited executor, which diff --git a/lib/datadog/tracing/contrib/ethon/multi_patch.rb b/lib/datadog/tracing/contrib/ethon/multi_patch.rb index b8541155a35..e4456d521cb 100644 --- a/lib/datadog/tracing/contrib/ethon/multi_patch.rb +++ b/lib/datadog/tracing/contrib/ethon/multi_patch.rb @@ -62,7 +62,7 @@ def datadog_multi_span Ext::SPAN_MULTI_REQUEST, service: datadog_configuration[:service_name] ) - @datadog_multi_trace_digest = Tracing.active_trace.to_digest + @datadog_multi_trace_digest = Tracing.active_trace.propagate! @datadog_multi_span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT) @datadog_multi_span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_MULTI_REQUEST) diff --git a/lib/datadog/tracing/contrib/propagation/sql_comment.rb b/lib/datadog/tracing/contrib/propagation/sql_comment.rb index 62765f026ec..c68f319ba12 100644 --- a/lib/datadog/tracing/contrib/propagation/sql_comment.rb +++ b/lib/datadog/tracing/contrib/propagation/sql_comment.rb @@ -45,7 +45,7 @@ def self.prepend_comment(sql, span_op, trace_op, mode) # When tracing is disabled, trace_operation is a dummy object that does not contain data to build traceparent if config.tracing.enabled tags[Ext::KEY_TRACEPARENT] = - Tracing::Distributed::TraceContext.new(fetcher: nil).send(:build_traceparent, trace_op.to_digest) + Tracing::Distributed::TraceContext.new(fetcher: nil).send(:build_traceparent, trace_op.propagate!) else Datadog.logger.warn( 'Sql comment propagation with `full` mode is aborted, because tracing is disabled. '\ diff --git a/lib/datadog/tracing/distributed/propagation.rb b/lib/datadog/tracing/distributed/propagation.rb index 9ad8b63ee35..cf1e4183745 100644 --- a/lib/datadog/tracing/distributed/propagation.rb +++ b/lib/datadog/tracing/distributed/propagation.rb @@ -56,7 +56,7 @@ def inject!(digest, data) return nil end - digest = digest.to_digest if digest.respond_to?(:to_digest) + digest = digest.propagate! if digest.respond_to?(:propagate!) if digest.trace_id.nil? ::Datadog.logger.debug('Cannot inject distributed trace data: digest.trace_id is nil.') diff --git a/lib/datadog/tracing/trace_operation.rb b/lib/datadog/tracing/trace_operation.rb index 7c1d4fa55a7..bc5dd1db837 100644 --- a/lib/datadog/tracing/trace_operation.rb +++ b/lib/datadog/tracing/trace_operation.rb @@ -301,11 +301,42 @@ def flush! build_trace(spans, !finished) end + # DEV-3.0: Sampling is a side effect of generating the digest in to_digest. With 3.0 we should remove the side effect + # and push users to use propagate! instead of to_digest. With that we can remove this method. + def to_digest_no_propagation + span_id = @active_span && @active_span.id + span_id ||= @parent_span_id unless finished? + TraceDigest.new( + span_id: span_id, + span_name: (@active_span && @active_span.name), + span_resource: (@active_span && @active_span.resource), + span_service: (@active_span && @active_span.service), + span_type: (@active_span && @active_span.type), + trace_distributed_tags: distributed_tags, + trace_hostname: @hostname, + trace_id: @id, + trace_name: name, + trace_origin: @origin, + trace_process_id: Core::Environment::Identity.pid, + trace_resource: resource, + trace_runtime_id: Core::Environment::Identity.id, + trace_sampling_priority: @sampling_priority, + trace_service: service, + trace_state: @trace_state, + trace_state_unknown_fields: @trace_state_unknown_fields, + span_remote: (@remote_parent && @active_span.nil?), + ).freeze + end + + def propagate! + to_digest + end + # Returns a set of trace headers used for continuing traces. # Used for propagation across execution contexts. # Data should reflect the active state of the trace. - # DEV-3.0: Sampling is a side effect of generating the digest. - # We should move the sample call to inject and right before moving to new contexts(threads, forking etc.) + # DEV-3.0: Sampling is a side effect of generating the digest in to_digest. + # With 3.0 we should remove the side effect and push users to use propagate! instead of to_digest. def to_digest # Resolve current span ID span_id = @active_span && @active_span.id @@ -523,7 +554,7 @@ def build_trace(spans, partial = false) end # Returns tracer tags that will be propagated if this span's context - # is exported through {.to_digest}. + # is exported through {.propagate!}. # @return [Hash] key value pairs of distributed tags def distributed_tags meta.select { |name, _| name.start_with?(Metadata::Ext::Distributed::TAGS_PREFIX) } diff --git a/sig/datadog/tracing/trace_operation.rbs b/sig/datadog/tracing/trace_operation.rbs index e434c9872d6..85245e75954 100644 --- a/sig/datadog/tracing/trace_operation.rbs +++ b/sig/datadog/tracing/trace_operation.rbs @@ -39,6 +39,8 @@ module Datadog def build_span: (untyped op_name, ?events: untyped?, ?on_error: untyped?, ?resource: untyped?, ?service: untyped?, ?start_time: untyped?, ?tags: untyped?, ?type: untyped?) -> untyped def flush!: () { (untyped) -> untyped } -> untyped def to_digest: () -> untyped + def propagate!: () -> untyped + def to_digest_without_propagate: () -> untyped def fork_clone: () -> untyped class Events diff --git a/spec/datadog/tracing/contrib/propagation/sql_comment_spec.rb b/spec/datadog/tracing/contrib/propagation/sql_comment_spec.rb index 9217b684fa2..91bf84721d9 100644 --- a/spec/datadog/tracing/contrib/propagation/sql_comment_spec.rb +++ b/spec/datadog/tracing/contrib/propagation/sql_comment_spec.rb @@ -66,7 +66,7 @@ end let(:trace_op) do double( - to_digest: Datadog::Tracing::TraceDigest.new( + propagate!: Datadog::Tracing::TraceDigest.new( trace_id: 0xC0FFEE, span_id: 0xBEE, trace_flags: 0xFE diff --git a/spec/datadog/tracing/contrib/sql_comment_propagation_examples.rb b/spec/datadog/tracing/contrib/sql_comment_propagation_examples.rb index 0c401a74648..70da8f41357 100644 --- a/spec/datadog/tracing/contrib/sql_comment_propagation_examples.rb +++ b/spec/datadog/tracing/contrib/sql_comment_propagation_examples.rb @@ -69,7 +69,7 @@ expect(Datadog::Tracing::Contrib::Propagation::SqlComment).to have_received(:prepend_comment).with( sql_statement, a_span_operation_with(service: service_name), - duck_type(:to_digest), + duck_type(:propagate!), propagation_mode ) end @@ -90,7 +90,7 @@ expect(Datadog::Tracing::Contrib::Propagation::SqlComment).to have_received(:prepend_comment).with( sql_statement, a_span_operation_with(service: service_name), - duck_type(:to_digest), + duck_type(:propagate!), propagation_mode ) end diff --git a/spec/datadog/tracing/trace_operation_spec.rb b/spec/datadog/tracing/trace_operation_spec.rb index 4977ef7cdd0..a4ba92226e3 100644 --- a/spec/datadog/tracing/trace_operation_spec.rb +++ b/spec/datadog/tracing/trace_operation_spec.rb @@ -136,6 +136,22 @@ end context 'given' do + context ':trace_operation_triggers_trace_propagated_event' do + let(:events) { instance_double('Events') } + let(:trace_propagated) { instance_double('TracePropagated') } + let(:trace_op) { described_class.new(events: events) } + before do + allow(events).to receive(:trace_propagated).and_return(trace_propagated) + allow(trace_propagated).to receive(:publish) + end + describe '#propagate!' do + it 'calls events.trace_propagated.publish with self' do + expect(trace_propagated).to receive(:publish).with(trace_op) + trace_op.to_digest + end + end + end + context ':agent_sample_rate' do subject(:options) { { agent_sample_rate: agent_sample_rate } } let(:agent_sample_rate) { 0.5 } diff --git a/spec/datadog/tracing/tracer_integration_spec.rb b/spec/datadog/tracing/tracer_integration_spec.rb index e7f1f3b0462..c4a3e2a3670 100644 --- a/spec/datadog/tracing/tracer_integration_spec.rb +++ b/spec/datadog/tracing/tracer_integration_spec.rb @@ -84,7 +84,7 @@ def lang_tag(span) workers = nil tracer.trace('start_inserts', resource: 'inventory') do - trace_digest = trace.to_digest + trace_digest = trace.propagate! workers = Array.new(5) do |index| Thread.new do @@ -305,7 +305,7 @@ def lang_tag(span) describe 'distributed trace' do let(:extract) { Datadog::Tracing::Contrib::HTTP.extract(rack_headers) } let(:trace) { Datadog::Tracing.continue_trace!(extract) } - let(:inject) { {}.tap { |env| Datadog::Tracing::Contrib::HTTP.inject(trace.to_digest, env) } } + let(:inject) { {}.tap { |env| Datadog::Tracing::Contrib::HTTP.inject(trace.propagate!, env) } } let(:rack_headers) { headers.map { |k, v| [RackSupport.header_to_rack(k), v] }.to_h } diff --git a/spec/datadog/tracing/tracer_spec.rb b/spec/datadog/tracing/tracer_spec.rb index 945b3884e25..8d42cac80d8 100644 --- a/spec/datadog/tracing/tracer_spec.rb +++ b/spec/datadog/tracing/tracer_spec.rb @@ -893,7 +893,7 @@ trace_state_unknown_fields: 'any;field', ) expect(digest.span_remote).to be true - expect(trace.to_digest.span_remote).to be false + expect(trace.propagate!.span_remote).to be false expect(trace.send(:distributed_tags)).to eq('_dd.p.test' => 'value')