Skip to content
Merged
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
1 change: 1 addition & 0 deletions sentry-ruby/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Refactor tracing implementation [#1309](https://github.com/getsentry/sentry-ruby/pull/1309)
- Allow configuring BreadcrumbBuffer's size limit [#1310](https://github.com/getsentry/sentry-ruby/pull/1310)
- Return nil from logger methods instead of breadcrumb buffer [#1299](https://github.com/getsentry/sentry-ruby/pull/1299)
- Compress event payload by default [#1314](https://github.com/getsentry/sentry-ruby/pull/1314)

## 4.2.2

Expand Down
4 changes: 3 additions & 1 deletion sentry-ruby/lib/sentry/transport/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module Sentry
class Transport
class Configuration
attr_accessor :timeout, :open_timeout, :proxy, :ssl, :ssl_ca_file, :ssl_verification, :http_adapter, :faraday_builder, :transport_class
attr_accessor :timeout, :open_timeout, :proxy, :ssl, :ssl_ca_file, :ssl_verification, :http_adapter, :faraday_builder,
:transport_class, :encoding

def initialize
@ssl_verification = true
@open_timeout = 1
@timeout = 2
@encoding = HTTPTransport::GZIP_ENCODING
end

def transport_class=(klass)
Expand Down
18 changes: 17 additions & 1 deletion sentry-ruby/lib/sentry/transport/http_transport.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
require 'faraday'
require 'zlib'

module Sentry
class HTTPTransport < Transport
CONTENT_TYPE = 'application/json'
GZIP_ENCODING = "gzip"
GZIP_THRESHOLD = 1024 * 30

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the "usual" size and throughput of Ruby events that you've seen so far? A threshold of somewhere around 32kB seems reasonable intuitively, I'd just love to confirm.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Rails apps, I think it's generally over 40kb because of the framework's stacktrace. But it could be quite small on non-Ruby apps, like 1x kb.

CONTENT_TYPE = 'application/x-sentry-envelope'

attr_reader :conn, :adapter

def initialize(*args)
Expand All @@ -13,8 +17,16 @@ def initialize(*args)
end

def send_data(data)
encoding = ""

if should_compress?(data)
data = Zlib.gzip(data)
encoding = GZIP_ENCODING
end

conn.post @endpoint do |req|
req.headers['Content-Type'] = CONTENT_TYPE
req.headers['Content-Encoding'] = encoding
req.headers['X-Sentry-Auth'] = generate_auth_header
req.body = data
end
Expand All @@ -31,6 +43,10 @@ def send_data(data)

private

def should_compress?(data)
@transport_configuration.encoding == GZIP_ENCODING && data.bytesize >= GZIP_THRESHOLD
end

def set_conn
server = @dsn.server

Expand Down
88 changes: 70 additions & 18 deletions sentry-ruby/spec/sentry/transport/http_transport_spec.rb
Original file line number Diff line number Diff line change
@@ -1,40 +1,92 @@
require 'spec_helper'

RSpec.describe Sentry::HTTPTransport do
let(:client) { Sentry::Client.new(Sentry.configuration) }
let(:event) { client.event_from_message("test") }
subject { described_class.new(Sentry.configuration) }

describe "customizations" do
before do
Sentry.init do |c|
c.dsn = 'http://12345@sentry.localdomain/sentry/42'
end
let(:configuration) do
Sentry::Configuration.new.tap do |config|
config.dsn = 'http://12345@sentry.localdomain/sentry/42'
end
end
let(:client) { Sentry::Client.new(configuration) }
let(:event) { client.event_from_message("foobarbaz") }
let(:data) do
subject.encode(event.to_hash)
end

subject { described_class.new(configuration) }

describe "customizations" do
it 'sets a custom User-Agent' do
expect(subject.conn.headers[:user_agent]).to eq("sentry-ruby/#{Sentry::VERSION}")
end

it 'allows to customise faraday' do
builder = spy('faraday_builder')
expect(Faraday).to receive(:new).and_yield(builder)
Sentry.configuration.transport.faraday_builder = proc { |b| b.request :instrumentation }
configuration.transport.faraday_builder = proc { |b| b.request :instrumentation }

subject

expect(builder).to have_received(:request).with(:instrumentation)
end
end

describe "request payload" do
let(:compressed_stubs) do
Faraday::Adapter::Test::Stubs.new do |stub|
stub.post('sentry/api/42/envelope/') do |env|
expect(env.request_headers["Content-Type"]).to eq("application/x-sentry-envelope")
expect(env.request_headers["Content-Encoding"]).to eq("gzip")

envelope = Zlib.gunzip(env.body)
expect(envelope).to include(event.event_id)
expect(envelope).to include("foobarbaz")
end
end
end

let(:uncompressed_stubs) do
Faraday::Adapter::Test::Stubs.new do |stub|
stub.post('sentry/api/42/envelope/') do |env|
expect(env.request_headers["Content-Type"]).to eq("application/x-sentry-envelope")
expect(env.request_headers["Content-Encoding"]).to eq("")

envelope = env.body
expect(envelope).to include(event.event_id)
expect(envelope).to include("foobarbaz")
end
end
end

it "compresses data by default" do
configuration.transport.http_adapter = [:test, compressed_stubs]

subject.send_data(data)
compressed_stubs.verify_stubbed_calls
end

it "doesn't compress small event" do
configuration.transport.http_adapter = [:test, uncompressed_stubs]

event.instance_variable_set(:@threads, nil) # shrink event

subject.send_data(data)
uncompressed_stubs.verify_stubbed_calls
end

it "doesn't compress data if the encoding is not gzip" do
configuration.transport.http_adapter = [:test, uncompressed_stubs]
configuration.transport.encoding = "json"

subject.send_data(data)
uncompressed_stubs.verify_stubbed_calls
end
end

describe "failed request handling" do
before do
Sentry.init do |c|
c.dsn = 'http://12345@sentry.localdomain/sentry/42'
c.transport.http_adapter = [:test, stubs]
c.transport.transport_class = described_class
end
configuration.transport.http_adapter = [:test, stubs]
end

context "receive 4xx responses" do
let(:stubs) do
Faraday::Adapter::Test::Stubs.new do |stub|
Expand All @@ -43,7 +95,7 @@
end

it 'raises an error' do
expect { subject.send_data(event.to_hash) }.to raise_error(Sentry::Error, /the server responded with status 404/)
expect { subject.send_data(data) }.to raise_error(Sentry::Error, /the server responded with status 404/)

stubs.verify_stubbed_calls
end
Expand All @@ -57,7 +109,7 @@
end

it 'raises an error' do
expect { subject.send_data(event.to_hash) }.to raise_error(Sentry::Error, /the server responded with status 500/)
expect { subject.send_data(data) }.to raise_error(Sentry::Error, /the server responded with status 500/)

stubs.verify_stubbed_calls
end
Expand All @@ -71,7 +123,7 @@
end

it 'raises an error with header' do
expect { subject.send_data(event.to_hash) }.to raise_error(Sentry::Error, /error_in_header/)
expect { subject.send_data(data) }.to raise_error(Sentry::Error, /error_in_header/)

stubs.verify_stubbed_calls
end
Expand Down