Commit 69f02d9c authored by Stan Hu's avatar Stan Hu

Clean up gRPC debug_error_string messages in Sentry

The upgrade of gRPC brought along a `debug_error_string` that makes it
harder for Sentry to group similar exceptions together. There doesn't
appear to be a way to turn this off, so we clean this up in a Sentry
field processsor. Now exceptions will have a field
`grpc_debug_error_string` field in the `extra` section.

Relates to https://gitlab.com/gitlab-org/gitlab/-/issues/238465
parent 1e0ff62a
...@@ -26,6 +26,8 @@ module Gitlab ...@@ -26,6 +26,8 @@ module Gitlab
# Sanitize fields based on those sanitized from Rails. # Sanitize fields based on those sanitized from Rails.
config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s) config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s)
config.processors << ::Gitlab::ErrorTracking::Processor::SidekiqProcessor config.processors << ::Gitlab::ErrorTracking::Processor::SidekiqProcessor
config.processors << ::Gitlab::ErrorTracking::Processor::GrpcErrorProcessor
# Sanitize authentication headers # Sanitize authentication headers
config.sanitize_http_headers = %w[Authorization Private-Token] config.sanitize_http_headers = %w[Authorization Private-Token]
config.tags = extra_tags_from_env.merge(program: Gitlab.process_name) config.tags = extra_tags_from_env.merge(program: Gitlab.process_name)
......
# frozen_string_literal: true
module Gitlab
module ErrorTracking
module Processor
class GrpcErrorProcessor < ::Raven::Processor
DEBUG_ERROR_STRING_REGEX = RE2('(.*) debug_error_string:(.*)')
def process(value)
return value unless grpc_exception?(value)
process_message(value)
process_exception_values(value)
process_custom_fingerprint(value)
value
end
def grpc_exception?(value)
value[:exception] && value[:message].start_with?('GRPC::')
end
def process_message(value)
message, debug_str = split_debug_error_string(value[:message])
return unless message
value[:message] = message
extra = value[:extra] || {}
extra[:grpc_debug_error_string] = debug_str if debug_str
end
def process_exception_values(value)
exceptions = value.dig(:exception, :values)
return unless exceptions.is_a?(Array)
exceptions.each do |entry|
message, _ = split_debug_error_string(entry[:value])
entry[:value] = message if message
end
end
def process_custom_fingerprint(value)
fingerprint = value[:fingerprint]
return value unless custom_grpc_fingerprint?(fingerprint)
message, _ = split_debug_error_string(fingerprint[1])
fingerprint[1] = message if message
end
private
def custom_grpc_fingerprint?(fingerprint)
fingerprint.is_a?(Array) && fingerprint.length == 2 && fingerprint[0].start_with?('GRPC::')
end
def split_debug_error_string(message)
return unless message
match = DEBUG_ERROR_STRING_REGEX.match(message)
return unless match
[match[1], match[2]]
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
describe '#process' do
subject { described_class.new }
context 'when there is no GRPC exception' do
let(:data) { { fingerprint: ['ArgumentError', 'Missing arguments'] } }
it 'leaves data unchanged' do
expect(subject.process(data)).to eq(data)
end
end
context 'when there is a GPRC exception with a debug string' do
let(:data) do
{
exception: {
values: [
{
value: "GRPC::DeadlineExceeded: 4:DeadlineExceeded. debug_error_string:{\"hello\":1}"
}
]
},
extra: {
caller: 'test'
},
message: "GRPC::DeadlineExceeded: 4:DeadlineExceeded. debug_error_string:{\"hello\":1}",
fingerprint: [
"GRPC::DeadlineExceeded",
"4:Deadline Exceeded. debug_error_string:{\"created\":\"@1598938192.005782000\",\"description\":\"Error received from peer unix:/home/git/gitalypraefect.socket\",\"file\":\"src/core/lib/surface/call.cc\",\"file_line\":1055,\"grpc_message\":\"Deadline Exceeded\",\"grpc_status\":4}"
]
}
end
let(:expected) do
{
message: "GRPC::DeadlineExceeded: 4:DeadlineExceeded.",
fingerprint: [
"GRPC::DeadlineExceeded",
"4:Deadline Exceeded."
],
exception: {
values: [
{
value: "GRPC::DeadlineExceeded: 4:DeadlineExceeded."
}
]
},
extra: {
caller: 'test',
grpc_debug_error_string: "{\"hello\":1}"
}
}
end
it 'removes the debug error string and stores it as an extra field' do
expect(subject.process(data)).to eq(expected)
end
context 'with no custom fingerprint' do
before do
data.delete(:fingerprint)
expected.delete(:fingerprint)
end
it 'removes the debug error string and stores it as an extra field' do
expect(subject.process(data)).to eq(expected)
end
end
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