diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/api/helpers.rb | 5 | ||||
-rw-r--r-- | lib/gitlab/diff/highlight.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/highlight.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/sentry.rb | 142 | ||||
-rw-r--r-- | lib/gitlab/sentry/logger.rb | 11 |
5 files changed, 110 insertions, 52 deletions
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 6c1a730935a..f0f8d2b3ce1 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -372,8 +372,9 @@ module API def handle_api_exception(exception) if report_exception?(exception) define_params_for_grape_middleware - Gitlab::Sentry.context(current_user) - Gitlab::Sentry.track_acceptable_exception(exception, extra: params) + Gitlab::Sentry.in_context(current_user) do + Gitlab::Sentry.report_exception(exception, extra: params) + end end # lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L60 diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index d2484217ab9..21360d28d82 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -35,7 +35,7 @@ module Gitlab # match the blob, which is a bug. But we shouldn't fail to render # completely in that case, even though we want to report the error. rescue RangeError => e - Gitlab::Sentry.track_exception(e, issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/45441') + Gitlab::Sentry.handle_exception(e, issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/45441') end end diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb index a4e60bbd828..a4c2fe2b3f2 100644 --- a/lib/gitlab/highlight.rb +++ b/lib/gitlab/highlight.rb @@ -61,7 +61,7 @@ module Gitlab tokens = lexer.lex(text, continue: continue) Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag).html_safe } rescue Timeout::Error => e - Gitlab::Sentry.track_exception(e) + Gitlab::Sentry.handle_exception(e) highlight_plain(text) rescue highlight_plain(text) diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb index 46d01964eac..8fbfe219ae1 100644 --- a/lib/gitlab/sentry.rb +++ b/lib/gitlab/sentry.rb @@ -1,67 +1,113 @@ # frozen_string_literal: true module Gitlab - module Sentry - def self.enabled? - (Rails.env.production? || Rails.env.development?) && - Gitlab::CurrentSettings.sentry_enabled? - end + class Sentry + class << self + attr_reader :sentry_enabled, :program + attr_accessor :user_context + + def configure!(sentry_dsn:, program:) + @sentry_enabled = sentry_dsn.present? + @program = program + + Raven.configure do |config| + config.dsn = dsn + config.release = Gitlab.revision + + # Sanitize fields based on those sanitized from Rails. + config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s) + # Sanitize authentication headers + config.sanitize_http_headers = %w[Authorization Private-Token] + config.tags = { program: program } + end if sentry_enabled + end - def self.context(current_user = nil) - return unless enabled? + def in_context(current_user = nil) + last_context = self.user_context - Raven.tags_context(locale: I18n.locale) + begin + self.user_context = { + id: current_user.id, + email: current_user.email, + username: current_user.username + } if current_user - if current_user - Raven.user_context( - id: current_user.id, - email: current_user.email, - username: current_user.username - ) + yield + ensure + self.user_context = last_context + end end - end - # This can be used for investigating exceptions that can be recovered from in - # code. The exception will still be raised in development and test - # environments. - # - # That way we can track down these exceptions with as much information as we - # need to resolve them. - # - # Provide an issue URL for follow up. - def self.track_exception(exception, issue_url: nil, extra: {}) - track_acceptable_exception(exception, issue_url: issue_url, extra: extra) - - raise exception if should_raise_for_dev? - end + # This can be used for investigating exceptions that can be recovered from in + # code. The exception will still be raised in development and test + # environments. + # + # That way we can track down these exceptions with as much information as we + # need to resolve them. + # + # Provide an issue URL for follow up. + def handle_exception(exception, issue_url: nil, extra: {}) + report_exception(exception, issue_url: issue_url, extra: extra) - # This should be used when you do not want to raise an exception in - # development and test. If you need development and test to behave - # just the same as production you can use this instead of - # track_exception. - def self.track_acceptable_exception(exception, issue_url: nil, extra: {}) - if enabled? + raise exception if should_raise_for_dev? + end + + # This should be used when you do not want to raise an exception in + # development and test. If you need development and test to behave + # just the same as production you can use this instead of + # handle_exception. + def report_exception(exception, issue_url: nil, extra: {}) extra[:issue_url] = issue_url if issue_url - context # Make sure we've set everything we know in the context - tags = { - Gitlab::CorrelationId::LOG_KEY.to_sym => Gitlab::CorrelationId.current_id - } + if sentry_enabled + tags = { + Gitlab::CorrelationId::LOG_KEY.to_sym => Gitlab::CorrelationId.current_id + } - Raven.capture_exception(exception, tags: tags, extra: extra) + Raven.capture_exception(exception, tags: tags, extra: extra) + else + # otherwise, send it to log file + details = extra.merge(user_context.to_h).merge( + exception_details(exception)) + + logger.error(details) + end end - end - def self.program_context - if Sidekiq.server? - 'sidekiq' - else - 'rails' + private + + def user_context= (value) + @user_context = value + + if sentry_enabled + Raven.tags_context(locale: I18n.locale) + Raven.user_context(*value) + end + end + + def should_raise_for_dev? + Rails.env.development? || Rails.env.test? + end + + def logger + Gitlab::Sentry::Logger.build end - end - def self.should_raise_for_dev? - Rails.env.development? || Rails.env.test? + def exception_details(exception) + { class: exception.class.to_s, + message: exception.message, + backtrace: filter_backtrace(exception.backtrace) + } + end + + # filter backtrace to only include GitLab directories + def filter_backtrace(backtrace, limit: 5) + root_path = Rails.root.to_s + '/' + + backtrace.select do |line| + line.start_with?(root_path) + end.first(limit) + end end end end diff --git a/lib/gitlab/sentry/logger.rb b/lib/gitlab/sentry/logger.rb new file mode 100644 index 00000000000..74dce0fa341 --- /dev/null +++ b/lib/gitlab/sentry/logger.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Gitlab + class Sentry + class Logger < ::Gitlab::JsonLogger + def self.file_name_noext + 'exceptions_json' + end + end + end +end |