Enable Redis tracing in Sentry APM
This change causes `db.redis.command` spans to be recorded by Sentry when APM is enabled. It also makes slight improvements to the Sentry initializer. flag=none closes DE-1055 test plan: - verify that Sentry and Canvas initialize OK, and both errors and APM transactions are recorded OK - verify that controllers which interface with Redis record spans in their APM transactions - verify that Redis commands are not recorded as breadcrumbs (we did not enable this feature) Change-Id: I7955b3ad5d6b59e6fd96c801881671814064d622 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/285255 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Aaron Ogata <aogata@instructure.com> QA-Review: Isaac Moore <isaac.moore@instructure.com> Product-Review: Isaac Moore <isaac.moore@instructure.com>
This commit is contained in:
parent
8530016136
commit
448d316c28
|
@ -27,49 +27,49 @@
|
||||||
Rails.configuration.to_prepare do
|
Rails.configuration.to_prepare do
|
||||||
settings = Rails.env.test? ? {} : SentryExtensions::Settings.settings
|
settings = Rails.env.test? ? {} : SentryExtensions::Settings.settings
|
||||||
|
|
||||||
Sentry.init do |config|
|
unless Sentry.initialized?
|
||||||
config.dsn = settings[:dsn]
|
Sentry.init do |config|
|
||||||
config.environment = Canvas.environment
|
config.dsn = settings[:dsn]
|
||||||
config.release = Canvas.revision
|
config.environment = Canvas.environment
|
||||||
config.sample_rate = SentryExtensions::Settings.get("sentry_backend_errors_sample_rate", "1.0").to_f
|
config.release = Canvas.revision
|
||||||
|
config.sample_rate = SentryExtensions::Settings.get("sentry_backend_errors_sample_rate", "1.0").to_f
|
||||||
|
|
||||||
config.traces_sampler = lambda do |sampling_context|
|
config.traces_sampler = lambda do |sampling_context|
|
||||||
unless sampling_context[:parent_sampled].nil?
|
unless sampling_context[:parent_sampled].nil?
|
||||||
# If there is a parent transaction, abide by its sampling decision
|
# If there is a parent transaction, abide by its sampling decision
|
||||||
next sampling_context[:parent_sampled]
|
next sampling_context[:parent_sampled]
|
||||||
|
end
|
||||||
|
|
||||||
|
SentryExtensions::Settings.get("sentry_backend_traces_sample_rate", "0.0").to_f
|
||||||
end
|
end
|
||||||
|
|
||||||
SentryExtensions::Settings.get("sentry_backend_traces_sample_rate", "0.0").to_f
|
# Override the Sentry-provided ActiveRecord subscriber with our own (to normalize SQL queries)
|
||||||
|
config.rails.tracing_subscribers.delete(Sentry::Rails::Tracing::ActiveRecordSubscriber)
|
||||||
|
config.rails.tracing_subscribers.add(SentryExtensions::Tracing::ActiveRecordSubscriber)
|
||||||
|
|
||||||
|
# sentry_logger would be nice here (it records log messages), but it currently includes raw SQL logs
|
||||||
|
config.breadcrumbs_logger = [:http_logger] if Canvas::Plugin.value_to_boolean(SentryExtensions::Settings.get("sentry_backend_breadcrumbs_enabled", "false"))
|
||||||
|
|
||||||
|
filter = ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
|
||||||
|
config.before_send = lambda do |event, _|
|
||||||
|
filter.filter(event.to_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
# this array should only contain exceptions that are intentionally
|
||||||
|
# thrown to drive client facing behavior. A good example
|
||||||
|
# are login/auth exceptions. Exceptions that are simply noisy/inconvenient
|
||||||
|
# should probably be caught and solved...
|
||||||
|
config.excluded_exceptions += %w[
|
||||||
|
AuthenticationMethods::AccessTokenError
|
||||||
|
AuthenticationMethods::AccessTokenScopeError
|
||||||
|
AuthenticationMethods::LoggedOutError
|
||||||
|
ActionController::InvalidAuthenticityToken
|
||||||
|
Folio::InvalidPage
|
||||||
|
Turnitin::Errors::SubmissionNotScoredError
|
||||||
|
Rack::QueryParser::InvalidParameterError
|
||||||
|
PG::UnableToSend
|
||||||
|
]
|
||||||
end
|
end
|
||||||
config.rails.tracing_subscribers = [
|
|
||||||
Sentry::Rails::Tracing::ActionControllerSubscriber,
|
|
||||||
Sentry::Rails::Tracing::ActionViewSubscriber,
|
|
||||||
Sentry::Rails::Tracing::ActiveStorageSubscriber,
|
|
||||||
SentryExtensions::Tracing::ActiveRecordSubscriber # overridden from the Sentry-provided one
|
|
||||||
]
|
|
||||||
|
|
||||||
# sentry_logger would be nice here (it records log messages), but it currently includes raw SQL logs
|
|
||||||
config.breadcrumbs_logger = [:http_logger] if Canvas::Plugin.value_to_boolean(SentryExtensions::Settings.get("sentry_backend_breadcrumbs_enabled", "false"))
|
|
||||||
|
|
||||||
filter = ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
|
|
||||||
config.before_send = lambda do |event, _|
|
|
||||||
filter.filter(event.to_hash)
|
|
||||||
end
|
|
||||||
|
|
||||||
# this array should only contain exceptions that are intentionally
|
|
||||||
# thrown to drive client facing behavior. A good example
|
|
||||||
# are login/auth exceptions. Exceptions that are simply noisy/inconvenient
|
|
||||||
# should probably be caught and solved...
|
|
||||||
config.excluded_exceptions += %w[
|
|
||||||
AuthenticationMethods::AccessTokenError
|
|
||||||
AuthenticationMethods::AccessTokenScopeError
|
|
||||||
AuthenticationMethods::LoggedOutError
|
|
||||||
ActionController::InvalidAuthenticityToken
|
|
||||||
Folio::InvalidPage
|
|
||||||
Turnitin::Errors::SubmissionNotScoredError
|
|
||||||
Rack::QueryParser::InvalidParameterError
|
|
||||||
PG::UnableToSend
|
|
||||||
]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Sentry.set_tags(settings.fetch(:tags, {}))
|
Sentry.set_tags(settings.fetch(:tags, {}))
|
||||||
|
|
|
@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
|
||||||
|
|
||||||
spec.add_dependency "guardrail", ">= 2.0.0"
|
spec.add_dependency "guardrail", ">= 2.0.0"
|
||||||
spec.add_dependency "inst_statsd", ">= 2.1.0"
|
spec.add_dependency "inst_statsd", ">= 2.1.0"
|
||||||
|
spec.add_dependency "sentry-ruby", "~> 5.1.0"
|
||||||
|
|
||||||
spec.add_development_dependency "bundler"
|
spec.add_development_dependency "bundler"
|
||||||
spec.add_development_dependency "byebug"
|
spec.add_development_dependency "byebug"
|
||||||
|
|
|
@ -391,6 +391,12 @@ module CanvasCache
|
||||||
def self.patch
|
def self.patch
|
||||||
Bundler.require "redis"
|
Bundler.require "redis"
|
||||||
require "redis/distributed"
|
require "redis/distributed"
|
||||||
|
require "sentry-ruby"
|
||||||
|
|
||||||
|
::Sentry.register_patch do
|
||||||
|
patch = ::Sentry::Redis::Client
|
||||||
|
::Redis::Client.prepend(patch) unless ::Redis::Client <= patch
|
||||||
|
end
|
||||||
|
|
||||||
::Redis::Client.prepend(::CanvasCache::Redis::Client)
|
::Redis::Client.prepend(::CanvasCache::Redis::Client)
|
||||||
::Redis::Distributed.prepend(::CanvasCache::Redis::Distributed)
|
::Redis::Distributed.prepend(::CanvasCache::Redis::Distributed)
|
||||||
|
|
|
@ -17,21 +17,23 @@
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
module SentryExtensions
|
module SentryExtensions
|
||||||
class Settings
|
module Settings
|
||||||
def self.settings
|
class << self
|
||||||
@sentry_settings ||= ConfigFile.load("sentry")
|
def settings
|
||||||
|
@sentry_settings ||= ConfigFile.load("sentry")
|
||||||
|
|
||||||
@sentry_settings.presence || {}
|
@sentry_settings.presence || {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get(name, default = nil)
|
def get(name, default = nil)
|
||||||
settings[name.to_sym] || Setting.get(name, default)
|
settings[name.to_sym] || Setting.get(name, default)
|
||||||
rescue PG::ConnectionBad
|
rescue PG::ConnectionBad
|
||||||
default
|
default
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.reset_settings
|
def reset_settings
|
||||||
@sentry_settings = nil
|
@sentry_settings = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue