Class: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber

Inherits:
Sentry::Rails::LogSubscriber show all
Includes:
ParameterFilter
Defined in:
lib/sentry/rails/log_subscribers/active_record_subscriber.rb

Overview

LogSubscriber for ActiveRecord events that captures database queries and logs them using Sentry’s structured logging system.

This subscriber captures sql.active_record events and formats them with relevant database information including SQL queries, duration, database configuration, and caching information.

Examples:

Usage

# Automatically attached when structured logging is enabled for :active_record
Sentry.init do |config|
  config.enable_logs = true
  config.rails.structured_logging = true
  config.rails.structured_logging.subscribers = { active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber }
end

Constant Summary collapse

EXCLUDED_NAMES =
["SCHEMA", "TRANSACTION"].freeze

Constants included from ParameterFilter

ParameterFilter::EMPTY_HASH

Constants inherited from Sentry::Rails::LogSubscriber

Sentry::Rails::LogSubscriber::ORIGIN

Instance Method Summary collapse

Methods included from ParameterFilter

backend, #filter_sensitive_params

Methods inherited from Sentry::Rails::LogSubscriber

#detach_from

Instance Method Details

#sql(event) ⇒ Object

Handle sql.active_record events

Parameters:

  • event (ActiveSupport::Notifications::Event)

    The SQL event



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/sentry/rails/log_subscribers/active_record_subscriber.rb', line 31

def sql(event)
  return unless Sentry.initialized?
  return if logger && !logger.info?
  return if EXCLUDED_NAMES.include?(event.payload[:name])

  sql = event.payload[:sql]
  statement_name = event.payload[:name]

  # Rails 5.0.0 doesn't include :cached in the payload, it was added in Rails 5.1
  cached = event.payload.fetch(:cached, false)
  connection_id = event.payload[:connection_id]

  db_config = extract_db_config(event.payload)

  attributes = {
    sql: sql,
    duration_ms: duration_ms(event),
    cached: cached
  }

  binds = event.payload[:binds]

  if Sentry.configuration.send_default_pii && (binds && !binds.empty?)
    type_casted_binds = type_casted_binds(event)

    binds.each_with_index do |bind, index|
      key = bind.respond_to?(:name) ? bind.name : index.to_s
      value = type_casted_binds[index].to_s

      attributes["db.query.parameter.#{key}"] = value
    end
  end

  attributes[:statement_name] = statement_name if statement_name && statement_name != "SQL"
  attributes[:connection_id] = connection_id if connection_id

  add_db_config_attributes(attributes, db_config)

  message = build_log_message(statement_name)

  log_structured_event(
    message: message,
    level: :info,
    attributes: attributes
  )
end

#type_casted_binds(event) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sentry/rails/log_subscribers/active_record_subscriber.rb', line 78

def type_casted_binds(event)
  binds = event.payload[:type_casted_binds]

  # When a query is cached, binds are a callable,
  # and under JRuby they're always a callable.
  if binds.respond_to?(:call)
    binds.call
  else
    binds
  end
end