Commit 9ef0cf74 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'mb-ruby-sentry-upgrade' into 'master'

Update Sentry gem to version 5.1.1

See merge request gitlab-org/gitlab!72428
parents c92576df 891ddd79
......@@ -302,6 +302,9 @@ gem 'rack-attack', '~> 6.3.0'
# Sentry integration
gem 'sentry-raven', '~> 3.1'
gem 'sentry-ruby', '~> 5.1.1'
gem 'sentry-rails', '~> 5.1.1'
gem 'sentry-sidekiq', '~> 5.1.1'
# PostgreSQL query parsing
#
......
......@@ -1174,8 +1174,19 @@ GEM
selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
sentry-rails (5.1.1)
railties (>= 5.0)
sentry-ruby-core (~> 5.1.1)
sentry-raven (3.1.2)
faraday (>= 1.0)
sentry-ruby (5.1.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
sentry-ruby-core (= 5.1.1)
sentry-ruby-core (5.1.1)
concurrent-ruby
sentry-sidekiq (5.1.1)
sentry-ruby-core (~> 5.1.1)
sidekiq (>= 3.0)
set (1.0.1)
settingslogic (2.0.9)
sexp_processor (4.15.1)
......@@ -1627,7 +1638,10 @@ DEPENDENCIES
sd_notify (~> 0.1.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.142)
sentry-rails (~> 5.1.1)
sentry-raven (~> 3.1)
sentry-ruby (~> 5.1.1)
sentry-sidekiq (~> 5.1.1)
settingslogic (~> 2.0.9)
shoulda-matchers (~> 4.0.1)
sidekiq (~> 6.4)
......
---
name: enable_new_sentry_integration
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72428
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344832
milestone: '14.9'
type: development
group: group::pipeline execution
default_enabled: false
---
name: enable_old_sentry_integration
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72428
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344832
milestone: '14.9'
type: development
group: group::pipeline execution
default_enabled: true
......@@ -23,7 +23,12 @@ module Gitlab
].freeze
class << self
def configure
def configure(&block)
configure_raven(&block)
configure_sentry(&block)
end
def configure_raven
Raven.configure do |config|
config.dsn = sentry_dsn
config.release = Gitlab.revision
......@@ -34,7 +39,20 @@ module Gitlab
# Sanitize authentication headers
config.sanitize_http_headers = %w[Authorization Private-Token]
config.before_send = method(:before_send)
config.before_send = method(:before_send_raven)
yield config if block_given?
end
end
def configure_sentry
Sentry.init do |config|
config.dsn = new_sentry_dsn
config.release = Gitlab.revision
config.environment = new_sentry_environment
config.before_send = method(:before_send_sentry)
config.background_worker_threads = 0
config.send_default_pii = true
yield config if block_given?
end
......@@ -96,6 +114,18 @@ module Gitlab
private
def before_send_raven(event, hint)
return unless Feature.enabled?(:enable_old_sentry_integration, default_enabled: :yaml)
before_send(event, hint)
end
def before_send_sentry(event, hint)
return unless Feature.enabled?(:enable_new_sentry_integration, default_enabled: :yaml)
before_send(event, hint)
end
def before_send(event, hint)
inject_context_for_exception(event, hint[:exception])
custom_fingerprinting(event, hint[:exception])
......@@ -112,6 +142,13 @@ module Gitlab
Raven.capture_exception(exception, **context_payload)
end
# There is a possibility that this method is called before Sentry is
# configured. Since Sentry 4.0, some methods of Sentry are forwarded to
# to `nil`, hence we have to check the client as well.
if sentry && ::Sentry.get_current_client && ::Sentry.configuration.dsn
::Sentry.capture_exception(exception, **context_payload)
end
if logging
formatter = Gitlab::ErrorTracking::LogFormatter.new
log_hash = formatter.generate_log(exception, context_payload)
......@@ -121,12 +158,30 @@ module Gitlab
end
def sentry_dsn
return unless Rails.env.production? || Rails.env.development?
return unless sentry_configurable?
return unless Gitlab.config.sentry.enabled
Gitlab.config.sentry.dsn
end
def new_sentry_dsn
return unless sentry_configurable?
return unless Gitlab::CurrentSettings.respond_to?(:sentry_enabled?)
return unless Gitlab::CurrentSettings.sentry_enabled?
Gitlab::CurrentSettings.sentry_dsn
end
def new_sentry_environment
return unless Gitlab::CurrentSettings.respond_to?(:sentry_environment)
Gitlab::CurrentSettings.sentry_environment
end
def sentry_configurable?
Rails.env.production? || Rails.env.development?
end
def should_raise_for_dev?
Rails.env.development? || Rails.env.test?
end
......
......@@ -18,7 +18,7 @@ module Gitlab
# only the first one since that's what is used for grouping.
def process_first_exception_value(event)
# Better in new version, will be event.exception.values
exceptions = event.instance_variable_get(:@interfaces)[:exception]&.values
exceptions = extract_exceptions_from(event)
return unless exceptions.is_a?(Array)
......@@ -37,7 +37,13 @@ module Gitlab
# instance variable
if message.present?
exceptions.each do |exception|
exception.value = message if valid_exception?(exception)
next unless valid_exception?(exception)
if exception.respond_to?(:value=)
exception.value = message
else
exception.instance_variable_set(:@value, message)
end
end
end
......@@ -55,6 +61,14 @@ module Gitlab
private
def extract_exceptions_from(event)
if event.is_a?(Raven::Event)
event.instance_variable_get(:@interfaces)[:exception]&.values
else
event.exception&.instance_variable_get(:@values)
end
end
def custom_grpc_fingerprint?(fingerprint)
fingerprint.is_a?(Array) && fingerprint.length == 2 && fingerprint[0].start_with?('GRPC::')
end
......@@ -71,7 +85,7 @@ module Gitlab
def valid_exception?(exception)
case exception
when Raven::SingleExceptionInterface
when Raven::SingleExceptionInterface, Sentry::SingleExceptionInterface
exception&.value
else
false
......
......@@ -2,9 +2,9 @@
require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor, :sentry do
describe '.call' do
let(:required_options) do
let(:raven_required_options) do
{
configuration: Raven.configuration,
context: Raven.context,
......@@ -12,7 +12,15 @@ RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
}
end
let(:event) { Raven::Event.from_exception(exception, required_options.merge(data)) }
let(:raven_event) do
Raven::Event
.from_exception(exception, raven_required_options.merge(data))
end
let(:sentry_event) do
Sentry.get_current_client.event_from_exception(exception)
end
let(:result_hash) { described_class.call(event).to_hash }
let(:data) do
......@@ -27,36 +35,43 @@ RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
}
end
before do
Sentry.get_current_scope.update_from_options(**data)
Sentry.get_current_scope.apply_to_event(sentry_event)
end
after do
Sentry.get_current_scope.clear
end
context 'when there is no GRPC exception' do
let(:exception) { RuntimeError.new }
let(:data) { { fingerprint: ['ArgumentError', 'Missing arguments'] } }
it 'leaves data unchanged' do
expect(result_hash).to include(data)
shared_examples 'leaves data unchanged' do
it { expect(result_hash).to include(data) }
end
end
context 'when there is a GRPC exception with a debug string' do
let(:exception) { GRPC::DeadlineExceeded.new('Deadline Exceeded', {}, '{"hello":1}') }
context 'with Raven event' do
let(:event) { raven_event }
it 'removes the debug error string and stores it as an extra field' do
expect(result_hash[:fingerprint])
.to eq(['GRPC::DeadlineExceeded', '4:Deadline Exceeded.'])
it_behaves_like 'leaves data unchanged'
end
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
context 'with Sentry event' do
let(:event) { sentry_event }
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
it_behaves_like 'leaves data unchanged'
end
end
context 'with no custom fingerprint' do
let(:data) do
{ extra: { caller: 'test' } }
end
context 'when there is a GRPC exception with a debug string' do
let(:exception) { GRPC::DeadlineExceeded.new('Deadline Exceeded', {}, '{"hello":1}') }
shared_examples 'processes the exception' do
it 'removes the debug error string and stores it as an extra field' do
expect(result_hash).not_to include(:fingerprint)
expect(result_hash[:fingerprint])
.to eq(['GRPC::DeadlineExceeded', '4:Deadline Exceeded.'])
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
......@@ -64,11 +79,42 @@ RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
context 'with no custom fingerprint' do
let(:data) do
{ extra: { caller: 'test' } }
end
it 'removes the debug error string and stores it as an extra field' do
expect(result_hash[:fingerprint]).to be_blank
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
end
end
context 'with Raven event' do
let(:event) { raven_event }
it_behaves_like 'processes the exception'
end
context 'with Sentry event' do
let(:event) { sentry_event }
it_behaves_like 'processes the exception'
end
end
context 'when there is a wrapped GRPC exception with a debug string' do
let(:inner_exception) { GRPC::DeadlineExceeded.new('Deadline Exceeded', {}, '{"hello":1}') }
let(:inner_exception) do
GRPC::DeadlineExceeded.new('Deadline Exceeded', {}, '{"hello":1}')
end
let(:exception) do
begin
raise inner_exception
......@@ -79,27 +125,10 @@ RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
e
end
it 'removes the debug error string and stores it as an extra field' do
expect(result_hash[:fingerprint])
.to eq(['GRPC::DeadlineExceeded', '4:Deadline Exceeded.'])
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
expect(result_hash[:exception][:values].second)
.to include(type: 'StandardError', value: '4:Deadline Exceeded.')
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
context 'with no custom fingerprint' do
let(:data) do
{ extra: { caller: 'test' } }
end
shared_examples 'processes the exception' do
it 'removes the debug error string and stores it as an extra field' do
expect(result_hash).not_to include(:fingerprint)
expect(result_hash[:fingerprint])
.to eq(['GRPC::DeadlineExceeded', '4:Deadline Exceeded.'])
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
......@@ -110,6 +139,37 @@ RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
context 'with no custom fingerprint' do
let(:data) do
{ extra: { caller: 'test' } }
end
it 'removes the debug error string and stores it as an extra field' do
expect(result_hash[:fingerprint]).to be_blank
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
expect(result_hash[:exception][:values].second)
.to include(type: 'StandardError', value: '4:Deadline Exceeded.')
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
end
end
context 'with Raven event' do
let(:event) { raven_event }
it_behaves_like 'processes the exception'
end
context 'with Sentry event' do
let(:event) { sentry_event }
it_behaves_like 'processes the exception'
end
end
end
......
......@@ -3,7 +3,7 @@
require 'spec_helper'
require 'rspec-parameterized'
RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor, :sentry do
after do
if described_class.instance_variable_defined?(:@permitted_arguments_for_worker)
described_class.remove_instance_variable(:@permitted_arguments_for_worker)
......@@ -95,7 +95,9 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
end
describe '.call' do
let(:required_options) do
let(:exception) { StandardError.new('Test exception') }
let(:raven_required_options) do
{
configuration: Raven.configuration,
context: Raven.context,
......@@ -103,9 +105,25 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
}
end
let(:event) { Raven::Event.new(required_options.merge(wrapped_value)) }
let(:raven_event) do
Raven::Event.new(raven_required_options.merge(wrapped_value))
end
let(:sentry_event) do
Sentry.get_current_client.event_from_exception(exception)
end
let(:result_hash) { described_class.call(event).to_hash }
before do
Sentry.get_current_scope.update_from_options(**wrapped_value)
Sentry.get_current_scope.apply_to_event(sentry_event)
end
after do
Sentry.get_current_scope.clear
end
context 'when there is Sidekiq data' do
let(:wrapped_value) { { extra: { sidekiq: value } } }
......@@ -140,42 +158,90 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
end
context 'when processing via the default error handler' do
include_examples 'Sidekiq arguments', args_in_job_hash: true
context 'with Raven events' do
let(:event) { raven_event}
include_examples 'Sidekiq arguments', args_in_job_hash: true
end
context 'with Sentry events' do
let(:event) { sentry_event}
include_examples 'Sidekiq arguments', args_in_job_hash: true
end
end
context 'when processing via Gitlab::ErrorTracking' do
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
context 'with Raven events' do
let(:event) { raven_event}
context 'when a jobstr field is present' do
let(:value) do
{
job: { 'args' => [1] },
jobstr: { 'args' => [1] }.to_json
}
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
it 'removes the jobstr' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value.except(:jobstr))
context 'with Sentry events' do
let(:event) { sentry_event}
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
end
context 'when no jobstr value is present' do
let(:value) { { job: { 'args' => [1] } } }
shared_examples 'handles jobstr fields' do
context 'when a jobstr field is present' do
let(:value) do
{
job: { 'args' => [1] },
jobstr: { 'args' => [1] }.to_json
}
end
it 'removes the jobstr' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value.except(:jobstr))
end
end
context 'when no jobstr value is present' do
let(:value) { { job: { 'args' => [1] } } }
it 'does nothing' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value)
it 'does nothing' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value)
end
end
end
context 'with Raven events' do
let(:event) { raven_event}
it_behaves_like 'handles jobstr fields'
end
context 'with Sentry events' do
let(:event) { sentry_event}
it_behaves_like 'handles jobstr fields'
end
end
context 'when there is no Sidekiq data' do
let(:value) { { tags: { foo: 'bar', baz: 'quux' } } }
let(:wrapped_value) { value }
it 'does nothing' do
expect(result_hash).to include(value)
expect(result_hash.dig(:extra, :sidekiq)).to be_nil
shared_examples 'does nothing' do
it 'does nothing' do
expect(result_hash).to include(value)
expect(result_hash.dig(:extra, :sidekiq)).to be_nil
end
end
context 'with Raven events' do
let(:event) { raven_event}
it_behaves_like 'does nothing'
end
context 'with Sentry events' do
let(:event) { sentry_event}
it_behaves_like 'does nothing'
end
end
......@@ -183,8 +249,22 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
let(:value) { { other: 'foo' } }
let(:wrapped_value) { { extra: { sidekiq: value } } }
it 'does nothing' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value)
shared_examples 'does nothing' do
it 'does nothing' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value)
end
end
context 'with Raven events' do
let(:event) { raven_event}
it_behaves_like 'does nothing'
end
context 'with Sentry events' do
let(:event) { sentry_event}
it_behaves_like 'does nothing'
end
end
end
......
......@@ -3,13 +3,14 @@
require 'spec_helper'
require 'raven/transports/dummy'
require 'sentry/transport/dummy_transport'
RSpec.describe Gitlab::ErrorTracking do
let(:exception) { RuntimeError.new('boom') }
let(:issue_url) { 'http://gitlab.com/gitlab-org/gitlab-foss/issues/1' }
let(:extra) { { issue_url: issue_url, some_other_info: 'info' } }
let(:user) { create(:user) }
let_it_be(:user) { create(:user) }
let(:sentry_payload) do
{
......@@ -43,17 +44,28 @@ RSpec.describe Gitlab::ErrorTracking do
}
end
let(:sentry_event) { Gitlab::Json.parse(Raven.client.transport.events.last[1]) }
let(:raven_event) do
event = Raven.client.transport.events.last[1]
Gitlab::Json.parse(event)
end
let(:sentry_event) do
Sentry.get_current_client.transport.events.last
end
before do
stub_feature_flags(enable_old_sentry_integration: true)
stub_feature_flags(enable_new_sentry_integration: true)
stub_sentry_settings
allow(described_class).to receive(:sentry_dsn).and_return(Gitlab.config.sentry.dsn)
allow(described_class).to receive(:sentry_configurable?) { true }
allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('cid')
allow(I18n).to receive(:locale).and_return('en')
described_class.configure do |config|
config.encoding = 'json'
config.encoding = 'json' if config.respond_to?(:encoding=)
config.transport.transport_class = Sentry::DummyTransport if config.respond_to?(:transport)
end
end
......@@ -63,6 +75,10 @@ RSpec.describe Gitlab::ErrorTracking do
end
end
after do
Sentry.get_current_scope.clear
end
describe '.track_and_raise_for_dev_exception' do
context 'when exceptions for dev should be raised' do
before do
......@@ -71,6 +87,7 @@ RSpec.describe Gitlab::ErrorTracking do
it 'raises the exception' do
expect(Raven).to receive(:capture_exception).with(exception, sentry_payload)
expect(Sentry).to receive(:capture_exception).with(exception, sentry_payload)
expect do
described_class.track_and_raise_for_dev_exception(
......@@ -89,6 +106,7 @@ RSpec.describe Gitlab::ErrorTracking do
it 'logs the exception with all attributes passed' do
expect(Raven).to receive(:capture_exception).with(exception, sentry_payload)
expect(Sentry).to receive(:capture_exception).with(exception, sentry_payload)
described_class.track_and_raise_for_dev_exception(
exception,
......@@ -112,6 +130,7 @@ RSpec.describe Gitlab::ErrorTracking do
describe '.track_and_raise_exception' do
it 'always raises the exception' do
expect(Raven).to receive(:capture_exception).with(exception, sentry_payload)
expect(Sentry).to receive(:capture_exception).with(exception, sentry_payload)
expect do
described_class.track_and_raise_for_dev_exception(
......@@ -136,20 +155,24 @@ RSpec.describe Gitlab::ErrorTracking do
end
describe '.track_exception' do
subject(:track_exception) { described_class.track_exception(exception, extra) }
subject(:track_exception) do
described_class.track_exception(exception, extra)
end
before do
allow(Raven).to receive(:capture_exception).and_call_original
allow(Sentry).to receive(:capture_exception).and_call_original
allow(Gitlab::ErrorTracking::Logger).to receive(:error)
end
it 'calls Raven.capture_exception' do
track_exception
expect(Raven).to have_received(:capture_exception).with(
exception,
sentry_payload
)
expect(Raven)
.to have_received(:capture_exception).with(exception, sentry_payload)
expect(Sentry)
.to have_received(:capture_exception).with(exception, sentry_payload)
end
it 'calls Gitlab::ErrorTracking::Logger.error with formatted payload' do
......@@ -172,7 +195,10 @@ RSpec.describe Gitlab::ErrorTracking do
context 'the exception implements :sentry_extra_data' do
let(:extra_info) { { event: 'explosion', size: :massive } }
let(:exception) { double(message: 'bang!', sentry_extra_data: extra_info, backtrace: caller, cause: nil) }
before do
allow(exception).to receive(:sentry_extra_data).and_return(extra_info)
end
it 'includes the extra data from the exception in the tracking information' do
track_exception
......@@ -180,29 +206,30 @@ RSpec.describe Gitlab::ErrorTracking do
expect(Raven).to have_received(:capture_exception).with(
exception, a_hash_including(extra: a_hash_including(extra_info))
)
expect(Sentry).to have_received(:capture_exception).with(
exception, a_hash_including(extra: a_hash_including(extra_info))
)
end
end
context 'the exception implements :sentry_extra_data, which returns nil' do
let(:exception) { double(message: 'bang!', sentry_extra_data: nil, backtrace: caller, cause: nil) }
let(:extra) { { issue_url: issue_url } }
before do
allow(exception).to receive(:sentry_extra_data).and_return(nil)
end
it 'just includes the other extra info' do
track_exception
expect(Raven).to have_received(:capture_exception).with(
exception, a_hash_including(extra: a_hash_including(extra))
)
end
end
context 'when the error is kind of an `ActiveRecord::StatementInvalid`' do
let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') }
it 'injects the normalized sql query into extra' do
track_exception
expect(sentry_event.dig('extra', 'sql')).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
expect(Sentry).to have_received(:capture_exception).with(
exception, a_hash_including(extra: a_hash_including(extra))
)
end
end
end
......@@ -212,32 +239,65 @@ RSpec.describe Gitlab::ErrorTracking do
before do
allow(Raven).to receive(:capture_exception).and_call_original
allow(Sentry).to receive(:capture_exception).and_call_original
allow(Gitlab::ErrorTracking::Logger).to receive(:error)
end
context 'custom GitLab context when using Raven.capture_exception directly' do
subject(:raven_capture_exception) { Raven.capture_exception(exception) }
subject(:track_exception) { Raven.capture_exception(exception) }
it 'merges a default set of tags into the existing tags' do
allow(Raven.context).to receive(:tags).and_return(foo: 'bar')
raven_capture_exception
track_exception
expect(sentry_event['tags']).to include('correlation_id', 'feature_category', 'foo', 'locale', 'program')
expect(raven_event['tags']).to include('correlation_id', 'feature_category', 'foo', 'locale', 'program')
end
it 'merges the current user information into the existing user information' do
Raven.user_context(id: -1)
raven_capture_exception
track_exception
expect(sentry_event['user']).to eq('id' => -1, 'username' => user.username)
expect(raven_event['user']).to eq('id' => -1, 'username' => user.username)
end
end
context 'custom GitLab context when using Sentry.capture_exception directly' do
subject(:track_exception) { Sentry.capture_exception(exception) }
it 'merges a default set of tags into the existing tags' do
Sentry.set_tags(foo: 'bar')
track_exception
expect(sentry_event.tags).to include(:correlation_id, :feature_category, :foo, :locale, :program)
end
it 'merges the current user information into the existing user information' do
Sentry.set_user(id: -1)
track_exception
expect(sentry_event.user).to eq(id: -1, username: user.username)
end
end
context 'with sidekiq args' do
context 'when the args does not have anything sensitive' do
let(:extra) { { sidekiq: { 'class' => 'PostReceive', 'args' => [1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value'] } } }
let(:extra) do
{
sidekiq: {
'class' => 'PostReceive',
'args' => [
1,
{ 'id' => 2, 'name' => 'hello' },
'some-value',
'another-value'
]
}
}
end
it 'ensures extra.sidekiq.args is a string' do
track_exception
......@@ -254,8 +314,10 @@ RSpec.describe Gitlab::ErrorTracking do
it 'does not filter parameters when sending to Sentry' do
track_exception
expected_data = [1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value']
expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq([1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value'])
expect(raven_event.dig('extra', 'sidekiq', 'args')).to eq(expected_data)
expect(sentry_event.extra[:sidekiq]['args']).to eq(expected_data)
end
end
......@@ -265,7 +327,8 @@ RSpec.describe Gitlab::ErrorTracking do
it 'filters sensitive arguments before sending and logging' do
track_exception
expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq(['[FILTERED]', 1, 2])
expect(raven_event.dig('extra', 'sidekiq', 'args')).to eq(['[FILTERED]', 1, 2])
expect(sentry_event.extra[:sidekiq]['args']).to eq(['[FILTERED]', 1, 2])
expect(Gitlab::ErrorTracking::Logger).to have_received(:error).with(
hash_including(
'extra.sidekiq' => {
......@@ -285,8 +348,10 @@ RSpec.describe Gitlab::ErrorTracking do
it 'sets the GRPC debug error string in the Sentry event and adds a custom fingerprint' do
track_exception
expect(sentry_event.dig('extra', 'grpc_debug_error_string')).to eq('{"hello":1}')
expect(sentry_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause.'])
expect(raven_event.dig('extra', 'grpc_debug_error_string')).to eq('{"hello":1}')
expect(raven_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause.'])
expect(sentry_event.extra[:grpc_debug_error_string]).to eq('{"hello":1}')
expect(sentry_event.fingerprint).to eq(['GRPC::DeadlineExceeded', '4:unknown cause.'])
end
end
......@@ -296,8 +361,10 @@ RSpec.describe Gitlab::ErrorTracking do
it 'does not do any processing on the event' do
track_exception
expect(sentry_event['extra']).not_to include('grpc_debug_error_string')
expect(sentry_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause'])
expect(raven_event['extra']).not_to include('grpc_debug_error_string')
expect(raven_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause'])
expect(sentry_event.extra).not_to include(:grpc_debug_error_string)
expect(sentry_event.fingerprint).to eq(['GRPC::DeadlineExceeded', '4:unknown cause'])
end
end
end
......
......@@ -90,10 +90,18 @@ module StubConfiguration
allow(Gitlab.config.repositories).to receive(:storages).and_return(Settingslogic.new(messages))
end
def stub_sentry_settings
allow(Gitlab.config.sentry).to receive(:enabled).and_return(true)
allow(Gitlab.config.sentry).to receive(:dsn).and_return('dummy://b44a0828b72421a6d8e99efd68d44fa8@example.com/42')
allow(Gitlab.config.sentry).to receive(:clientside_dsn).and_return('dummy://b44a0828b72421a6d8e99efd68d44fa8@example.com/43')
def stub_sentry_settings(enabled: true)
allow(Gitlab.config.sentry).to receive(:enabled) { enabled }
allow(Gitlab::CurrentSettings).to receive(:sentry_enabled?) { enabled }
dsn = 'dummy://b44a0828b72421a6d8e99efd68d44fa8@example.com/42'
allow(Gitlab.config.sentry).to receive(:dsn) { dsn }
allow(Gitlab::CurrentSettings).to receive(:sentry_dsn) { dsn }
clientside_dsn = 'dummy://b44a0828b72421a6d8e99efd68d44fa8@example.com/43'
allow(Gitlab.config.sentry).to receive(:clientside_dsn) { clientside_dsn }
allow(Gitlab::CurrentSettings)
.to receive(:sentry_clientside_dsn) { clientside_dsn }
end
def stub_kerberos_setting(messages)
......
# frozen_string_literal: true
RSpec.configure do |config|
config.around(:example, :sentry) do |example|
dsn = Sentry.get_current_client.configuration.dsn
Sentry.get_current_client.configuration.dsn = 'dummy://b44a0828b72421a6d8e99efd68d44fa8@example.com/42'
begin
example.run
ensure
Sentry.get_current_client.configuration.dsn = dsn.to_s.presence
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment