Module: Bigcommerce::Lightstep::ActiveRecord::Adapter

Extended by:
ActiveSupport::Concern
Defined in:
lib/bigcommerce/lightstep/active_record/adapter.rb

Overview

Patches mysql and ActiveRecord to allow for mysql span tracing

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.enabled?Boolean

Note: we only support patching mysql2 gem at this point.

Returns:

  • (Boolean)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/bigcommerce/lightstep/active_record/adapter.rb', line 43

def self.enabled?
  return false unless defined?(::ActiveRecord) && ::Bigcommerce::Lightstep.active_record

  adapter_name = if ::ActiveRecord::Base.respond_to?(:connection_config) # rails 6
                   ::ActiveRecord::Base.connection_config[:adapter].to_s
                 elsif ::ActiveRecord::Base.respond_to?(:connection_db_config) # rails 7
                   ::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter].to_s
                 else
                   'unknown'
                 end
  adapter_name.casecmp('mysql2')&.zero? == true
rescue StandardError => e
  ::Bigcommerce::Lightstep.logger&.warn "Failed to determine ActiveRecord database adapter in bc-lightstep-ruby initializer: #{e.message}"
  false
end

.patchObject

Patch ActiveRecord to enable mysql span traces



30
31
32
33
34
35
36
# File 'lib/bigcommerce/lightstep/active_record/adapter.rb', line 30

def self.patch
  return unless enabled?

  # rubocop:disable Lint/SendWithMixinArgument
  ::ActiveRecord::ConnectionAdapters::Mysql2Adapter.send(:include, ::Bigcommerce::Lightstep::ActiveRecord::Adapter)
  # rubocop:enable Lint/SendWithMixinArgument
end

Instance Method Details

#execute_with_inst(sql, name = 'SQL', async: false) ⇒ Object

Parameters:

  • sql (String)

    The raw sql query

  • name (String) (defaults to: 'SQL')

    The type of sql query



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/bigcommerce/lightstep/active_record/adapter.rb', line 63

def execute_with_inst(sql, name = 'SQL', async: false)
  # bail out early if not enabled. This should not get here, but is provided as a failsafe.
  return execute_without_inst(sql, name, async: async) unless ::Bigcommerce::Lightstep.active_record

  sanitized_sql = lightstep_sanitize_sql(sql)
  name = 'QUERY' if name.to_s.strip.empty?

  # we dont need to track all sql
  return execute_without_inst(sql, name) if lightstep_skip_tracing?(name, sanitized_sql)

  lightstep_tracer.db_trace(
    statement: sanitized_sql,
    host: @config[:host],
    adapter: @config[:adapter],
    database: @config[:database]
  ) do
    execute_without_inst(sql, name)
  end
end

#lightstep_sanitization_regexpRegexp

Returns:

  • (Regexp)


96
97
98
# File 'lib/bigcommerce/lightstep/active_record/adapter.rb', line 96

def lightstep_sanitization_regexp
  @lightstep_sanitization_regexp ||= ::Regexp.new('(\'[\s\S][^\']*\'|\d*\.\d+|\d+|NULL)', ::Regexp::IGNORECASE)
end

#lightstep_sanitize_sql(sql) ⇒ String

Sanitize the sql for safe logging

Parameters:

  • (String)

Returns:

  • (String)


89
90
91
# File 'lib/bigcommerce/lightstep/active_record/adapter.rb', line 89

def lightstep_sanitize_sql(sql)
  sql.to_s.gsub(lightstep_sanitization_regexp, '?').tr("\n", ' ').to_s
end

#lightstep_skip_tracing?(name, sql) ⇒ Boolean

Filter out sql queries from tracing we don’t care about

Parameters:

  • name (String)
  • sql (String)

Returns:

  • (Boolean)


106
107
108
# File 'lib/bigcommerce/lightstep/active_record/adapter.rb', line 106

def lightstep_skip_tracing?(name, sql)
  name.empty? || sql.empty? || sql.include?('COMMIT') || sql.include?('SCHEMA') || sql.include?('SHOW FULL FIELDS')
end

#lightstep_tracer::Bigcommerce::Lightstep::ActiveRecord::Tracer



113
114
115
# File 'lib/bigcommerce/lightstep/active_record/adapter.rb', line 113

def lightstep_tracer
  @lightstep_tracer ||= ::Bigcommerce::Lightstep::ActiveRecord::Tracer.new
end