Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/error_tracking/processor/grpc_error_processor.rb')
-rw-r--r--lib/gitlab/error_tracking/processor/grpc_error_processor.rb166
1 files changed, 116 insertions, 50 deletions
diff --git a/lib/gitlab/error_tracking/processor/grpc_error_processor.rb b/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
index 871e9c4b7c8..419098dbd09 100644
--- a/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
+++ b/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
@@ -6,60 +6,126 @@ module Gitlab
class GrpcErrorProcessor < ::Raven::Processor
DEBUG_ERROR_STRING_REGEX = RE2('(.*) debug_error_string:(.*)')
- def process(value)
- process_first_exception_value(value)
- process_custom_fingerprint(value)
+ def process(payload)
+ return payload if ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
- value
- end
-
- # Sentry can report multiple exceptions in an event. Sanitize
- # only the first one since that's what is used for grouping.
- def process_first_exception_value(value)
- exceptions = value.dig(:exception, :values)
-
- return unless exceptions.is_a?(Array)
-
- entry = exceptions.first
-
- return unless entry.is_a?(Hash)
-
- exception_type = entry[:type]
- raw_message = entry[:value]
-
- return unless exception_type&.start_with?('GRPC::')
- return unless raw_message.present?
-
- message, debug_str = split_debug_error_string(raw_message)
-
- entry[:value] = message if message
- extra = value[:extra] || {}
- extra[:grpc_debug_error_string] = debug_str if debug_str
- end
-
- def process_custom_fingerprint(value)
- fingerprint = value[:fingerprint]
-
- return value unless custom_grpc_fingerprint?(fingerprint)
+ self.class.process_first_exception_value(payload)
+ self.class.process_custom_fingerprint(payload)
- message, _ = split_debug_error_string(fingerprint[1])
- fingerprint[1] = message if message
+ payload
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]]
+ class << self
+ def call(event)
+ return event unless ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
+
+ process_first_exception_value(event)
+ process_custom_fingerprint(event)
+
+ event
+ end
+
+ # Sentry can report multiple exceptions in an event. Sanitize
+ # only the first one since that's what is used for grouping.
+ def process_first_exception_value(event_or_payload)
+ exceptions = exceptions(event_or_payload)
+
+ return unless exceptions.is_a?(Array)
+
+ exception = exceptions.first
+
+ return unless valid_exception?(exception)
+
+ exception_type, raw_message = type_and_value(exception)
+
+ return unless exception_type&.start_with?('GRPC::')
+ return unless raw_message.present?
+
+ message, debug_str = split_debug_error_string(raw_message)
+
+ set_new_values!(event_or_payload, exception, message, debug_str)
+ end
+
+ def process_custom_fingerprint(event)
+ fingerprint = fingerprint(event)
+
+ return event 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
+
+ # The below methods can be removed once we remove the
+ # sentry_processors_before_send feature flag, and we can
+ # assume we always have an Event object
+ def exceptions(event_or_payload)
+ case event_or_payload
+ when Raven::Event
+ # Better in new version, will be event_or_payload.exception.values
+ event_or_payload.instance_variable_get(:@interfaces)[:exception]&.values
+ when Hash
+ event_or_payload.dig(:exception, :values)
+ end
+ end
+
+ def valid_exception?(exception)
+ case exception
+ when Raven::SingleExceptionInterface
+ exception&.value
+ when Hash
+ true
+ else
+ false
+ end
+ end
+
+ def type_and_value(exception)
+ case exception
+ when Raven::SingleExceptionInterface
+ [exception.type, exception.value]
+ when Hash
+ exception.values_at(:type, :value)
+ end
+ end
+
+ def set_new_values!(event_or_payload, exception, message, debug_str)
+ case event_or_payload
+ when Raven::Event
+ # Worse in new version, no setter! Have to poke at the
+ # instance variable
+ exception.value = message if message
+ event_or_payload.extra[:grpc_debug_error_string] = debug_str if debug_str
+ when Hash
+ exception[:value] = message if message
+ extra = event_or_payload[:extra] || {}
+ extra[:grpc_debug_error_string] = debug_str if debug_str
+ end
+ end
+
+ def fingerprint(event_or_payload)
+ case event_or_payload
+ when Raven::Event
+ event_or_payload.fingerprint
+ when Hash
+ event_or_payload[:fingerprint]
+ end
+ end
end
end
end