Method: NewRelic::Agent::Datastores.wrap

Defined in:
lib/new_relic/agent/datastores.rb

.wrap(product, operation, collection = nil, callback = nil) ⇒ Object

Note:

THERE ARE SECURITY CONCERNS WHEN CAPTURING QUERY TEXT! New Relic’s Transaction Tracing and Slow SQL features will attempt to apply obfuscation to the passed queries, but it is possible for a query format to be unsupported and result in exposing user information embedded within captured queries.

Wrap a call to a datastore and record New Relic Datastore metrics. This method can be used when a collection (i.e. table or model name) is known at runtime to be included in the metric naming. It is intended for situations that the simpler NewRelic::Agent::Datastores.trace can’t properly handle.

To use this, wrap the datastore operation in the block passed to wrap.

NewRelic::Agent::Datastores.wrap("FauxDB", "find", "items") do
  FauxDB.find(query)
end

Parameters:

  • product (String)

    the datastore name for use in metric naming, e.g. “FauxDB”

  • operation (String, Symbol)

    the name of operation (e.g. “select”), often named after the method that’s being instrumented.

  • collection (optional, String) (defaults to: nil)

    the collection name for use in statement-level metrics (i.e. table or model name)

  • callback (Proc, #call) (defaults to: nil)

    proc or other callable to invoke after running the datastore block. Receives three arguments: result of the yield, the most specific (scoped) metric name, and elapsed time of the call. An example use is attaching SQL to Transaction Traces at the end of a wrapped datastore call.

    callback = Proc.new do |result, metrics, elapsed|
      NewRelic::Agent::Datastores.notice_sql(query, metrics, elapsed)
    end
    
    NewRelic::Agent::Datastores.wrap("FauxDB", "find", "items", callback) do
      FauxDB.find(query)
    end
    
[View source]

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/new_relic/agent/datastores.rb', line 109

def self.wrap(product, operation, collection = nil, callback = nil)
  NewRelic::Agent.record_api_supportability_metric(:wrap)

  return yield unless operation

  segment = NewRelic::Agent::Tracer.start_datastore_segment(
    product: product,
    operation: operation,
    collection: collection
  )

  begin
    result = yield
  ensure
    begin
      if callback
        elapsed_time = Process.clock_gettime(Process::CLOCK_REALTIME) - segment.start_time
        callback.call(result, segment.name, elapsed_time)
      end
    ensure
      ::NewRelic::Agent::Transaction::Segment.finish(segment)
    end
  end
end