Skip to content

Commit

Permalink
Add correct breadcrumb levels for 4xx/5xx response codes (#2549)
Browse files Browse the repository at this point in the history
  • Loading branch information
sl0thentr0py authored Feb 7, 2025
1 parent 01abd66 commit 1fb93ad
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 26 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Unreleased

### Features

- Add correct breadcrumb levels for 4xx/5xx response codes ([#2549](https://github.com/getsentry/sentry-ruby/pull/2549))

### Miscellaneous

- Deprecate `enable_tracing` in favor of `traces_sample_rate = 1.0` [#2535](https://github.com/getsentry/sentry-ruby/pull/2535)
Expand Down
16 changes: 15 additions & 1 deletion sentry-ruby/lib/sentry/utils/http_tracing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def set_propagation_headers(req)

def record_sentry_breadcrumb(request_info, response_status)
crumb = Sentry::Breadcrumb.new(
level: :info,
level: get_level(response_status),
category: self.class::BREADCRUMB_CATEGORY,
type: "info",
data: { status: response_status, **request_info }
Expand Down Expand Up @@ -55,6 +55,20 @@ def build_nested_query(value, prefix = nil)
"#{URI.encode_www_form_component(prefix)}=#{URI.encode_www_form_component(value)}"
end
end

private

def get_level(status)
return :info unless status && status.is_a?(Integer)

if status >= 500
:error
elsif status >= 400
:warning
else
:info
end
end
end
end
end
11 changes: 11 additions & 0 deletions sentry-ruby/spec/sentry/breadcrumb/http_logger_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@
{ status: 200, method: "POST", url: "http://example.com/path", query: "foo=bar", body: 'quz=qux' }
)
end

{ 200 => :info, 302 => :info, 400 => :warning, 404 => :warning, 500 => :error, 502 => :error }.each do |status, level|
it "has correct level #{level} for #{status}" do
stub_normal_response(code: status)
response = Net::HTTP.get_response(URI("http://example.com/path?foo=bar"))

crumb = Sentry.get_current_scope.breadcrumbs.peek
expect(crumb.level).to eq(level)
expect(crumb.data[:status]).to eq(status)
end
end
end

context "with config.send_default_pii = false" do
Expand Down
45 changes: 32 additions & 13 deletions sentry-ruby/spec/sentry/excon_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,24 +117,43 @@
})
end

it "records breadcrumbs" do
Excon.stub({}, { body: "", status: 200 })
context "breadcrumbs" do
it "records correct data in breadcrumbs" do
Excon.stub({}, { body: "", status: 200 })

transaction = Sentry.start_transaction
Sentry.get_current_scope.set_span(transaction)
transaction = Sentry.start_transaction
Sentry.get_current_scope.set_span(transaction)

_response = Excon.get("http://example.com/path?foo=bar", mock: true)

_response = Excon.get("http://example.com/path?foo=bar", mock: true)
transaction.span_recorder.spans.last

transaction.span_recorder.spans.last
crumb = Sentry.get_current_scope.breadcrumbs.peek
expect(crumb.category).to eq("http")
expect(crumb.level).to eq(:info)
expect(crumb.data[:status]).to eq(200)
expect(crumb.data[:method]).to eq("GET")
expect(crumb.data[:url]).to eq("http://example.com/path")
expect(crumb.data[:query]).to eq("foo=bar")
expect(crumb.data[:body]).to be(nil)
end

{ 200 => :info, 400 => :warning, 500 => :error }.each do |status, level|
it "has correct level #{level} for #{status}" do
Excon.stub({}, { body: "", status: status })

transaction = Sentry.start_transaction
Sentry.get_current_scope.set_span(transaction)

crumb = Sentry.get_current_scope.breadcrumbs.peek
_response = Excon.get("http://example.com/path?foo=bar", mock: true)

expect(crumb.category).to eq("http")
expect(crumb.data[:status]).to eq(200)
expect(crumb.data[:method]).to eq("GET")
expect(crumb.data[:url]).to eq("http://example.com/path")
expect(crumb.data[:query]).to eq("foo=bar")
expect(crumb.data[:body]).to be(nil)
transaction.span_recorder.spans.last

crumb = Sentry.get_current_scope.breadcrumbs.peek
expect(crumb.level).to eq(level)
expect(crumb.data[:status]).to eq(status)
end
end
end
end

Expand Down
53 changes: 41 additions & 12 deletions sentry-ruby/spec/sentry/faraday_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@
stub.post("/test") do
[200, { "Content-Type" => "application/json" }, { hello: "world" }.to_json]
end

stub.get("/200") do
[200, { "Content-Type" => "text/html" }, "<h1>hello world</h1>"]
end

stub.get("/400") do
[400, { "Content-Type" => "text/html" }, "<h1>bad request</h1>"]
end

stub.get("/500") do
[500, { "Content-Type" => "text/html" }, "<h1>server error</h1>"]
end
end
end
end
Expand Down Expand Up @@ -94,22 +106,39 @@
})
end

it "records breadcrumbs" do
transaction = Sentry.start_transaction
Sentry.get_current_scope.set_span(transaction)
context "breadcrumbs" do
it "records correct data in breadcrumbs" do
transaction = Sentry.start_transaction
Sentry.get_current_scope.set_span(transaction)

_response = http.get("/test?foo=bar")
_response = http.get("/test?foo=bar")

transaction.span_recorder.spans.last
transaction.span_recorder.spans.last

crumb = Sentry.get_current_scope.breadcrumbs.peek
crumb = Sentry.get_current_scope.breadcrumbs.peek
expect(crumb.category).to eq("http")
expect(crumb.level).to eq(:info)
expect(crumb.data[:status]).to eq(200)
expect(crumb.data[:method]).to eq("GET")
expect(crumb.data[:url]).to eq("http://example.com/test")
expect(crumb.data[:query]).to eq("foo=bar")
expect(crumb.data[:body]).to be(nil)
end

{ 200 => :info, 400 => :warning, 500 => :error }.each do |status, level|
it "has correct level #{level} for #{status}" do
transaction = Sentry.start_transaction
Sentry.get_current_scope.set_span(transaction)

expect(crumb.category).to eq("http")
expect(crumb.data[:status]).to eq(200)
expect(crumb.data[:method]).to eq("GET")
expect(crumb.data[:url]).to eq("http://example.com/test")
expect(crumb.data[:query]).to eq("foo=bar")
expect(crumb.data[:body]).to be(nil)
_response = http.get("/#{status}")

transaction.span_recorder.spans.last

crumb = Sentry.get_current_scope.breadcrumbs.peek
expect(crumb.level).to eq(level)
expect(crumb.data[:status]).to eq(status)
end
end
end

it "records POST request body" do
Expand Down

0 comments on commit 1fb93ad

Please sign in to comment.