Module: Datadog::Contrib::ActiveRecord::Utils

Defined in:
lib/ddtrace/contrib/active_record/utils.rb

Overview

Common utilities for Rails

Constant Summary collapse

EMPTY_CONFIG =
{}.freeze

Class Method Summary collapse

Class Method Details

.adapter_hostObject



19
20
21
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 19

def self.adapter_host
  connection_config[:host]
end

.adapter_nameObject



11
12
13
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 11

def self.adapter_name
  Datadog::Utils::Database.normalize_vendor(connection_config[:adapter])
end

.adapter_portObject



23
24
25
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 23

def self.adapter_port
  connection_config[:port]
end

.connection_config(connection = nil, connection_id = nil) ⇒ Object

Returns the connection configuration hash from the current connection

Since Rails 6.0, we have direct access to the object, while older versions of Rails only provide us the connection id.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 35

def self.connection_config(connection = nil, connection_id = nil)
  return default_connection_config if connection.nil? && connection_id.nil?

  conn = if !connection.nil?
           # Since Rails 6.0, the connection object
           # is directly available.
           connection
         else
           # For Rails < 6.0, only the `connection_id`
           # is available. We have to find the connection
           # object from it.
           connection_from_id(connection_id)
         end

  if conn && conn.instance_variable_defined?(:@config)
    conn.instance_variable_get(:@config)
  else
    EMPTY_CONFIG
  end
end

.connection_from_id(connection_id) ⇒ Object

JRuby does not enable ObjectSpace._id2ref by default, as it has large performance impact: https://github.com/jruby/jruby/wiki/PerformanceTuning/cf155dd9#dont-enable-objectspace

This fallback code does not support the makara gem, as its connections don't live in the ActiveRecord connection pool.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 61

def self.connection_from_id(connection_id)
  # `connection_id` is the `#object_id` of the
  # connection. We can perform an ObjectSpace
  # lookup to find it.
  #
  # This works not only for ActiveRecord, but for
  # extensions that might have their own connection
  # pool (e.g. https://rubygems.org/gems/makara).
  ObjectSpace._id2ref(connection_id)
rescue => e
  # Because `connection_id` references a live connection
  # present in the current stack, it is very unlikely that
  # `_id2ref` will fail, but we add this safeguard just
  # in case.
  Datadog.logger.debug(
    "connection_id #{connection_id} does not represent a valid object. " \
            "Cause: #{e.message} Source: #{Array(e.backtrace).first}"
  )
end

.database_nameObject



15
16
17
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 15

def self.database_name
  connection_config[:database]
end

.db_config(connection_pool) ⇒ Hash

Returns:

  • (Hash)


114
115
116
117
118
119
120
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 114

def self.db_config(connection_pool)
  if ::Rails::VERSION::MAJOR >= 6 && ::Rails::VERSION::MINOR >= 1
    connection_pool.db_config.configuration_hash
  else
    connection_pool.spec.config
  end
end

.default_connection_configHash

Returns:

  • (Hash)


98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ddtrace/contrib/active_record/utils.rb', line 98

def self.default_connection_config
  return @default_connection_config if instance_variable_defined?(:@default_connection_config)

  current_connection_name = if ::ActiveRecord::Base.respond_to?(:connection_specification_name)
                              ::ActiveRecord::Base.connection_specification_name
                            else
                              ::ActiveRecord::Base
                            end

  connection_pool = ::ActiveRecord::Base.connection_handler.retrieve_connection_pool(current_connection_name)
  connection_pool.nil? ? EMPTY_CONFIG : (@default_connection_config = db_config(connection_pool))
rescue StandardError
  EMPTY_CONFIG
end