summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/api/helpers.rb5
-rw-r--r--lib/gitlab/diff/highlight.rb2
-rw-r--r--lib/gitlab/highlight.rb2
-rw-r--r--lib/gitlab/sentry.rb142
-rw-r--r--lib/gitlab/sentry/logger.rb11
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