156 lines
4.9 KiB
Ruby
156 lines
4.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Sentry configuration for error tracking and performance monitoring
|
|
# Only initializes if SENTRY_DSN is configured
|
|
|
|
return unless ENV['SENTRY_DSN'].present?
|
|
|
|
require 'sentry-rails'
|
|
|
|
Sentry.init do |config|
|
|
config.dsn = ENV['SENTRY_DSN']
|
|
|
|
# Configure sampling for production (lower in production, higher in staging)
|
|
config.traces_sample_rate = case Rails.env
|
|
when 'production' then ENV.fetch('SENTRY_TRACES_SAMPLE_RATE', '0.05').to_f
|
|
when 'staging' then ENV.fetch('SENTRY_TRACES_SAMPLE_RATE', '0.2').to_f
|
|
else ENV.fetch('SENTRY_TRACES_SAMPLE_RATE', '0.1').to_f
|
|
end
|
|
|
|
# Enable breadcrumbs for better debugging
|
|
config.breadcrumbs_logger = [:active_support_logger, :http_logger]
|
|
|
|
# Send PII data (like IPs) to Sentry for debugging (disable in production if needed)
|
|
config.send_default_pii = ENV.fetch('SENTRY_SEND_PII', 'false') == 'true'
|
|
|
|
# Set environment
|
|
config.environment = Rails.env
|
|
|
|
# Configure release info from Docker tag or Git
|
|
if ENV['GIT_COMMIT_SHA']
|
|
config.release = ENV['GIT_COMMIT_SHA'][0..7]
|
|
elsif ENV['APP_VERSION']
|
|
config.release = ENV['APP_VERSION']
|
|
end
|
|
|
|
# Set server name for multi-instance environments
|
|
config.server_name = ENV.fetch('SERVER_NAME', 'baffle-agent')
|
|
|
|
# Filter out certain errors to reduce noise and add tags
|
|
config.before_send = lambda do |event, hint|
|
|
# Filter out 404 errors and other expected HTTP errors
|
|
if event.contexts.dig(:response, :status_code) == 404
|
|
nil
|
|
# Filter out validation errors in development
|
|
elsif Rails.env.development? && event.exception&.message&.include?("Validation failed")
|
|
nil
|
|
# Filter out specific noisy exceptions
|
|
elsif %w[ActionController::RoutingError
|
|
ActionController::InvalidAuthenticityToken
|
|
ActionController::UnknownFormat
|
|
ActionDispatch::Http::Parameters::ParseError].include?(event.exception&.class&.name)
|
|
nil
|
|
else
|
|
# Add tags for better filtering in Sentry
|
|
event.tags.merge!({
|
|
ruby_version: RUBY_VERSION,
|
|
rails_version: Rails.version,
|
|
environment: Rails.env
|
|
})
|
|
event
|
|
end
|
|
end
|
|
|
|
# Configure exception class exclusion
|
|
config.excluded_exceptions += [
|
|
'ActionController::RoutingError',
|
|
'ActionController::InvalidAuthenticityToken',
|
|
'CGI::Session::CookieStore::TamperedWithCookie',
|
|
'ActionController::UnknownFormat',
|
|
'ActionDispatch::Http::Parameters::ParseError',
|
|
'Mongoid::Errors::DocumentNotFound'
|
|
]
|
|
end
|
|
|
|
# SolidQueue monitoring will be automatically handled by sentry-solid_queue gem
|
|
|
|
# Add correlation ID to Sentry context
|
|
ActiveSupport::Notifications.subscribe('action_controller.process_action') do |name, start, finish, id, payload|
|
|
controller = payload[:controller]
|
|
action = payload[:action]
|
|
request_id = payload[:request]&.request_id
|
|
|
|
if controller && action && request_id
|
|
Sentry.set_context(:request, {
|
|
correlation_id: request_id,
|
|
controller: controller.controller_name,
|
|
action: action.action_name,
|
|
ip: request&.remote_ip
|
|
})
|
|
end
|
|
end
|
|
|
|
# Add ActiveJob context to all job transactions
|
|
ActiveSupport::Notifications.subscribe('perform.active_job') do |name, start, finish, id, payload|
|
|
job = payload[:job]
|
|
|
|
Sentry.configure_scope do |scope|
|
|
scope.set_tag(:job_class, job.class.name)
|
|
scope.set_tag(:job_queue, job.queue_name)
|
|
scope.set_tag(:job_id, job.job_id)
|
|
|
|
scope.set_context(:job, {
|
|
job_id: job.job_id,
|
|
job_class: job.class.name,
|
|
queue_name: job.queue_name,
|
|
arguments: job.arguments.to_s,
|
|
enqueued_at: job.enqueued_at,
|
|
executions: job.executions
|
|
})
|
|
end
|
|
end
|
|
|
|
# Monitor SolidQueue job failures
|
|
ActiveSupport::Notifications.subscribe('solid_queue.error') do |name, start, finish, id, payload|
|
|
job = payload[:job]
|
|
error = payload[:error]
|
|
|
|
Sentry.with_scope do |scope|
|
|
scope.set_tag(:job_class, job.class_name)
|
|
scope.set_tag(:job_queue, job.queue_name)
|
|
scope.set_context(:job, {
|
|
job_id: job.active_job_id,
|
|
arguments: job.arguments.to_s,
|
|
queue_name: job.queue_name,
|
|
created_at: job.created_at
|
|
})
|
|
scope.set_context(:error, {
|
|
error_class: error.class.name,
|
|
error_message: error.message
|
|
})
|
|
|
|
Sentry.capture_exception(error)
|
|
end
|
|
end
|
|
|
|
# Set user context when available
|
|
if defined?(Current) && Current.user
|
|
Sentry.set_user(id: Current.user.id, email: Current.user.email)
|
|
end
|
|
|
|
# Add application-specific context
|
|
app_version = begin
|
|
BaffleHub::VERSION
|
|
rescue
|
|
ENV['APP_VERSION'] || ENV['GIT_COMMIT_SHA']&.[](0..7) || 'unknown'
|
|
end
|
|
|
|
Sentry.set_context('application', {
|
|
name: 'BaffleHub',
|
|
version: app_version,
|
|
environment: Rails.env,
|
|
database: ActiveRecord::Base.connection.adapter_name,
|
|
queue_adapter: Rails.application.config.active_job.queue_adapter
|
|
})
|
|
|
|
Rails.logger.info "Sentry configured for environment: #{Rails.env}" |