Skip to content

Commit

Permalink
Merge pull request #2189 from newrelic/you_rang❓
Browse files Browse the repository at this point in the history
supportability metrics for gem method invocation
  • Loading branch information
fallwith authored Sep 8, 2023
2 parents 942607b + 180fde6 commit efb6eb1
Show file tree
Hide file tree
Showing 33 changed files with 151 additions and 7 deletions.
11 changes: 11 additions & 0 deletions lib/new_relic/agent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,17 @@ def record_metric_once(metric_name, value = 0.0)
record_metric(metric_name, value)
end

def record_instrumentation_invocation(library)
record_metric_once("Supportability/#{library}/Invoked")
end

# see ActiveSupport::Inflector.demodulize
def base_name(klass_name)
return klass_name unless ridx = klass_name.rindex('::')

klass_name[(ridx + 2), klass_name.length]
end

SUPPORTABILITY_INCREMENT_METRIC = 'Supportability/API/increment_metric'.freeze

# Increment a simple counter metric.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ module NewRelic
module Agent
module Instrumentation
module ActiveSupportLogger
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

# Mark @skip_instrumenting on any broadcasted loggers to instrument Rails.logger only
def broadcast_with_tracing(logger)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

NewRelic::Agent::Instrumentation::Logger.mark_skip_instrumenting(logger)
yield
rescue => error
Expand Down
9 changes: 9 additions & 0 deletions lib/new_relic/agent/instrumentation/bunny/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Bunny
DEFAULT_NAME = 'Default'
DEFAULT_TYPE = :direct
SLASH = '/'
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

def exchange_name(name)
name.empty? ? DEFAULT_NAME : name
Expand All @@ -28,6 +29,8 @@ module Exchange
include Bunny

def publish_with_tracing(payload, opts = {})
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

begin
destination = exchange_name(name)

Expand Down Expand Up @@ -62,6 +65,8 @@ module Queue
include Bunny

def pop_with_tracing
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

bunny_error, delivery_info, message_properties, _payload = nil, nil, nil, nil
begin
t0 = Process.clock_gettime(Process::CLOCK_REALTIME)
Expand Down Expand Up @@ -104,6 +109,8 @@ def pop_with_tracing
end

def purge_with_tracing
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

begin
type = server_named? ? :temporary_queue : :queue
segment = NewRelic::Agent::Tracer.start_message_broker_segment(
Expand All @@ -129,6 +136,8 @@ module Consumer
include Bunny

def call_with_tracing(*args)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

delivery_info, message_properties, _ = args
queue_name = queue.respond_to?(:name) ? queue.name : queue

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
module NewRelic::Agent::Instrumentation
module ConcurrentRuby
SEGMENT_NAME = 'Concurrent/Task'
SUPPORTABILITY_METRIC = 'Supportability/ConcurrentRuby/Invoked'
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

def add_task_tracing(&task)
NewRelic::Agent.record_metric_once(SUPPORTABILITY_METRIC)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

NewRelic::Agent::Tracer.thread_block_with_current_transaction(
segment_name: SEGMENT_NAME,
Expand Down
4 changes: 4 additions & 0 deletions lib/new_relic/agent/instrumentation/curb/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def header_str_with_tracing
module Multi
include NewRelic::Agent::MethodTracer

INSTRUMENTATION_NAME = 'Curb'

# Add CAT with callbacks if the request is serial
def add_with_tracing(curl)
if curl.respond_to?(:_nr_serial) && curl._nr_serial
Expand All @@ -81,6 +83,8 @@ def add_with_tracing(curl)
def perform_with_tracing
return yield if first_request_is_serial?

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

trace_execution_scoped('External/Multiple/Curb::Multi/perform') do
yield
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ module DelayedJobTracer
include NewRelic::Agent::Instrumentation::ControllerInstrumentation

NR_TRANSACTION_CATEGORY = 'OtherTransaction/DelayedJob'.freeze
INSTRUMENTATION_NAME = 'DelayedJob'

def invoke_job_with_tracing
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

options = {
:category => NR_TRANSACTION_CATEGORY,
:path => ::NewRelic::Agent::Instrumentation::DelayedJob::Naming.name_from_payload(payload_object)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ module NewRelic::Agent::Instrumentation
module Elasticsearch
PRODUCT_NAME = 'Elasticsearch'
OPERATION = 'perform_request'
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

def perform_request_with_tracing(method, path, params = {}, body = nil, headers = nil)
return yield unless NewRelic::Agent::Tracer.tracing_enabled?

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

segment = NewRelic::Agent::Tracer.start_datastore_segment(
product: PRODUCT_NAME,
operation: nr_operation || OPERATION,
Expand Down
3 changes: 3 additions & 0 deletions lib/new_relic/agent/instrumentation/excon/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module ::Excon
module Middleware
class NewRelicCrossAppTracing
TRACE_DATA_IVAR = :@newrelic_trace_data
INSTRUMENTATION_NAME = 'Excon'

def initialize(stack)
@stack = stack
Expand All @@ -18,6 +19,8 @@ def request_call(datum) # THREAD_LOCAL_ACCESS
# :idempotent in the options, but there will be only a single
# accompanying response_call/error_call.
if datum[:connection] && !datum[:connection].instance_variable_get(TRACE_DATA_IVAR)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

wrapped_request = ::NewRelic::Agent::HTTPClients::ExconHTTPRequest.new(datum)
segment = NewRelic::Agent::Tracer.start_external_request_segment(
library: wrapped_request.type,
Expand Down
4 changes: 4 additions & 0 deletions lib/new_relic/agent/instrumentation/grape/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ module Grape
module Instrumentation
extend self

INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

# Since 1.2.0, the class `Grape::API` no longer refers to an API instance, rather, what used to be `Grape::API` is `Grape::API::Instance`
# https://github.com/ruby-grape/grape/blob/c20a73ac1e3f3ba1082005ed61bf69452373ba87/UPGRADING.md#upgrading-to--120
def instrumented_class
Expand Down Expand Up @@ -46,6 +48,8 @@ def prepare!
def handle_transaction(endpoint, class_name, version)
return unless endpoint && route = endpoint.route

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

name_transaction(route, class_name, version)
capture_params(endpoint)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ module GRPC
module Client
include NewRelic::Agent::Instrumentation::GRPC::Helper

INSTRUMENTATION_NAME = 'gRPC_Client'

def issue_request_with_tracing(grpc_type, method, requests, marshal, unmarshal,
deadline:, return_op:, parent:, credentials:, metadata:)
return yield unless trace_with_newrelic?

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

segment = request_segment(method)
request_wrapper = NewRelic::Agent::Instrumentation::GRPC::Client::RequestWrapper.new(@host)
# do not insert CAT headers for gRPC requests https://github.com/newrelic/newrelic-ruby-agent/issues/1730
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ module GRPC
module Server
include NewRelic::Agent::Instrumentation::GRPC::Helper

INSTRUMENTATION_NAME = 'gRPC_Server'

DT_KEYS = [NewRelic::NEWRELIC_KEY, NewRelic::TRACEPARENT_KEY, NewRelic::TRACESTATE_KEY].freeze
INSTANCE_VAR_HOST = :@host_nr
INSTANCE_VAR_PORT = :@port_nr
Expand All @@ -23,6 +25,8 @@ module Server
def handle_with_tracing(streamer_type, active_call, mth, _inter_ctx)
return yield unless trace_with_newrelic?

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

metadata = metadata_for_call(active_call)
txn = NewRelic::Agent::Transaction.start_new_transaction(NewRelic::Agent::Tracer.state,
CATEGORY,
Expand Down
2 changes: 1 addition & 1 deletion lib/new_relic/agent/instrumentation/grpc_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
end

executes do
supportability_name = 'gRPC_Client'
supportability_name = NewRelic::Agent::Instrumentation::GRPC::Client::INSTRUMENTATION_NAME
if use_prepend?
prepend_instrument GRPC::ClientStub, NewRelic::Agent::Instrumentation::GRPC::Client::Prepend, supportability_name
else
Expand Down
2 changes: 1 addition & 1 deletion lib/new_relic/agent/instrumentation/grpc_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
end

executes do
supportability_name = 'gRPC_Server'
supportability_name = NewRelic::Agent::Instrumentation::GRPC::Client::INSTRUMENTATION_NAME
if use_prepend?
prepend_instrument GRPC::RpcServer, NewRelic::Agent::Instrumentation::GRPC::Server::RpcServerPrepend, supportability_name
prepend_instrument GRPC::RpcDesc, NewRelic::Agent::Instrumentation::GRPC::Server::RpcDescPrepend, supportability_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
module NewRelic::Agent::Instrumentation
module HTTPClient
module Instrumentation
INSTRUMENTATION_NAME = 'HTTPClient'

def with_tracing(request, connection)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

wrapped_request = NewRelic::Agent::HTTPClients::HTTPClientRequest.new(request)
segment = NewRelic::Agent::Tracer.start_external_request_segment(
library: wrapped_request.type,
Expand Down
4 changes: 4 additions & 0 deletions lib/new_relic/agent/instrumentation/httprb/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

module NewRelic::Agent::Instrumentation
module HTTPrb
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

def with_tracing(request)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

wrapped_request = ::NewRelic::Agent::HTTPClients::HTTPRequest.new(request)

begin
Expand Down
3 changes: 3 additions & 0 deletions lib/new_relic/agent/instrumentation/logger/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module NewRelic
module Agent
module Instrumentation
module Logger
INSTRUMENTATION_NAME = 'Logger'

def skip_instrumenting?
defined?(@skip_instrumenting) && @skip_instrumenting
end
Expand Down Expand Up @@ -51,6 +53,7 @@ def format_message_with_tracing(severity, datetime, progname, msg)
mark_skip_instrumenting

unless ::NewRelic::Agent.agent.nil?
::NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
::NewRelic::Agent.agent.log_event_aggregator.record(formatted_message, severity)
formatted_message = LocalLogDecorator.decorate(formatted_message)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ module Tracer
LOCALHOST = 'localhost'
MULTIGET_METRIC_NAME = 'get_multi_request'
MEMCACHED = 'Memcached'
INSTRUMENTATION_NAME = 'Dalli'

def with_newrelic_tracing(operation, *args)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

segment = NewRelic::Agent::Tracer.start_datastore_segment(
product: MEMCACHED,
operation: operation
Expand All @@ -28,6 +31,8 @@ def with_newrelic_tracing(operation, *args)
end

def server_for_key_with_newrelic_tracing
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

yield.tap do |server|
begin
if txn = ::NewRelic::Agent::Tracer.current_transaction
Expand All @@ -43,6 +48,8 @@ def server_for_key_with_newrelic_tracing
end

def get_multi_with_newrelic_tracing(method_name)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

segment = NewRelic::Agent::Tracer.start_segment(
name: "Ruby/Memcached/Dalli/#{method_name}"
)
Expand All @@ -55,6 +62,8 @@ def get_multi_with_newrelic_tracing(method_name)
end

def send_multiget_with_newrelic_tracing(keys)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

segment = ::NewRelic::Agent::Tracer.start_datastore_segment(
product: MEMCACHED,
operation: MULTIGET_METRIC_NAME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ module NewRelic
module Agent
module Instrumentation
module NetHTTP
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

def request_with_tracing(request)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

wrapped_request = NewRelic::Agent::HTTPClients::NetHTTPRequest.new(self, request)

segment = NewRelic::Agent::Tracer.start_external_request_segment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

module NewRelic::Agent::Instrumentation
module Padrino
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

def invoke_route_with_tracing(*args)
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

begin
env['newrelic.last_route'] = args[0].original_path
rescue => e
Expand Down
6 changes: 6 additions & 0 deletions lib/new_relic/agent/instrumentation/rack/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module NewRelic
module Agent
module Instrumentation
module RackBuilder
INSTRUMENTATION_NAME = 'Rack'

def self.track_deferred_detection(builder_class)
class << builder_class
attr_accessor :_nr_deferred_detection_ran
Expand Down Expand Up @@ -51,13 +53,17 @@ def middleware_instrumentation_enabled?
def run_with_tracing(app)
return yield(app) unless middleware_instrumentation_enabled?

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

yield(::NewRelic::Agent::Instrumentation::MiddlewareProxy.wrap(app, true))
end

def use_with_tracing(middleware_class)
return if middleware_class.nil?
return yield(middleware_class) unless middleware_instrumentation_enabled?

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

yield(::NewRelic::Agent::Instrumentation::MiddlewareProxy.for_class(middleware_class))
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ module Agent
module Instrumentation
module Rails3
module ActionController
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)

# determine the path that is used in the metric name for
# the called controller action
def newrelic_metric_path(action_name_override = nil)
Expand All @@ -21,6 +23,8 @@ def newrelic_metric_path(action_name_override = nil)
end

def process_action(*args) # THREAD_LOCAL_ACCESS
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

munged_params = NewRelic::Agent::ParameterFiltering.filter_rails_request_parameters(request.filtered_parameters)
perform_action_with_newrelic_trace(:category => :controller,
:name => self.action_name,
Expand Down
4 changes: 4 additions & 0 deletions lib/new_relic/agent/instrumentation/rake/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ module Agent
module Instrumentation
module Rake
module Tracer
INSTRUMENTATION_NAME = 'Rake'

def invoke_with_newrelic_tracing(*args)
unless NewRelic::Agent::Instrumentation::Rake.should_trace?(name)
return yield
end

NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

begin
timeout = NewRelic::Agent.config[:'rake.connect_timeout']
NewRelic::Agent.instance.wait_on_connect(timeout)
Expand Down
Loading

0 comments on commit efb6eb1

Please sign in to comment.