Skip to content

Commit

Permalink
feat(otel): support span events
Browse files Browse the repository at this point in the history
  • Loading branch information
mabdinur committed Jul 10, 2024
1 parent 7732142 commit be2749a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 3 deletions.
10 changes: 10 additions & 0 deletions lib/datadog/opentelemetry/sdk/span_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require_relative 'trace/span'
require_relative '../../tracing/span_link'
require_relative '../../tracing/span_event'
require_relative '../../tracing/trace_digest'

module Datadog
Expand Down Expand Up @@ -31,6 +32,15 @@ def on_start(span, parent_context)
#
# @param [Span] span the {Span} that just ended.
def on_finish(span)
unless span.events.nil?
span.datadog_span.span_events = span.events.map do |event|
Datadog::Tracing::SpanEvent.new(
event.name,
attributes: event.attributes,
time_unix_nano: event.timestamp
)
end
end
span.datadog_span.finish(ns_to_time(span.end_timestamp))
end

Expand Down
9 changes: 7 additions & 2 deletions lib/datadog/tracing/span.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Span
:resource,
:service,
:links,
:events,
:type,
:start_time,
:status,
Expand Down Expand Up @@ -60,7 +61,8 @@ def initialize(
type: nil,
trace_id: nil,
service_entry: nil,
links: nil
links: nil,
events: nil
)
@name = Core::Utils::SafeDup.frozen_or_dup(name)
@service = Core::Utils::SafeDup.frozen_or_dup(service)
Expand Down Expand Up @@ -90,6 +92,8 @@ def initialize(

@links = links || []

@events = events || []

# Mark with the service entry span metric, if applicable
set_metric(Metadata::Ext::TAG_TOP_LEVEL, 1.0) if service_entry
end
Expand Down Expand Up @@ -141,7 +145,8 @@ def to_hash
span_id: @id,
trace_id: @trace_id,
type: @type,
span_links: @links.map(&:to_hash)
span_links: @links.map(&:to_hash),
events: @events.map(&:to_hash)
}

if stopped?
Expand Down
5 changes: 4 additions & 1 deletion lib/datadog/tracing/span_operation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SpanOperation
:start_time,
:trace_id,
:type
attr_accessor :links, :status
attr_accessor :links, :status, :span_events

def initialize(
name,
Expand All @@ -49,6 +49,7 @@ def initialize(
trace_id: nil,
type: nil,
links: nil,
span_events: nil,
id: nil
)
# Ensure dynamically created strings are UTF-8 encoded.
Expand All @@ -68,6 +69,7 @@ def initialize(
@status = 0
# stores array of span links
@links = links || []
@span_events = span_events || []

# start_time and end_time track wall clock. In Ruby, wall clock
# has less accuracy than monotonic clock, so if possible we look to only use wall clock
Expand Down Expand Up @@ -455,6 +457,7 @@ def build_span
type: @type,
trace_id: @trace_id,
links: @links,
events: @span_events,
service_entry: parent.nil? || (service && parent.service != service)
)
end
Expand Down
3 changes: 3 additions & 0 deletions lib/datadog/tracing/transport/serializable_trace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ def to_msgpack(packer = nil)
packer.write_map_header(number_of_elements_to_write) # Set header with how many elements in the map
end

# convert span events to tags
# span.set_tag('events', span.events.map(&:to_hash).to_json) if span.events

# DEV: We use strings as keys here, instead of symbols, as
# DEV: MessagePack will ultimately convert them to strings.
# DEV: By providing strings directly, we skip this indirection operation.
Expand Down
35 changes: 35 additions & 0 deletions spec/datadog/opentelemetry_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,41 @@
end
end

describe '#add_event' do
subject! do
start_span
start_span.add_event('Exception was raised!', **event_options)
start_span.finish
end

let(:start_span) { otel_tracer.start_span('start-span', **span_options) }
let(:active_span) { Datadog::Tracing.active_span }

context 'with name, attributes and timestamp' do
let(:event_options) do
{ attributes: { 'raised' => false, 'handler' => 'default', 'count' => 1 }, timestamp: 17206369349 }
end

it 'adds one event to the span' do
expect(span.events.count).to eq(1)
expect(span.events[0].name).to eq('Exception was raised!')
expect(span.events[0].time_unix_nano).to eq(17206369349000000000)
expect(span.events[0].attributes).to eq({ 'raised' => 'false', 'handler' => 'default', 'count' => '1' })
end
end

context 'without a timestamp or attributes' do
let(:event_options) { {} }

it 'adds one event with timestamp set to the current time and attributes set to an empty hash' do
expect(span.events.count).to eq(1)
expect(span.events[0].name).to eq('Exception was raised!')
expect(span.events[0].time_unix_nano / 1e9).to be_within(1).of(Time.now.to_f)
expect(span.events[0].attributes).to eq({})
end
end
end

describe '#status=' do
subject! do
start_span
Expand Down

0 comments on commit be2749a

Please sign in to comment.