module NewRelic::Agent::Instrumentation::ActiveRecordHelper

Constants

ACTIVE_RECORD
ACTIVE_RECORD_DEFAULT_PRODUCT_NAME
MAKARA_SUFFIX
OPERATION_NAMES

These are used primarily to optimize and avoid allocation on well known operations coming in. Anything not matching the list is fine, it just needs to get downcased directly for use.

OTHER
PRODUCT_NAMES
SPACE

Public Instance Methods

bare_adapter_name(adapter_name) click to toggle source

convert vendor (makara, etc.) wrapper names to their bare names ex: postgresql_makara -> postgresql

# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 101
def bare_adapter_name(adapter_name)
  # TODO: OLD RUBIES - RUBY_VERSION < 2.5
  # With Ruby 2.5+ we could use #delete_suffix instead of #chomp for a
  # potential speed boost
  return adapter_name.chomp(MAKARA_SUFFIX) if adapter_name&.end_with?(MAKARA_SUFFIX)

  adapter_name
end
calculate(*args, &blk) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 76
def calculate(*args, &blk)
  ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
    calculate_without_newrelic(*args, &blk)
  end
end
delete_all(*args, &blk) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 53
def delete_all(*args, &blk)
  ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
    delete_all_without_newrelic(*args, &blk)
  end
end
destroy_all(*args, &blk) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 68
def destroy_all(*args, &blk)
  ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
    destroy_all_without_newrelic(*args, &blk)
  end
end
instrument_additional_methods() click to toggle source

Used by both the AR 3.x and 4.x instrumentation

# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 15
def instrument_additional_methods
  instrument_save_methods
  instrument_relation_methods
end
instrument_relation_methods() click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 40
def instrument_relation_methods
  ::ActiveRecord::Relation.class_eval do
    alias_method(:update_all_without_newrelic, :update_all)

    def update_all(*args, &blk)
      ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
        update_all_without_newrelic(*args, &blk)
      end
    end

    alias_method(:delete_all_without_newrelic, :delete_all)

    if RUBY_VERSION < '2.7.0'
      def delete_all(*args, &blk)
        ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
          delete_all_without_newrelic(*args, &blk)
        end
      end
    else
      def delete_all(*args, **kwargs, &blk)
        ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
          delete_all_without_newrelic(*args, **kwargs, &blk)
        end
      end
    end

    alias_method(:destroy_all_without_newrelic, :destroy_all)

    def destroy_all(*args, &blk)
      ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
        destroy_all_without_newrelic(*args, &blk)
      end
    end

    alias_method(:calculate_without_newrelic, :calculate)

    def calculate(*args, &blk)
      ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
        calculate_without_newrelic(*args, &blk)
      end
    end

    if method_defined?(:pluck)
      alias_method(:pluck_without_newrelic, :pluck)

      def pluck(*args, &blk)
        ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
          pluck_without_newrelic(*args, &blk)
        end
      end

    end
  end
end
instrument_save_methods() click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 20
def instrument_save_methods
  ::ActiveRecord::Base.class_eval do
    alias_method(:save_without_newrelic, :save)

    def save(*args, &blk)
      ::NewRelic::Agent.with_database_metric_name(self.class.name, nil, ACTIVE_RECORD) do
        save_without_newrelic(*args, &blk)
      end
    end

    alias_method(:save_without_newrelic!, :save!)

    def save!(*args, &blk)
      ::NewRelic::Agent.with_database_metric_name(self.class.name, nil, ACTIVE_RECORD) do
        save_without_newrelic!(*args, &blk)
      end
    end
  end
end
map_operation(raw_operation) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 158
def map_operation(raw_operation)
  direct_op = OPERATION_NAMES[raw_operation]
  return direct_op if direct_op

  raw_operation.downcase
end
map_product(adapter_name) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 211
def map_product(adapter_name)
  PRODUCT_NAMES.fetch(adapter_name, ACTIVE_RECORD_DEFAULT_PRODUCT_NAME)
end
model_from_splits(splits) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 128
def model_from_splits(splits)
  if splits.length == 2
    splits.first
  end
end
operation_from_splits(splits, sql) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 134
def operation_from_splits(splits, sql)
  if splits.length == 2
    map_operation(splits[1])
  else
    NewRelic::Agent::Database.parse_operation_from_query(sql) || OTHER
  end
end
pluck(*args, &blk) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 85
def pluck(*args, &blk)
  ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
    pluck_without_newrelic(*args, &blk)
  end
end
product_operation_collection_for(name, sql, adapter_name) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 110
def product_operation_collection_for(name, sql, adapter_name)
  product = map_product(bare_adapter_name(adapter_name))
  splits = split_name(name)
  model = model_from_splits(splits)
  operation = operation_from_splits(splits, sql)
  NewRelic::Agent::Datastores::MetricHelper.product_operation_collection_for(product, operation, model, ACTIVE_RECORD)
end
save(*args, &blk) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 24
def save(*args, &blk)
  ::NewRelic::Agent.with_database_metric_name(self.class.name, nil, ACTIVE_RECORD) do
    save_without_newrelic(*args, &blk)
  end
end
save!(*args, &blk) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 32
def save!(*args, &blk)
  ::NewRelic::Agent.with_database_metric_name(self.class.name, nil, ACTIVE_RECORD) do
    save_without_newrelic!(*args, &blk)
  end
end
split_name(name) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 120
def split_name(name)
  if name&.respond_to?(:split)
    name.split(SPACE)
  else
    NewRelic::EMPTY_ARRAY
  end
end
update_all(*args, &blk) click to toggle source
# File lib/new_relic/agent/instrumentation/active_record_helper.rb, line 44
def update_all(*args, &blk)
  ::NewRelic::Agent.with_database_metric_name(self.name, nil, ACTIVE_RECORD) do
    update_all_without_newrelic(*args, &blk)
  end
end