-
Notifications
You must be signed in to change notification settings - Fork 373
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
[OpenTracing] Span and SpanContext implementation #472
Changes from all commits
04abcab
f8910b6
c6d3007
cdb7f4b
a8ca2e1
65915bf
8e369d5
6f16be3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,90 @@ | ||
module Datadog | ||
module OpenTracer | ||
# OpenTracing adapter for Datadog::Span | ||
class Span < ::OpenTracing::Span | ||
attr_reader \ | ||
:datadog_span | ||
|
||
def initialize(datadog_span:, span_context:) | ||
@datadog_span = datadog_span | ||
@span_context = span_context | ||
end | ||
|
||
# Set the name of the operation | ||
# | ||
# @param [String] name | ||
def operation_name=(name) | ||
datadog_span.name = name | ||
end | ||
|
||
# Span Context | ||
# | ||
# @return [SpanContext] | ||
def context | ||
@span_context | ||
end | ||
|
||
# Set a tag value on this span | ||
# @param key [String] the key of the tag | ||
# @param value [String, Numeric, Boolean] the value of the tag. If it's not | ||
# a String, Numeric, or Boolean it will be encoded with to_s | ||
def set_tag(key, value) | ||
tap { datadog_span.set_tag(key, value) } | ||
end | ||
|
||
# Set a baggage item on the span | ||
# @param key [String] the key of the baggage item | ||
# @param value [String] the value of the baggage item | ||
def set_baggage_item(key, value) | ||
tap do | ||
# SpanContext is immutable, so to make changes | ||
# build a new span context. | ||
@span_context = SpanContextFactory.clone( | ||
span_context: context, | ||
baggage: { key => value } | ||
) | ||
end | ||
end | ||
|
||
# Get a baggage item | ||
# @param key [String] the key of the baggage item | ||
# @return [String] value of the baggage item | ||
def get_baggage_item(key) | ||
context.baggage[key] | ||
end | ||
|
||
# @deprecated Use {#log_kv} instead. | ||
# Reason: event is an optional standard log field defined in spec and not required. Also, | ||
# method name {#log_kv} is more consistent with other language implementations such as Python and Go. | ||
# | ||
# Add a log entry to this span | ||
# @param event [String] event name for the log | ||
# @param timestamp [Time] time of the log | ||
# @param fields [Hash] Additional information to log | ||
def log(event: nil, timestamp: Time.now, **fields) | ||
super # Log deprecation warning | ||
|
||
# If the fields specify an error | ||
if fields.key?(:'error.object') | ||
datadog_span.set_error(fields[:'error.object']) | ||
end | ||
end | ||
|
||
# Add a log entry to this span | ||
# @param timestamp [Time] time of the log | ||
# @param fields [Hash] Additional information to log | ||
def log_kv(timestamp: Time.now, **fields) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the other error fields ( All standard log fields: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
# If the fields specify an error | ||
if fields.key?(:'error.object') | ||
datadog_span.set_error(fields[:'error.object']) | ||
end | ||
end | ||
|
||
# Finish the {Span} | ||
# @param end_time [Time] custom end time, if not now | ||
def finish(end_time: Time.now) | ||
datadog_span.finish(end_time) | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,14 @@ | ||
module Datadog | ||
module OpenTracer | ||
# OpenTracing adapter for SpanContext | ||
class SpanContext < ::OpenTracing::SpanContext | ||
attr_reader \ | ||
:datadog_context | ||
|
||
def initialize(datadog_context:, baggage: {}) | ||
@datadog_context = datadog_context | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
@baggage = baggage.freeze | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
module Datadog | ||
module OpenTracer | ||
# Creates new Datadog::OpenTracer::SpanContext | ||
module SpanContextFactory | ||
module_function | ||
|
||
def build(datadog_context:, baggage: {}) | ||
SpanContext.new( | ||
datadog_context: datadog_context, | ||
baggage: baggage.dup | ||
) | ||
end | ||
|
||
def clone(span_context:, baggage: {}) | ||
SpanContext.new( | ||
datadog_context: span_context.datadog_context, | ||
# Merge baggage from previous SpanContext | ||
baggage: span_context.baggage.merge(baggage) | ||
) | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
require 'spec_helper' | ||
|
||
require 'ddtrace/opentracer' | ||
require 'ddtrace/opentracer/helper' | ||
|
||
if Datadog::OpenTracer.supported? | ||
RSpec.describe Datadog::OpenTracer::SpanContextFactory do | ||
include_context 'OpenTracing helpers' | ||
|
||
describe 'class methods' do | ||
describe '#build' do | ||
context 'given Datadog::Context' do | ||
subject(:span_context) do | ||
described_class.build( | ||
datadog_context: datadog_context | ||
) | ||
end | ||
let(:datadog_context) { instance_double(Datadog::Context) } | ||
|
||
it { is_expected.to be_a_kind_of(Datadog::OpenTracer::SpanContext) } | ||
|
||
describe 'builds a SpanContext where' do | ||
it { expect(span_context.datadog_context).to be(datadog_context) } | ||
|
||
describe '#baggage' do | ||
subject(:baggage) { span_context.baggage } | ||
it { is_expected.to be_a_kind_of(Hash) } | ||
it { is_expected.to be_empty } | ||
end | ||
end | ||
|
||
context 'and baggage' do | ||
subject(:span_context) do | ||
described_class.build( | ||
datadog_context: datadog_context, | ||
baggage: original_baggage | ||
) | ||
end | ||
let(:original_baggage) { { 'account_id' => '1234' } } | ||
|
||
it { is_expected.to be_a_kind_of(Datadog::OpenTracer::SpanContext) } | ||
|
||
describe 'builds a SpanContext where' do | ||
it { expect(span_context.datadog_context).to be(datadog_context) } | ||
|
||
describe '#baggage' do | ||
subject(:baggage) { span_context.baggage } | ||
it { is_expected.to be_a_kind_of(Hash) } | ||
|
||
context 'when the original baggage contains data' do | ||
it { is_expected.to include('account_id' => '1234') } | ||
it { is_expected.to_not be(original_baggage) } | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
describe '#clone' do | ||
context 'given a SpanContext' do | ||
subject(:span_context) { described_class.clone(span_context: original_span_context) } | ||
let(:original_span_context) do | ||
instance_double( | ||
Datadog::OpenTracer::SpanContext, | ||
datadog_context: original_datadog_context, | ||
baggage: original_baggage | ||
) | ||
end | ||
let(:original_datadog_context) { instance_double(Datadog::Context) } | ||
let(:original_baggage) { {} } | ||
|
||
it { is_expected.to be_a_kind_of(Datadog::OpenTracer::SpanContext) } | ||
|
||
describe 'builds a SpanContext where' do | ||
it { expect(span_context.datadog_context).to be(original_datadog_context) } | ||
|
||
describe '#baggage' do | ||
subject(:baggage) { span_context.baggage } | ||
it { is_expected.to be_a_kind_of(Hash) } | ||
|
||
context 'when the original SpanContext contains baggage' do | ||
let(:original_baggage) { { 'org_id' => '4321' } } | ||
it { is_expected.to include('org_id' => '4321') } | ||
it { is_expected.to_not be(original_baggage) } | ||
end | ||
end | ||
end | ||
|
||
context 'and baggage' do | ||
subject(:span_context) { described_class.clone(span_context: original_span_context, baggage: param_baggage) } | ||
let(:param_baggage) { {} } | ||
|
||
it { is_expected.to be_a_kind_of(Datadog::OpenTracer::SpanContext) } | ||
|
||
describe 'builds a SpanContext where' do | ||
describe '#baggage' do | ||
subject(:baggage) { span_context.baggage } | ||
it { is_expected.to be_a_kind_of(Hash) } | ||
|
||
context 'when the original SpanContext contains baggage' do | ||
let(:original_baggage) { { 'org_id' => '4321' } } | ||
it { is_expected.to include('org_id' => '4321') } | ||
it { is_expected.to_not be(original_baggage) } | ||
end | ||
|
||
context 'when the original baggage contains data' do | ||
let(:param_baggage) { { 'account_id' => '1234' } } | ||
it { is_expected.to include('account_id' => '1234') } | ||
it { is_expected.to_not be(param_baggage) } | ||
end | ||
|
||
context 'when the original SpanContext baggage and param baggage contains data' do | ||
context 'that doesn\'t overlap' do | ||
let(:original_baggage) { { 'org_id' => '4321' } } | ||
let(:param_baggage) { { 'account_id' => '1234' } } | ||
it { is_expected.to include('org_id' => '4321', 'account_id' => '1234') } | ||
it { is_expected.to_not be(original_baggage) } | ||
it { is_expected.to_not be(param_baggage) } | ||
end | ||
|
||
context 'that overlaps' do | ||
let(:original_baggage) { { 'org_id' => '4321' } } | ||
let(:param_baggage) { { 'org_id' => '1234' } } | ||
it { is_expected.to include('org_id' => '1234') } | ||
it { is_expected.to_not be(original_baggage) } | ||
it { is_expected.to_not be(param_baggage) } | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍