Skip to content

Commit

Permalink
merge contributed instrumentation and patches
Browse files Browse the repository at this point in the history
  • Loading branch information
jaggederest committed May 12, 2011
2 parents b1da5e5 + a584013 commit 5a2aec6
Show file tree
Hide file tree
Showing 13 changed files with 324 additions and 20 deletions.
11 changes: 11 additions & 0 deletions lib/rpm_contrib/instrumentation/active_mq.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# == ActiveMQ Instrumentation ==
# Robert R. Meyer
# Blue-Dog-Archolite @ GitHub

if defined?(ActiveMessaging::Processor) and not NewRelic::Control.instance['disable_active_mq']
ActiveMessaging::Processor.class_eval do
class << self
add_method_tracer :on_message, 'ActiveMessaging/OnMessage'
end
end
end
19 changes: 19 additions & 0 deletions lib/rpm_contrib/instrumentation/crack.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
if defined?(::Crack) && !NewRelic::Control.instance['disable_crack']
if defined?(::Crack::JSON)
::Crack::JSON.class_eval do
class << self
include NewRelic::Agent::MethodTracer
add_method_tracer :parse, 'Parser/#{self.name}/parse'
end
end
end

if defined?(::Crack::XML)
::Crack::XML.class_eval do
class << self
include NewRelic::Agent::MethodTracer
add_method_tracer :parse, 'Parser/#{self.name}/parse'
end
end
end
end
39 changes: 39 additions & 0 deletions lib/rpm_contrib/instrumentation/curb.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
if defined?(::Curl) and not NewRelic::Control.instance['disable_curb']
Curl::Easy.class_eval do
def host
URI.parse(self.url).host
end

# TODO: http, http_delete, http_get, http_post, http_head, http_put
def perform_with_newrelic_trace(*args, &block)
metrics = ["External/#{host}/Curl::Easy","External/#{host}/all"]
if NewRelic::Agent::Instrumentation::MetricFrame.recording_web_transaction?
metrics << "External/allWeb"
else
metrics << "External/allOther"
end
self.class.trace_execution_scoped metrics do
perform_without_newrelic_trace(*args, &block)
end
end
alias perform_without_newrelic_trace perform
alias perform perform_with_newrelic_trace
end

Curl::Multi.class_eval do
# TODO: http
def perform_with_newrelic_trace(*args, &block)
metrics = ["External/Curl::Multi"]
if NewRelic::Agent::Instrumentation::MetricFrame.recording_web_transaction?
metrics << "External/allWeb"
else
metrics << "External/allOther"
end
self.class.trace_execution_scoped metrics do
perform_without_newrelic_trace(*args, &block)
end
end
alias perform_without_newrelic_trace perform
alias perform perform_with_newrelic_trace
end
end
16 changes: 16 additions & 0 deletions lib/rpm_contrib/instrumentation/elastic_search.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# == Elastic Search Instrumentation
#

if defined?(::ElasticSearch) and not NewRelic::Control.instance['disable_elastic_search_instrumentation']

::ElasticSearch::Client.class_eval do
add_method_tracer :index, 'ActiveRecord/ElasticSearch/index'
add_method_tracer :get, 'ActiveRecord/ElasticSearch/get'
add_method_tracer :delete, 'ActiveRecord/ElasticSearch/delete'
add_method_tracer :search, 'ActiveRecord/ElasticSearch/search'
add_method_tracer :scroll, 'ActiveRecord/ElasticSearch/scroll'
add_method_tracer :count, 'ActiveRecord/ElasticSearch/count'
add_method_tracer :bulk, 'ActiveRecord/ElasticSearch/bulk'
end

end
65 changes: 49 additions & 16 deletions lib/rpm_contrib/instrumentation/resque.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,61 @@

module RPMContrib
SUPPORTS_FORK =
begin
# jruby has a Kernel.fork method, but it raises NotImplementedError by default
if Kernel.respond_to?(:fork)
Kernel.fork { exit! }
true
else
false
end
rescue NotImplementedError
false
end

module Instrumentation
# == Resque Instrumentation
#
# Installs a hook to ensure the agent starts manually when the worker
# starts and also adds the tracer to the process method which executes
# in the forked task.
module ResqueInstrumentation
Resque.before_first_fork do
NewRelic::Agent.manual_start(:dispatcher => :resque)
def self.flush_metric_data
return if !NewRelic::Agent.agent.started? || NewRelic::Agent.agent.instance_variable_get(:@worker_loop).nil?
NewRelic::Agent.agent.instance_variable_get(:@worker_loop).run_task
end

Resque.after_fork do
NewRelic::Agent.after_fork(:force_reconnect => false)
end
end
end
end if defined?(::Resque) and not NewRelic::Control.instance['disable_resque']
::Resque::Job.class_eval do
include NewRelic::Agent::Instrumentation::ControllerInstrumentation

old_perform_method = instance_method(:perform)

define_method(:perform) do
class_name = (payload_class ||self.class).name
NewRelic::Agent.reset_stats if NewRelic::Agent.respond_to? :reset_stats
perform_action_with_newrelic_trace(:name => 'perform', :class_name => class_name,
:category => 'OtherTransaction/ResqueJob') do
old_perform_method.bind(self).call
end

if ::RPMContrib::SUPPORTS_FORK
NewRelic::Agent.shutdown unless defined?(::Resque.before_child_exit)
else
::RPMContrib::Instrumentation::ResqueInstrumentation.flush_metric_data unless defined?(::Resque.before_child_exit)
end

module Resque
module Plugins
module NewRelicInstrumentation
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
end
end

def around_perform_with_monitoring(*args)
perform_action_with_newrelic_trace(:name => 'perform', :class_name => class_name, :category => 'OtherTransaction/ResqueJob') do
yield(*args)
if defined?(::Resque.before_child_exit)
::Resque.before_child_exit do |worker|
if ::RPMContrib::SUPPORTS_FORK
NewRelic::Agent.shutdown
else
::RPMContrib::Instrumentation::ResqueInstrumentation.flush_metric_data
end
end
end
end
end
end
end if defined?(::Resque::Job) and not NewRelic::Control.instance['disable_resque']
20 changes: 20 additions & 0 deletions lib/rpm_contrib/instrumentation/sinatra.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
if defined?(Sinatra::Base) and not NewRelic::Control.instance['disable_sinatra_template']
module Sinatra
Base.class_eval do
def render_with_newrelic_trace(*args, &block)
engine, file = *args
return render_without_newrelic_trace(*args, &block) if file == "= yield"

file = "Proc" if file.is_a?(Proc)
metrics = ["Sinatra/#{engine}/#{file}"]

self.class.trace_execution_scoped metrics do
render_without_newrelic_trace(*args, &block)
end
end

alias render_without_newrelic_trace render
alias render render_with_newrelic_trace
end
end
end
21 changes: 21 additions & 0 deletions lib/rpm_contrib/instrumentation/typhoeus.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
if defined? Typhoeus
require 'uri'
module Typhoeus
Request.instance_eval do
def get_with_newrelic_trace(*args, &block)
uri = URI.parse(args.first)
metrics = ["External/#{uri.host}/Typhoeus/GET","External/#{uri.host}/all"]
if NewRelic::Agent::Instrumentation::MetricFrame.recording_web_transaction?
metrics << "External/allWeb"
else
metrics << "External/allOther"
end
self.class.trace_execution_scoped metrics do
get_without_newrelic_trace(*args, &block)
end
end
alias get_without_newrelic_trace get
alias get get_with_newrelic_trace
end
end
end
10 changes: 10 additions & 0 deletions lib/rpm_contrib/instrumentation/ultrasphinx.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'new_relic/agent/method_tracer.rb'

module Ultrasphinx
class Search
include NewRelic::Agent::MethodTracer

add_method_tracer :run
add_method_tracer :results
end
end
15 changes: 15 additions & 0 deletions lib/rpm_contrib/instrumentation/workling.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Workling instrumentation contributed by Chad Ingram of Aurora Feint
#

if defined?(::Workling) and not NewRelic::Control.instance['disable_workling']
Workling::Base.class_eval do
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
end

Workling::Discovery.discovered.each do |clazz|
(clazz.public_instance_methods - Workling::Base.public_instance_methods).each do |method|
puts "added method tracer Workling/#{clazz.name}/#{method}"
clazz.send(:add_method_tracer, method, "Workling/#{clazz.name}/#{method}", :category => :task)
end
end
end
8 changes: 8 additions & 0 deletions lib/rpm_contrib/instrumentation/yajl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
if defined?(::Yajl::Encoder) and not NewRelic::Control.instance['disable_yajl_instrumentation']
::Yajl::Encoder.class_eval do
class << self
include NewRelic::Agent::MethodTracer
add_method_tracer :parse, 'Encoder/Yajl/encode'
end
end
end
20 changes: 16 additions & 4 deletions rpm_contrib.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,28 @@ the New Relic Ruby monitoring gem newrelic_rpm.
"lib/rpm_contrib/detection/camping.rb",
"lib/rpm_contrib/detection/resque.rb",
"lib/rpm_contrib/instrumentation.rb",
"lib/rpm_contrib/instrumentation/active_mq.rb",
"lib/rpm_contrib/instrumentation/aws.rb",
"lib/rpm_contrib/instrumentation/aws/s3.rb",
"lib/rpm_contrib/instrumentation/camping.rb",
"lib/rpm_contrib/instrumentation/cassandra.rb",
"lib/rpm_contrib/instrumentation/crack.rb",
"lib/rpm_contrib/instrumentation/curb.rb",
"lib/rpm_contrib/instrumentation/elastic_search.rb",
"lib/rpm_contrib/instrumentation/mongo.rb",
"lib/rpm_contrib/instrumentation/paperclip.rb",
"lib/rpm_contrib/instrumentation/redis.rb",
"lib/rpm_contrib/instrumentation/resque.rb",
"lib/rpm_contrib/instrumentation/sinatra.rb",
"lib/rpm_contrib/instrumentation/typhoeus.rb",
"lib/rpm_contrib/instrumentation/ultrasphinx.rb",
"lib/rpm_contrib/instrumentation/workling.rb",
"lib/rpm_contrib/instrumentation/yajl.rb",
"test/helper.rb",
"test/schema.rb",
"test/test_mongoid.rb",
"test/test_redis.rb"
"test/test_curb.rb",
"test/test_redis.rb",
"test/test_workling.rb"
]
s.homepage = %q{http://github.com/newrelic/rpm_contrib}
s.rdoc_options = ["--charset=UTF-8", "--line-numbers", "--inline-source", "--title", "Contributed Instrumentation for New Relic RPM", "-m", "README.md"]
Expand All @@ -50,8 +61,9 @@ the New Relic Ruby monitoring gem newrelic_rpm.
s.test_files = [
"test/helper.rb",
"test/schema.rb",
"test/test_mongoid.rb",
"test/test_redis.rb"
"test/test_curb.rb",
"test/test_redis.rb",
"test/test_workling.rb"
]

if s.respond_to? :specification_version then
Expand Down
66 changes: 66 additions & 0 deletions test/test_curb.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require "#{File.dirname(__FILE__)}/helper"
require 'curb'

class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
def setup
NewRelic::Agent.manual_start
@engine = NewRelic::Agent.instance.stats_engine
@engine.clear_stats
end
def test_get
curl = Curl::Easy.new('http://www.google.com/index.html')
curl.perform
assert_match /<head>/, curl.body_str
assert_equal %w[External/www.google.com/Curl::Easy External/Curl::Multi
External/allOther External/www.google.com/all].sort,
@engine.metrics.sort
end

def test_multi
multi = Curl::Multi.new
curl1 = Curl::Easy.new('http://www.google.com/index.html')
multi.add curl1
curl2 = Curl::Easy.new('http://www.yahoo.com/')
multi.add curl2
multi.perform
assert_match /<head>/, curl1.body_str
assert_match /<head>/, curl2.body_str
assert_equal %w[External/Curl::Multi External/allOther].sort,
@engine.metrics.sort
end

def test_background
perform_action_with_newrelic_trace("task", :category => :task) do
curl = Curl::Easy.new('http://www.google.com/index.html')
curl.perform
assert_match /<head>/, curl.body_str
end
assert_equal %w[External/Curl::Multi
External/Curl::Multi:OtherTransaction/Background/NewRelic::Agent::NetInstrumentationTest/task
External/www.google.com/Curl::Easy External/allOther External/www.google.com/all
External/www.google.com/Curl::Easy:OtherTransaction/Background/NewRelic::Agent::NetInstrumentationTest/task].sort,
@engine.metrics.select{|m| m =~ /^External/}.sort
end

def test_transactional
perform_action_with_newrelic_trace("task") do
curl = Curl::Easy.new('http://www.google.com/index.html')
curl.perform
assert_match /<head>/, curl.body_str
end
assert_equal %w[External/Curl::Multi
External/Curl::Multi:Controller/NewRelic::Agent::NetInstrumentationTest/task
External/www.google.com/Curl::Easy External/allWeb External/www.google.com/all
External/www.google.com/Curl::Easy:Controller/NewRelic::Agent::NetInstrumentationTest/task].sort,
@engine.metrics.select{|m| m =~ /^External/}.sort
end
def test_ignore
NewRelic::Agent.disable_all_tracing do
curl = Curl::Easy.new('http://www.google.com/index.html')
curl.http_post('data')
end
assert_equal 0, @engine.metrics.size
end

end
34 changes: 34 additions & 0 deletions test/test_workling.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require "#{File.dirname(__FILE__)}/helper"
begin
require 'redis'
require 'ruby-debug'
rescue LoadError
end

require "#{File.dirname(__FILE__)}/../lib/rpm_contrib/instrumentation/workling"

if defined?(::Workling)


class WorklingTest < Test::Unit::TestCase

# Called before every test method runs. Can be used
# to set up fixture information.
def setup
# Do nothing
end

# Called after every test method runs. Can be used to tear
# down fixture information.

def teardown
# Do nothing
end

# Fake test
def test_fail


end
end
end

0 comments on commit 5a2aec6

Please sign in to comment.