-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[OpenTracing] Context propagation implementation (#495)
* Added: Propagators to OpenTracer. * Added: Specs for OpenTracer::Propagators. * Fixed: OpenTracer::Tracer#start_span not using provided SpanContext. * Added: OpenTracer context propagation integration specs.
- Loading branch information
Showing
14 changed files
with
973 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
module Datadog | ||
module OpenTracer | ||
# OpenTracing propagator for Datadog::OpenTracer::Tracer | ||
module BinaryPropagator | ||
extend Propagator | ||
|
||
# Inject a SpanContext into the given carrier | ||
# | ||
# @param span_context [SpanContext] | ||
# @param carrier [Carrier] A carrier object of Binary type | ||
def self.inject(span_context, carrier) | ||
nil | ||
end | ||
|
||
# Extract a SpanContext in Binary format from the given carrier. | ||
# | ||
# @param carrier [Carrier] A carrier object of Binary type | ||
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found | ||
def self.extract(carrier) | ||
SpanContext::NOOP_INSTANCE | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
require 'ddtrace/span' | ||
require 'ddtrace/ext/distributed' | ||
|
||
module Datadog | ||
module OpenTracer | ||
# DistributedHeaders provides easy access and validation to headers | ||
class DistributedHeaders | ||
include Datadog::Ext::DistributedTracing | ||
|
||
def initialize(carrier) | ||
@carrier = carrier | ||
end | ||
|
||
def valid? | ||
# Sampling priority is optional. | ||
!trace_id.nil? && !parent_id.nil? | ||
end | ||
|
||
def trace_id | ||
value = @carrier[HTTP_HEADER_TRACE_ID].to_i | ||
return if value <= 0 || value >= Datadog::Span::MAX_ID | ||
value | ||
end | ||
|
||
def parent_id | ||
value = @carrier[HTTP_HEADER_PARENT_ID].to_i | ||
return if value <= 0 || value >= Datadog::Span::MAX_ID | ||
value | ||
end | ||
|
||
def sampling_priority | ||
hdr = @carrier[HTTP_HEADER_SAMPLING_PRIORITY] | ||
# It's important to make a difference between no header, | ||
# and a header defined to zero. | ||
return unless hdr | ||
value = hdr.to_i | ||
return if value < 0 | ||
value | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module Datadog | ||
module OpenTracer | ||
# OpenTracing propagator for Datadog::OpenTracer::Tracer | ||
module Propagator | ||
# Inject a SpanContext into the given carrier | ||
# | ||
# @param span_context [SpanContext] | ||
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format` | ||
def inject(span_context, carrier) | ||
raise NotImplementedError | ||
end | ||
|
||
# Extract a SpanContext in the given format from the given carrier. | ||
# | ||
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format` | ||
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found | ||
def extract(carrier) | ||
raise NotImplementedError | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
require 'ddtrace/propagation/http_propagator' | ||
|
||
module Datadog | ||
module OpenTracer | ||
# OpenTracing propagator for Datadog::OpenTracer::Tracer | ||
module RackPropagator | ||
extend Propagator | ||
extend Datadog::Ext::DistributedTracing | ||
include Datadog::Ext::DistributedTracing | ||
|
||
BAGGAGE_PREFIX = 'ot-baggage-'.freeze | ||
BAGGAGE_PREFIX_FORMATTED = 'HTTP_OT_BAGGAGE_'.freeze | ||
|
||
class << self | ||
# Inject a SpanContext into the given carrier | ||
# | ||
# @param span_context [SpanContext] | ||
# @param carrier [Carrier] A carrier object of Rack type | ||
def inject(span_context, carrier) | ||
# Inject Datadog trace properties | ||
Datadog::HTTPPropagator.inject!(span_context.datadog_context, carrier) | ||
|
||
# Inject baggage | ||
span_context.baggage.each do |key, value| | ||
carrier[BAGGAGE_PREFIX + key] = value | ||
end | ||
|
||
nil | ||
end | ||
|
||
# Extract a SpanContext in Rack format from the given carrier. | ||
# | ||
# @param carrier [Carrier] A carrier object of Rack type | ||
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found | ||
def extract(carrier) | ||
# First extract & build a Datadog context | ||
datadog_context = Datadog::HTTPPropagator.extract(carrier) | ||
|
||
# Then extract any other baggage | ||
baggage = {} | ||
carrier.each do |key, value| | ||
baggage[header_to_baggage(key)] = value if baggage_header?(key) | ||
end | ||
|
||
SpanContextFactory.build(datadog_context: datadog_context, baggage: baggage) | ||
end | ||
|
||
private | ||
|
||
def baggage_header?(header) | ||
header.start_with?(BAGGAGE_PREFIX_FORMATTED) | ||
end | ||
|
||
def header_to_baggage(key) | ||
key[BAGGAGE_PREFIX_FORMATTED.length, key.length].downcase | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
require 'ddtrace/ext/distributed' | ||
|
||
module Datadog | ||
module OpenTracer | ||
# OpenTracing propagator for Datadog::OpenTracer::Tracer | ||
module TextMapPropagator | ||
extend Propagator | ||
extend Datadog::Ext::DistributedTracing | ||
include Datadog::Ext::DistributedTracing | ||
|
||
BAGGAGE_PREFIX = 'ot-baggage-'.freeze | ||
|
||
class << self | ||
# Inject a SpanContext into the given carrier | ||
# | ||
# @param span_context [SpanContext] | ||
# @param carrier [Carrier] A carrier object of Rack type | ||
def inject(span_context, carrier) | ||
# Inject Datadog trace properties | ||
span_context.datadog_context.tap do |datadog_context| | ||
carrier[HTTP_HEADER_TRACE_ID] = datadog_context.trace_id | ||
carrier[HTTP_HEADER_PARENT_ID] = datadog_context.span_id | ||
carrier[HTTP_HEADER_SAMPLING_PRIORITY] = datadog_context.sampling_priority | ||
end | ||
|
||
# Inject baggage | ||
span_context.baggage.each do |key, value| | ||
carrier[BAGGAGE_PREFIX + key] = value | ||
end | ||
|
||
nil | ||
end | ||
|
||
# Extract a SpanContext in TextMap format from the given carrier. | ||
# | ||
# @param carrier [Carrier] A carrier object of TextMap type | ||
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found | ||
def extract(carrier) | ||
# First extract & build a Datadog context | ||
headers = DistributedHeaders.new(carrier) | ||
|
||
datadog_context = if headers.valid? | ||
Datadog::Context.new( | ||
trace_id: headers.trace_id, | ||
span_id: headers.parent_id, | ||
sampling_priority: headers.sampling_priority | ||
) | ||
else | ||
Datadog::Context.new | ||
end | ||
|
||
# Then extract any other baggage | ||
baggage = {} | ||
carrier.each do |key, value| | ||
baggage[item_to_baggage(key)] = value if baggage_item?(key) | ||
end | ||
|
||
SpanContextFactory.build(datadog_context: datadog_context, baggage: baggage) | ||
end | ||
|
||
private | ||
|
||
def baggage_item?(item) | ||
item.start_with?(BAGGAGE_PREFIX) | ||
end | ||
|
||
def item_to_baggage(key) | ||
key[BAGGAGE_PREFIX.length, key.length] | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
require 'spec_helper' | ||
|
||
require 'ddtrace/opentracer' | ||
require 'ddtrace/opentracer/helper' | ||
|
||
if Datadog::OpenTracer.supported? | ||
RSpec.describe Datadog::OpenTracer::BinaryPropagator do | ||
include_context 'OpenTracing helpers' | ||
|
||
describe '#inject' do | ||
subject { described_class.inject(span_context, carrier) } | ||
let(:span_context) { instance_double(Datadog::OpenTracer::SpanContext) } | ||
let(:carrier) { instance_double(Datadog::OpenTracer::Carrier) } | ||
it { is_expected.to be nil } | ||
end | ||
|
||
describe '#extract' do | ||
subject(:span_context) { described_class.extract(carrier) } | ||
let(:carrier) { instance_double(Datadog::OpenTracer::Carrier) } | ||
it { is_expected.to be(Datadog::OpenTracer::SpanContext::NOOP_INSTANCE) } | ||
end | ||
end | ||
end |
Oops, something went wrong.