Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions sentry-ruby/lib/sentry/span.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,16 @@ def start_child(**attributes)
def with_child_span(**attributes, &block)
child_span = start_child(**attributes)

yield(child_span)
begin
yield(child_span)
rescue
child_span.set_http_status(500)
raise
ensure
child_span.finish
end

child_span.finish
rescue
child_span.set_http_status(500)
child_span.finish
raise
child_span
end

def deep_dup
Expand Down
51 changes: 51 additions & 0 deletions sentry-ruby/spec/sentry_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,57 @@
end
end

context "when the block exits early" do
let(:transaction) { described_class.start_transaction(name: "request", sampled: true) }

before do
perform_basic_setup { |config| config.traces_sample_rate = 1.0 }
described_class.get_current_scope.set_span(transaction)
end

def return_from_child_span
Sentry.with_child_span(op: "child") { return :returned }
end

def expect_finished_child_span
expect(Sentry.get_current_scope.get_span).to equal(transaction)
transaction.finish
expect(last_sentry_event.spans.size).to eq(1)
expect(last_sentry_event.spans.first).to include(op: "child", timestamp: be_a(Float))
end

it "records the span when the block breaks" do
result = described_class.with_child_span(op: "child") { break :returned }

expect(result).to eq(:returned)
expect_finished_child_span
end

it "records the span when the block returns from its enclosing method" do
expect(return_from_child_span).to eq(:returned)
expect_finished_child_span
end

it "records the span when the block throws" do
result = catch(:finished) do
described_class.with_child_span(op: "child") { throw :finished, :returned }
end

expect(result).to eq(:returned)
expect_finished_child_span
end

it "finishes the span and propagates exceptions outside StandardError" do
exception = Class.new(Exception).new("stop")

expect do
described_class.with_child_span(op: "child") { raise exception }
end.to raise_error { |raised| expect(raised).to equal(exception) }

expect_finished_child_span
end
end

context "when the current span is present" do
let(:parent_span) do
transaction = described_class.start_transaction(op: "foo")
Expand Down