Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

First pass at new instrumentation

  • Loading branch information...
commit 873b2a3879326ee059d8f66ecddcc67198e41215 1 parent 725bea7
@bkayser bkayser authored
View
7 CHANGELOG
@@ -1,2 +1,7 @@
* Version 1.0.0
- - Initial Release
+
+ Initial Release:
+ - Camping
+ - Authlogic
+ - DelayedJob
+ - Paperclip
View
34 README.md
@@ -0,0 +1,34 @@
+# The RPM Contrib Gem
+
+The `rpm_contrib` gem contains instrumentation for the New Relic RPM agent
+contributed by the community of RPM users. It requires the RPM Agent
+to run.
+
+We encourage contributions to this project and will provide whatever
+assistance we can to those wishing to develop instrumentation for
+other open source Ruby libraries.
+
+## Note on Patches/Pull Requests
+
+* Fork the http://www.github.com/newrelic/rpm_contrib project.
+* Add instrumentation files to `lib/rpm_contrib/instrumentation`. These
+ files will be loaded when the RPM agent is initialized.
+* Add samplers to `lib/rpm_contrib/samplers`. These classes are
+ installed automatically when the RPM agent is initialized.
+* Add tests.
+* Commit, do not mess with the Rakefile, version, or history. (if you
+ want to have your own version, that is fine but bump version in a
+ commit by itself I can ignore when I pull)
+* Send me a pull request. Bonus points for topic branches.
+
+## Further Information
+
+See http://newrlic.github.com/rpm for API documentation on the Agent.
+
+See http://support.newrelic.com/faqs for additional tips and documentation.
+
+Contact support@newrelic.com for help.
+
+== Copyright
+
+Copyright (c) 2010 New Relic. See LICENSE for details.
View
17 README.rdoc
@@ -1,17 +0,0 @@
-= rpm_contrib
-
-Description goes here.
-
-== Note on Patches/Pull Requests
-
-* Fork the project.
-* Make your feature addition or bug fix.
-* Add tests for it. This is important so I don't break it in a
- future version unintentionally.
-* Commit, do not mess with rakefile, version, or history.
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
-* Send me a pull request. Bonus points for topic branches.
-
-== Copyright
-
-Copyright (c) 2010 New Relic. See LICENSE for details.
View
15 lib/rpm_contrib.rb
@@ -1,4 +1,17 @@
+# Hook instrumentation and samplers in this gem into the normal RPM
+# start up sequence.
require 'newrelic_rpm'
module RPMContrib
- VERSION = File.read(File.dirname(__FILE__)+"/../CHANGELOG")[/Version ([\d\.]+)$/, 1]
+
+ lib_root = File.dirname(__FILE__)
+
+ # Tell the agent to load all the files in the rpm_contrib/instrumentation directory.
+
+ NewRelic::Agent.add_instrumentation(lib_root+"/rpm_contrib/instrumentation/**/*.rb")
+
+ # Load all the Sampler class definitions. These will register
+ # automatically with the agent.
+ Dir.glob(lib_root + "/rpm_contrib/samplers/**/*.rb") { |file| require file }
+
+ VERSION = File.read(lib_root+"/../CHANGELOG")[/Version ([\d\.]+)$/, 1]
end
View
0  lib/new_relic/agent/instrumentation/authlogic.rb → lib/rpm_contrib/instrumentation/authlogic.rb
File renamed without changes
View
74 lib/rpm_contrib/instrumentation/camping.rb
@@ -0,0 +1,74 @@
+require 'new_relic/agent/instrumentation/controller_instrumentation'
+
+module RPMContrib
+ module Instrumentation
+ # == Instrumentation for Camping
+ # To instrument all controllers do the following:
+ # 1. Add the necessary NewRelic-specific requires in your require section
+ # 2. Add an include at the end of your main Camping app module
+ # 3. Add a call to NewRelic::Agent.manual_start at the end of the file to start the agent
+ # 4. Run the following command to get the NewRelic license key to use: heroku config -all
+ # 5. Create a newrelic.yml under the /config folder with the following content:
+ #
+ # common: &default_settings
+ # license_key: 'PASTE THE VALUE OF NEW_RELIC_LICENSE_KEY HERE'
+ # agent_enabled: true
+ # app_name: PASTE THE NAME OF YOUR CAMPING APP HERE
+ # enabled: true
+ #
+ # production:
+ # <<: *default_settings
+ # enabled: true
+ #
+ # Camping code example:
+ # --------------------------------------------------------------------------------------
+ # require "newrelic_rpm"
+ # require 'new_relic/agent/agent'
+ # require 'new_relic/agent/instrumentation/controller_instrumentation'
+ # require 'new_relic/agent/instrumentation/camping'
+ #
+ # Camping.goes :NewRelicCampingTest
+ #
+ # module NewRelicCampingTest
+ # # your code
+ #
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
+ # include NewRelic::Agent::Instrumentation::Camping
+ # end
+ #
+ # NewRelic::Agent.manual_start
+ #
+
+ module Camping
+
+ def self.included(mod)
+
+ # Since the Camping::Base module is essentially copied
+ # into the main module (the mod passed in) of a Camping app
+ # using the Camping.goes :NewRelicCampingTest syntax
+ # we need to evaluate "weld" the NewRelic plugin in the context of the new Base
+
+ (Kernel.const_get(mod.name)::Base).module_eval do
+
+ # Add the new method to the Camping app's Base module
+ # since the Camping::Base module is being included
+ # in every Camping controller
+
+ def service_with_newrelic(*args)
+ perform_action_with_newrelic_trace(:category => :rack) do
+ service_without_newrelic(*args)
+ end
+ end
+
+ # Alias the "standard" service method
+ # so we can provide a level of indirection
+ # to perform the tracing for NewRelic
+
+ alias service_without_newrelic service
+ alias service service_with_newrelic
+ end
+ end
+
+ end #RPMContrib::Instrumentation::Camping
+ end
+end
View
2  ...nt/instrumentation/delayed_job_instrumentation.rb → ...ib/instrumentation/delayed_job_instrumentation.rb
@@ -1,4 +1,4 @@
-module NewRelic::Agent::Instrumentation::DelayedJobInstrumentation
+module RPMContrib::Instrumentation::DelayedJobInstrumentation
extend self
Delayed::Job.class_eval do
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
View
22 lib/rpm_contrib/instrumentation/paperclip.rb
@@ -0,0 +1,22 @@
+# Paperclip Instrumentation.
+
+if defined? ::Paperclip
+
+ ::Paperclip::Attachment.class_eval do
+ add_method_tracer :save, 'Paperclip/#{name}/save'
+ add_method_tracer :assign, 'Paperclip/#{name}/assign'
+ add_method_tracer :post_process, 'Paperclip/#{name}/post_process'
+ end
+
+ ::Paperclip::Storage::Filesystem.class_eval do
+ add_method_tracer :flush_deletes, 'Paperclip/Storage/flush_deletes'
+ add_method_tracer :flush_writes, 'Paperclip/Storage/flush_writes'
+ end
+
+ ::Paperclip::Storage::S3.class_eval do
+ add_method_tracer :flush_deletes, 'Paperclip/Storage/flush_deletes'
+ add_method_tracer :flush_writes, 'Paperclip/Storage/flush_writes'
+ end
+
+end
+
View
0  ..._relic/agent/samplers/delayed_job_lock_sampler.rb → lib/rpm_contrib/samplers/delayed_job_lock_sampler.rb
File renamed without changes
View
108 test/delayed_job_instrumentation/delayed_job_test.rb
@@ -0,0 +1,108 @@
+module DelayedJobInstrumentation
+ require File.expand_path(File.join(File.dirname(__FILE__),'/../test_helper'))
+
+ class LongRunningJob
+ def perform
+ sleep 5
+ end
+ end
+
+ class NamedJob
+ def display_name
+ 'some custom name'
+ end
+ def perform
+ true
+ end
+ end
+
+ class DelayedJobTest < Test::Unit::TestCase
+ def local_env
+ NewRelic::Control.instance.local_env
+ end
+
+ def worker_name
+ local_env.dispatcher_instance_id
+ end
+
+ def lock_n_jobs(n=1)
+ n.times do
+ job = Delayed::Job.create
+ job.update_attributes({
+ :locked_at => Time.now,
+ :locked_by => worker_name
+ })
+ end
+ end
+
+ def setup
+ NewRelic::Agent.manual_start
+ @agent = NewRelic::Agent.instance
+
+ @agent.transaction_sampler.harvest
+ @agent.stats_engine.clear_stats
+ end
+
+ def teardown
+ @agent.instance_variable_set("@histogram", NewRelic::Histogram.new)
+ end
+
+ def test_job_instrumentation
+ job = Delayed::Job.new(:payload_object => LongRunningJob.new)
+ job_name = "Controller/Task/Delayed::Job/LongRunningJob"
+
+ job.invoke_job
+ job_stats = @agent.stats_engine.get_stats(job_name)
+
+ assert @agent.stats_engine.metrics.include?(job_name)
+ assert_equal 1, job_stats.call_count
+ end
+
+ def test_custom_name
+ job = Delayed::Job.new(:payload_object => NamedJob.new)
+ job_name = "Controller/Task/Delayed::Job/some custom name"
+
+ job.invoke_job
+ job_stats = @agent.stats_engine.get_stats(job_name)
+
+ assert @agent.stats_engine.metrics.include?(job_name)
+ assert_equal 1, job_stats.call_count
+ end
+
+ def test_lock_sampler
+ stats_engine = NewRelic::Agent::StatsEngine.new
+ sampler = NewRelic::Agent::Samplers::DelayedJobLockSampler.new
+ sampler.stats_engine = stats_engine
+
+ lock_n_jobs(1)
+ sampler.poll
+
+ assert_equal 1, sampler.stats.data_point_count
+ assert_equal 1, sampler.stats.min_call_time
+ assert_equal 1, sampler.stats.max_call_time
+
+ lock_n_jobs(4)
+ sampler.poll
+
+ assert_equal 2, sampler.stats.data_point_count
+ assert_equal 1, sampler.stats.min_call_time
+ assert_equal 5, sampler.stats.max_call_time
+
+ lock_n_jobs(5)
+ sampler.poll
+ sampler.poll
+
+ assert_equal 4, sampler.stats.data_point_count
+ assert_equal 1, sampler.stats.min_call_time
+ assert_equal 10, sampler.stats.max_call_time
+
+ Delayed::Job.destroy_all
+ sampler.poll
+
+ assert_equal 5, sampler.stats.data_point_count
+ assert_equal 0, sampler.stats.min_call_time
+ assert_equal 10, sampler.stats.max_call_time
+ end
+
+ end
+end if defined? Delayed::Job
Please sign in to comment.
Something went wrong with that request. Please try again.