Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
marcotc committed Sep 19, 2024
1 parent 9c95130 commit e2b815c
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 44 deletions.
2 changes: 0 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,3 @@ end
#
# TODO: Remove this once the issue is resolved: https://github.com/ffi/ffi/issues/1107
gem 'ffi', '~> 1.16.3', require: false

# gem 'aws-sdk'
2 changes: 2 additions & 0 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ Aws::S3::Client.new.list_buckets
| `enabled` | `DD_TRACE_AWS_ENABLED` | `Bool` | Whether the integration should create spans. | `true` |
| `service_name` | `DD_TRACE_AWS_SERVICE_NAME` | `String` | Name of application running the `aws` instrumentation. May be overridden by `global_default_service_name`. [See _Additional Configuration_ for more details](#additional-configuration) | `aws` |
| `peer_service` | `DD_TRACE_AWS_PEER_SERVICE` | `String` | Name of external service the application connects to | `nil` |
| `propagation` | `DD_TRACE_AWS_PROPAGATION_ENABLED` | `Bool` | Enables distributed trace propagation for SNS and SQS messages. | `false` |
| `parentage_style` | `DD_TRACE_AWS_TRACE_PARENTAGE_STYLE` | `String` | Controls whether the local trace is parented to the SQS message consumed. Possible values are: `local`, `distributed`. This option is always disable (the equivalent to `local`) if `propagation` is disabled. | `local` |

### Concurrent Ruby

Expand Down
1 change: 1 addition & 0 deletions lib/datadog/tracing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require_relative 'core'
require_relative 'tracing/pipeline'
require_relative 'tracing/distributed'

module Datadog
# Datadog APM tracing public API.
Expand Down
35 changes: 0 additions & 35 deletions lib/datadog/tracing/contrib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require_relative '../tracing'
require_relative 'contrib/registry'
require_relative 'contrib/extensions'
require_relative 'contrib/component'

module Datadog
module Tracing
Expand All @@ -27,40 +26,6 @@ module Contrib
# after the tracer has complete initialization. Use `Datadog::Tracing::Contrib::REGISTRY` instead
# of `Datadog.registry` when you code might be called during tracer initialization.
REGISTRY = Registry.new

def self.inject(digest, data)
raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation

@propagation.inject!(digest, data)
end

def self.extract(data)
raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation

@propagation.extract(data)
end

Contrib::Component.register('_contrib') do |config|
tracing = config.tracing
tracing.propagation_style # TODO: do we still need this?

@propagation = Datadog::Tracing::Distributed::Propagation.new(
propagation_styles: {
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER =>
Tracing::Distributed::B3Multi.new(fetcher: Tracing::Distributed::Fetcher),
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER =>
Tracing::Distributed::B3Single.new(fetcher: Tracing::Distributed::Fetcher),
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG =>
Tracing::Distributed::Datadog.new(fetcher: Tracing::Distributed::Fetcher),
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT =>
Tracing::Distributed::TraceContext.new(fetcher: Tracing::Distributed::Fetcher),
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => Tracing::Distributed::None.new
},
propagation_style_inject: tracing.propagation_style_inject,
propagation_style_extract: tracing.propagation_style_extract,
propagation_extract_first: tracing.propagation_extract_first
)
end
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/datadog/tracing/contrib/aws/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,18 @@ class Settings < Contrib::Configuration::Settings
o.default false
end

# Controls whether the local trace is parented to the SNS message consumed.
# Controls whether the local trace is parented to the SQS message consumed.
# Possible values are:
# `local`: The local active trace is used; SNS has no effect on trace parentage.
# `distributed`: The local active trace becomes a child of the propagation context from the SNS message.
# `distributed`: The local active trace becomes a child of the propagation context from the SQS message.
#
# This option is always disable (the equivalent to`local`) if `propagation` is disabled.
# @default `DD_TRACE_AWS_TRACE_PARENTAGE_STYLE` environment variable, otherwise `distributed`
# @default `DD_TRACE_AWS_TRACE_PARENTAGE_STYLE` environment variable, otherwise `local`
# @return [String]
option :parentage_style do |o|
o.type :string
o.env Ext::ENV_TRACE_PARENTAGE_STYLE
o.default 'distributed'
o.default 'local'
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/datadog/tracing/contrib/aws/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ def call(context)
start_time = Core::Utils::Time.now.utc # Save the start time as the span creation is delayed
begin
response = @handler.call(context)
rescue Exception => e
rescue Exception => e # rubocop:disable Lint/RescueException
# Catch exception to reraise it inside the trace block, to ensure the span has correct error information
# This matches the behavior of {Datadog::Tracing::SpanOperation#measure}
end

Tracing.trace(Ext::SPAN_COMMAND, start_time: start_time) do |span, trace|
Expand Down
6 changes: 4 additions & 2 deletions lib/datadog/tracing/contrib/aws/service/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ def add_tags(span, params); end
def extract_propagation!(response, data_type)
messages = response.data.messages

# DEV: Extract the context from the first message today.
# DEV: Use span links in the future to support multiple messages related to a single span.
return unless (message = messages[0])

message_attributes = message.message_attributes

return unless message_attributes && (datadog = message_attributes['_datadog'])

if (data = datadog[data_type]) && (parsed_data = JSON.parse(data))
Tracing.continue_trace!(Contrib.extract(parsed_data))
Tracing.continue_trace!(Distributed.extract(parsed_data))
end
end

Expand All @@ -33,7 +35,7 @@ def inject_propagation(trace, params, data_type)
return if message_attributes.size >= MESSAGE_ATTRIBUTES_LIMIT

data = {}
if Datadog::Tracing::Contrib.inject(trace.to_digest, data)
if Distributed.inject(trace.to_digest, data)
message_attributes['_datadog'] = { :data_type => data_type, :binary_value => data.to_json }
end
end
Expand Down
59 changes: 59 additions & 0 deletions lib/datadog/tracing/distributed.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

require_relative 'distributed/b3_multi'
require_relative 'distributed/b3_single'
require_relative 'distributed/datadog'
require_relative 'distributed/none'
require_relative 'distributed/propagation'
require_relative 'distributed/trace_context'
require_relative 'contrib/component'

module Datadog
module Tracing
# Namespace for distributed tracing propagation and correlation
module Distributed
module_function

# Inject distributed headers into the given request
# @param digest [Datadog::Tracing::TraceDigest] the trace to inject
# @param data [Hash] the request to inject
def inject(digest, data)
raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation

@propagation.inject!(digest, data)
end

# Extract distributed headers from the given request
# @param data [Hash] the request to extract from
# @return [Datadog::Tracing::TraceDigest,nil] the extracted trace digest or nil if none was found
def extract(data)
raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation

@propagation.extract(data)
end

Contrib::Component.register('distributed') do |config|
tracing = config.tracing
# DEV: evaluate propagation_style in case it overrides propagation_style_extract & propagation_extract_first
tracing.propagation_style

@propagation = Propagation.new(
propagation_styles: {
Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER =>
B3Multi.new(fetcher: Fetcher),
Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER =>
B3Single.new(fetcher: Fetcher),
Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG =>
Datadog.new(fetcher: Fetcher),
Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT =>
TraceContext.new(fetcher: Fetcher),
Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => None.new
},
propagation_style_inject: tracing.propagation_style_inject,
propagation_style_extract: tracing.propagation_style_extract,
propagation_extract_first: tracing.propagation_extract_first
)
end
end
end
end
2 changes: 2 additions & 0 deletions lib/datadog/tracing/trace_digest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ def merge(field_value_pairs)
)
end

# rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
def ==(other)
self.class == other.class &&
span_id == other.span_id &&
Expand All @@ -204,6 +205,7 @@ def ==(other)
trace_state_unknown_fields == other.trace_state_unknown_fields &&
span_remote == other.span_remote
end
# rubocop:enable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity

alias eql? ==

Expand Down
12 changes: 12 additions & 0 deletions sig/datadog/tracing/distributed.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Datadog
module Tracing
module Distributed
@propagation: Propagation

def inject: (TraceDigest digest, ::Hash[untyped, untyped] data) -> (bool | nil)

def extract: (::Hash[untyped, untyped] data) -> (TraceDigest | nil)
end
end
end

33 changes: 33 additions & 0 deletions spec/datadog/tracing/distributed_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'datadog/tracing/distributed'

RSpec.describe Datadog::Tracing::Distributed do
context 'integration test' do
before { Datadog.configure {} }

describe '#inject' do
subject(:inject) { described_class.inject(digest, data) }
let(:trace_id) { Datadog::Tracing::Utils::TraceId.next_id }
let(:span_id) { Datadog::Tracing::Utils.next_id }
let(:digest) do
Datadog::Tracing::TraceDigest.new(trace_id: trace_id, span_id: span_id)
end
let(:data) { {} }

it 'injects distributed headers' do
inject
expect(data).to include('x-datadog-trace-id')
expect(data).to include('x-datadog-parent-id')
end
end

describe '#extract' do
subject(:extract) { described_class.extract(data) }

let(:data) { { 'x-datadog-trace-id' => '1', 'x-datadog-parent-id' => '2' } }

it 'extracts distributed headers' do
is_expected.to be_a_kind_of(Datadog::Tracing::TraceDigest)
end
end
end
end

0 comments on commit e2b815c

Please sign in to comment.