rpm_contrib 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,7 @@
1
+ * Version 1.0.0
2
+
3
+ Initial Release:
4
+ - Camping
5
+ - Authlogic
6
+ - DelayedJob
7
+ - Paperclip
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 New Relic, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # The RPM Contrib Gem
2
+
3
+ The `rpm_contrib` gem contains instrumentation for the New Relic RPM agent
4
+ contributed by the community of RPM users. It requires the RPM Agent
5
+ to run.
6
+
7
+ We encourage contributions to this project and will provide whatever
8
+ assistance we can to those wishing to develop instrumentation for
9
+ other open source Ruby libraries.
10
+
11
+ ## Note on Patches/Pull Requests
12
+
13
+ * Fork the http://www.github.com/newrelic/rpm_contrib project.
14
+ * Add instrumentation files to `lib/rpm_contrib/instrumentation`. These
15
+ files will be loaded when the RPM agent is initialized.
16
+ * Add samplers to `lib/rpm_contrib/samplers`. These classes are
17
+ installed automatically when the RPM agent is initialized.
18
+ * Add tests.
19
+ * Commit, do not mess with the Rakefile, version, or history. (if you
20
+ want to have your own version, that is fine but bump version in a
21
+ commit by itself I can ignore when I pull)
22
+ * Send me a pull request. Bonus points for topic branches.
23
+
24
+ ## Further Information
25
+
26
+ Refer to the [Agent API Documentation](http://newrelic.github.com/rpm).
27
+
28
+ See [the support site](http://support.newrelic.com/faqs) for additional tips and documentation.
29
+
30
+ Contact support@newrelic.com for help.
31
+
32
+ ## Copyright
33
+
34
+ Copyright (c) 2010 New Relic. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ # See http://www.rubygems.org/read/chapter/20
4
+
5
+ def version
6
+ @rpm_contrib_version ||= File.read("CHANGELOG")[/Version ([\d\.]+)$/, 1]
7
+ end
8
+
9
+ begin
10
+ require 'jeweler'
11
+ Jeweler::Tasks.new do |gem|
12
+ gem.name = "rpm_contrib"
13
+ gem.summary = %Q{Contributed Instrumentation for New Relic RPM}
14
+ gem.description = <<-EOF
15
+ Community contributed instrumentation for various frameworks based on
16
+ the New Relic Ruby monitoring gem newrelic_rpm.
17
+ EOF
18
+ gem.email = "support@newrelic.com"
19
+ gem.homepage = "http://github.com/newrelic/rpm_contrib"
20
+ gem.author = "Bill Kayser"
21
+ gem.add_dependency 'newrelic_rpm', '>= 2.10.2.2'
22
+ gem.version = version
23
+ gem.files = FileList['LICENSE', 'README*', 'lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a
24
+ end
25
+ Jeweler::GemcutterTasks.new
26
+ rescue LoadError
27
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
28
+ end
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |test|
32
+ test.libs << 'lib' << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+
37
+ begin
38
+ require 'rcov/rcovtask'
39
+ Rcov::RcovTask.new do |test|
40
+ test.libs << 'test'
41
+ test.pattern = 'test/**/test_*.rb'
42
+ test.verbose = true
43
+ end
44
+ rescue LoadError
45
+ task :rcov do
46
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
47
+ end
48
+ end
49
+
50
+ task :test => :check_dependencies
51
+
52
+ task :default => :test
53
+
54
+ require 'rake/rdoctask'
55
+ Rake::RDocTask.new do |rdoc|
56
+ rdoc.rdoc_dir = 'rdoc'
57
+ rdoc.title = "rpm_contrib #{version}"
58
+ rdoc.rdoc_files.include('README*')
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ end
@@ -0,0 +1,8 @@
1
+ if defined? Authlogic::Session::Base
2
+ Authlogic::Session::Base.class_eval do
3
+ # add_method_tracer :record, 'Authlogic/record'
4
+ class << self
5
+ add_method_tracer :find, 'Authlogic/find'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,74 @@
1
+ require 'new_relic/agent/instrumentation/controller_instrumentation'
2
+
3
+ module RPMContrib
4
+ module Instrumentation
5
+ # == Instrumentation for Camping
6
+ # To instrument all controllers do the following:
7
+ # 1. Add the necessary NewRelic-specific requires in your require section
8
+ # 2. Add an include at the end of your main Camping app module
9
+ # 3. Add a call to NewRelic::Agent.manual_start at the end of the file to start the agent
10
+ # 4. Run the following command to get the NewRelic license key to use: heroku config -all
11
+ # 5. Create a newrelic.yml under the /config folder with the following content:
12
+ #
13
+ # common: &default_settings
14
+ # license_key: 'PASTE THE VALUE OF NEW_RELIC_LICENSE_KEY HERE'
15
+ # agent_enabled: true
16
+ # app_name: PASTE THE NAME OF YOUR CAMPING APP HERE
17
+ # enabled: true
18
+ #
19
+ # production:
20
+ # <<: *default_settings
21
+ # enabled: true
22
+ #
23
+ # Camping code example:
24
+ # --------------------------------------------------------------------------------------
25
+ # require "newrelic_rpm"
26
+ # require 'new_relic/agent/agent'
27
+ # require 'new_relic/agent/instrumentation/controller_instrumentation'
28
+ # require 'new_relic/agent/instrumentation/camping'
29
+ #
30
+ # Camping.goes :NewRelicCampingTest
31
+ #
32
+ # module NewRelicCampingTest
33
+ # # your code
34
+ #
35
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
36
+ # include NewRelic::Agent::Instrumentation::Camping
37
+ # end
38
+ #
39
+ # NewRelic::Agent.manual_start
40
+ #
41
+
42
+ module Camping
43
+
44
+ def self.included(mod)
45
+
46
+ # Since the Camping::Base module is essentially copied
47
+ # into the main module (the mod passed in) of a Camping app
48
+ # using the Camping.goes :NewRelicCampingTest syntax
49
+ # we need to evaluate "weld" the NewRelic plugin in the context of the new Base
50
+
51
+ (Kernel.const_get(mod.name)::Base).module_eval do
52
+
53
+ # Add the new method to the Camping app's Base module
54
+ # since the Camping::Base module is being included
55
+ # in every Camping controller
56
+
57
+ def service_with_newrelic(*args)
58
+ perform_action_with_newrelic_trace(:category => :rack) do
59
+ service_without_newrelic(*args)
60
+ end
61
+ end
62
+
63
+ # Alias the "standard" service method
64
+ # so we can provide a level of indirection
65
+ # to perform the tracing for NewRelic
66
+
67
+ alias service_without_newrelic service
68
+ alias service service_with_newrelic
69
+ end
70
+ end
71
+
72
+ end #RPMContrib::Instrumentation::Camping
73
+ end
74
+ end
@@ -0,0 +1,45 @@
1
+ module RPMContrib::Instrumentation::DelayedJobInstrumentation
2
+ extend self
3
+ Delayed::Job.class_eval do
4
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
5
+ if self.instance_methods.include?('name')
6
+ add_transaction_tracer "invoke_job", :category => :task, :name => '#{self.name}'
7
+ else
8
+ add_transaction_tracer "invoke_job", :category => :task
9
+ end
10
+ end
11
+
12
+ Delayed::Worker.class_eval do
13
+ def initialize_with_new_relic(*args)
14
+ initialize_without_new_relic(*args)
15
+ NewRelic::.delayed_worker = self
16
+ end
17
+
18
+ alias initialize_without_new_relic initialize
19
+ alias initialize initialize_with_new_relic
20
+ end
21
+
22
+ def delayed_worker=(w)
23
+ @delayed_worker = w
24
+ env = NewRelic::Control.instance.local_env
25
+ env.dispatcher = :delayed_job
26
+ env.dispatcher_instance_id = case
27
+ when @delayed_worker.respond_to?(:name)
28
+ @delayed_worker.name
29
+ when @delayed_worker.class.respond_to?(:default_name)
30
+ @delayed_worker.class.default_name
31
+ else
32
+ "host:#{Socket.gethostname} pid:#{Process.pid}" rescue "pid:#{Process.pid}"
33
+ end
34
+
35
+ env.append_environment_value 'Dispatcher', @dispatcher.to_s
36
+ env.append_environment_value 'Dispatcher instance id', @dispatcher_instance_id
37
+
38
+ @delayed_worker
39
+ end
40
+
41
+ def delayed_worker
42
+ @delayed_worker
43
+ end
44
+
45
+ end if defined?(Delayed::Job)
@@ -0,0 +1,22 @@
1
+ # Paperclip Instrumentation.
2
+
3
+ if defined? ::Paperclip
4
+
5
+ ::Paperclip::Attachment.class_eval do
6
+ add_method_tracer :save, 'Paperclip/#{name}/save'
7
+ add_method_tracer :assign, 'Paperclip/#{name}/assign'
8
+ add_method_tracer :post_process, 'Paperclip/#{name}/post_process'
9
+ end
10
+
11
+ ::Paperclip::Storage::Filesystem.class_eval do
12
+ add_method_tracer :flush_deletes, 'Paperclip/Storage/flush_deletes'
13
+ add_method_tracer :flush_writes, 'Paperclip/Storage/flush_writes'
14
+ end
15
+
16
+ ::Paperclip::Storage::S3.class_eval do
17
+ add_method_tracer :flush_deletes, 'Paperclip/Storage/flush_deletes'
18
+ add_method_tracer :flush_writes, 'Paperclip/Storage/flush_writes'
19
+ end
20
+
21
+ end
22
+
@@ -0,0 +1,28 @@
1
+ module NewRelic::Agent::Samplers
2
+ class DelayedJobLockSampler < NewRelic::Agent::Sampler
3
+ def initialize
4
+ super :delayed_job_lock
5
+ raise Unsupported, "No delayed job workers running" unless Instrumentation::DelayedJobInstrumentation.delayed_worker
6
+ end
7
+
8
+ def stats
9
+ stats_engine.get_stats("DJ/Locked Jobs", false)
10
+ end
11
+
12
+ def local_env
13
+ NewRelic::Control.instance.local_env
14
+ end
15
+
16
+ def worker_name
17
+ local_env.dispatcher_instance_id
18
+ end
19
+
20
+ def locked_jobs
21
+ Delayed::Job.count(:conditions => {:locked_by => worker_name})
22
+ end
23
+
24
+ def poll
25
+ stats.record_data_point locked_jobs
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # Hook instrumentation and samplers in this gem into the normal RPM
2
+ # start up sequence.
3
+ require 'newrelic_rpm'
4
+ module RPMContrib
5
+
6
+ lib_root = File.dirname(__FILE__)
7
+
8
+ # Tell the agent to load all the files in the rpm_contrib/instrumentation directory.
9
+
10
+ NewRelic::Agent.add_instrumentation(lib_root+"/rpm_contrib/instrumentation/**/*.rb")
11
+
12
+ # Load all the Sampler class definitions. These will register
13
+ # automatically with the agent.
14
+ Dir.glob(lib_root + "/rpm_contrib/samplers/**/*.rb") { |file| require file }
15
+
16
+ VERSION = File.read(lib_root+"/../CHANGELOG")[/Version ([\d\.]+)$/, 1]
17
+ end
@@ -0,0 +1,108 @@
1
+ module DelayedJobInstrumentation
2
+ require File.expand_path(File.join(File.dirname(__FILE__),'/../test_helper'))
3
+
4
+ class LongRunningJob
5
+ def perform
6
+ sleep 5
7
+ end
8
+ end
9
+
10
+ class NamedJob
11
+ def display_name
12
+ 'some custom name'
13
+ end
14
+ def perform
15
+ true
16
+ end
17
+ end
18
+
19
+ class DelayedJobTest < Test::Unit::TestCase
20
+ def local_env
21
+ NewRelic::Control.instance.local_env
22
+ end
23
+
24
+ def worker_name
25
+ local_env.dispatcher_instance_id
26
+ end
27
+
28
+ def lock_n_jobs(n=1)
29
+ n.times do
30
+ job = Delayed::Job.create
31
+ job.update_attributes({
32
+ :locked_at => Time.now,
33
+ :locked_by => worker_name
34
+ })
35
+ end
36
+ end
37
+
38
+ def setup
39
+ NewRelic::Agent.manual_start
40
+ @agent = NewRelic::Agent.instance
41
+
42
+ @agent.transaction_sampler.harvest
43
+ @agent.stats_engine.clear_stats
44
+ end
45
+
46
+ def teardown
47
+ @agent.instance_variable_set("@histogram", NewRelic::Histogram.new)
48
+ end
49
+
50
+ def test_job_instrumentation
51
+ job = Delayed::Job.new(:payload_object => LongRunningJob.new)
52
+ job_name = "Controller/Task/Delayed::Job/LongRunningJob"
53
+
54
+ job.invoke_job
55
+ job_stats = @agent.stats_engine.get_stats(job_name)
56
+
57
+ assert @agent.stats_engine.metrics.include?(job_name)
58
+ assert_equal 1, job_stats.call_count
59
+ end
60
+
61
+ def test_custom_name
62
+ job = Delayed::Job.new(:payload_object => NamedJob.new)
63
+ job_name = "Controller/Task/Delayed::Job/some custom name"
64
+
65
+ job.invoke_job
66
+ job_stats = @agent.stats_engine.get_stats(job_name)
67
+
68
+ assert @agent.stats_engine.metrics.include?(job_name)
69
+ assert_equal 1, job_stats.call_count
70
+ end
71
+
72
+ def test_lock_sampler
73
+ stats_engine = NewRelic::Agent::StatsEngine.new
74
+ sampler = NewRelic::Agent::Samplers::DelayedJobLockSampler.new
75
+ sampler.stats_engine = stats_engine
76
+
77
+ lock_n_jobs(1)
78
+ sampler.poll
79
+
80
+ assert_equal 1, sampler.stats.data_point_count
81
+ assert_equal 1, sampler.stats.min_call_time
82
+ assert_equal 1, sampler.stats.max_call_time
83
+
84
+ lock_n_jobs(4)
85
+ sampler.poll
86
+
87
+ assert_equal 2, sampler.stats.data_point_count
88
+ assert_equal 1, sampler.stats.min_call_time
89
+ assert_equal 5, sampler.stats.max_call_time
90
+
91
+ lock_n_jobs(5)
92
+ sampler.poll
93
+ sampler.poll
94
+
95
+ assert_equal 4, sampler.stats.data_point_count
96
+ assert_equal 1, sampler.stats.min_call_time
97
+ assert_equal 10, sampler.stats.max_call_time
98
+
99
+ Delayed::Job.destroy_all
100
+ sampler.poll
101
+
102
+ assert_equal 5, sampler.stats.data_point_count
103
+ assert_equal 0, sampler.stats.min_call_time
104
+ assert_equal 10, sampler.stats.max_call_time
105
+ end
106
+
107
+ end
108
+ end if defined? Delayed::Job
data/test/helper.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'rpm_contrib'
7
+
8
+ class Test::Unit::TestCase
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestRpmContrib < Test::Unit::TestCase
4
+ def test_something_for_real
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rpm_contrib
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Bill Kayser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-28 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: newrelic_rpm
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.10.2.2
24
+ version:
25
+ description: " Community contributed instrumentation for various frameworks based on\n the New Relic Ruby monitoring gem newrelic_rpm.\n"
26
+ email: support@newrelic.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.md
34
+ files:
35
+ - CHANGELOG
36
+ - LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - lib/rpm_contrib.rb
40
+ - lib/rpm_contrib/instrumentation/authlogic.rb
41
+ - lib/rpm_contrib/instrumentation/camping.rb
42
+ - lib/rpm_contrib/instrumentation/delayed_job_instrumentation.rb
43
+ - lib/rpm_contrib/instrumentation/paperclip.rb
44
+ - lib/rpm_contrib/samplers/delayed_job_lock_sampler.rb
45
+ - test/delayed_job_instrumentation/delayed_job_test.rb
46
+ - test/helper.rb
47
+ - test/test_rpm_contrib.rb
48
+ has_rdoc: true
49
+ homepage: http://github.com/newrelic/rpm_contrib
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --charset=UTF-8
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.3.5
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Contributed Instrumentation for New Relic RPM
76
+ test_files:
77
+ - test/delayed_job_instrumentation/delayed_job_test.rb
78
+ - test/helper.rb
79
+ - test/test_rpm_contrib.rb