Skip to content

Commit

Permalink
feat: Add add_link to span api/sdk (#1623)
Browse files Browse the repository at this point in the history
* add add_link to span api/sdk

* Update api/lib/opentelemetry/trace/span.rb

Co-authored-by: Kayla Reopelle (she/her) <87386821+kaylareopelle@users.noreply.github.com>

* Update sdk/lib/opentelemetry/sdk/trace/span.rb

Co-authored-by: Kayla Reopelle (she/her) <87386821+kaylareopelle@users.noreply.github.com>

* only freeze links when the span is ended

---------

Co-authored-by: Kayla Reopelle (she/her) <87386821+kaylareopelle@users.noreply.github.com>
  • Loading branch information
dmathieu and kaylareopelle committed Apr 9, 2024
1 parent 35abeac commit f14bdac
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
22 changes: 22 additions & 0 deletions api/lib/opentelemetry/trace/span.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,28 @@ def add_attributes(attributes)
self
end

# Add a link to a {Span}.
#
# Adding links at span creation using the `links` option is preferred
# to calling add_link later, because head sampling decisions can only
# consider information present during span creation.
#
# Example:
#
# span.add_link(OpenTelemetry::Trace::Link.new(span_to_link_from.context))
#
# Note that the OpenTelemetry project
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
# documents} certain "standard attributes" that have prescribed semantic
# meanings.
#
# @param [OpenTelemetry::Trace::Link] the link object to add on the {Span}.
#
# @return [self] returns itself
def add_link(link)
self
end

# Add an event to a {Span}.
#
# Example:
Expand Down
6 changes: 6 additions & 0 deletions api/test/opentelemetry/trace/span_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
end
end

describe '#add_link' do
it 'returns self' do
_(span.add_link(OpenTelemetry::Trace::Link.new(span_context))).must_equal(span)
end
end

describe '#add_event' do
it 'returns self' do
_(span.add_event('event-name')).must_equal(span)
Expand Down
36 changes: 34 additions & 2 deletions sdk/lib/opentelemetry/sdk/trace/span.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,37 @@ def add_attributes(attributes)
self
end

# Add a link to a {Span}.
#
# Adding links at span creation using the `links` option is preferred
# to calling add_link later, because head sampling decisions can only
# consider information present during span creation.
#
# Example:
#
# span.add_link(OpenTelemetry::Trace::Link.new(span_to_link_from.context))
#
# Note that the OpenTelemetry project
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
# documents} certain "standard attributes" that have prescribed semantic
# meanings.
#
# @param [OpenTelemetry::Trace::Link] the link object to add on the {Span}.
#
# @return [self] returns itself
def add_link(link)
@mutex.synchronize do
if @ended
OpenTelemetry.logger.warn('Calling add_link on an ended Span.')
else
@links ||= []
@links = trim_links(@links << link, @span_limits.link_count_limit, @span_limits.link_attribute_count_limit)
@total_recorded_links += 1
end
end
self
end

# Add an Event to a {Span}.
#
# Example:
Expand Down Expand Up @@ -242,6 +273,7 @@ def finish(end_timestamp: nil)
@end_timestamp = relative_timestamp(end_timestamp)
@attributes = validated_attributes(@attributes).freeze
@events.freeze
@links.freeze
@ended = true
end
@span_processors.each { |processor| processor.on_finish(self) }
Expand Down Expand Up @@ -373,7 +405,7 @@ def trim_links(links, link_count_limit, link_attribute_count_limit) # rubocop:di

if links.size <= link_count_limit &&
links.all? { |link| link.span_context.valid? && link.attributes.size <= link_attribute_count_limit && Internal.valid_attributes?(name, 'link', link.attributes) }
return links.frozen? ? links : links.clone.freeze
return links
end

# Slow path: trim attributes for each Link.
Expand All @@ -386,7 +418,7 @@ def trim_links(links, link_count_limit, link_attribute_count_limit) # rubocop:di
excess = attrs.size - link_attribute_count_limit
excess.times { attrs.shift } if excess.positive?
OpenTelemetry::Trace::Link.new(link.span_context, attrs)
end.freeze
end
end

def append_event(events, event) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
Expand Down
41 changes: 41 additions & 0 deletions sdk/test/opentelemetry/sdk/trace/span_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,47 @@
end
end

describe '#add_link' do
it 'does not add a link if span is ended' do
span.finish
span.add_link(OpenTelemetry::Trace::Link.new(context))
_(span.links).must_be_nil
end

it 'adds a link' do
span.add_link(OpenTelemetry::Trace::Link.new(context))
links = span.links
_(links.size).must_equal(1)
_(links.first.span_context).must_equal(context)
end

it 'adds a link with attributes' do
attrs = { 'foo' => 'bar' }
span.add_link(OpenTelemetry::Trace::Link.new(context, attrs))
links = span.links
_(links.size).must_equal(1)
_(links.first.attributes).must_equal(attrs)
end

it 'updates the links count' do
span.add_link(OpenTelemetry::Trace::Link.new(context))
span.add_link(OpenTelemetry::Trace::Link.new(context))
_(span.to_span_data.total_recorded_links).must_equal(2)
end

it 'trims excess links' do
span.add_link(OpenTelemetry::Trace::Link.new(context))
span.add_link(OpenTelemetry::Trace::Link.new(context))
_(span.links.size).must_equal(1)
end

it 'prunes invalid links' do
invalid_context = OpenTelemetry::Trace::SpanContext.new(trace_id: OpenTelemetry::Trace::INVALID_TRACE_ID)
span.add_link(OpenTelemetry::Trace::Link.new(invalid_context))
_(span.links.size).must_equal(0)
end
end

describe '#add_event' do
it 'add a named event' do
span.add_event('added')
Expand Down

0 comments on commit f14bdac

Please sign in to comment.