newrelic_rpm 3.5.6.42.beta → 3.5.6.46.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +5 -0
- data/lib/new_relic/agent/busy_calculator.rb +5 -0
- data/lib/new_relic/agent/worker_loop.rb +2 -1
- data/lib/new_relic/control/instance_methods.rb +1 -1
- data/lib/new_relic/version.rb +1 -1
- data/newrelic_rpm.gemspec +6 -1
- data/test/multiverse/suites/active_record/Envfile +1 -1
- data/test/multiverse/suites/active_record/ar_method_aliasing.rb +1 -1
- data/test/multiverse/suites/agent_only/service_timeout_test.rb +6 -3
- data/test/multiverse/suites/agent_only/start_up_test.rb +9 -2
- data/test/multiverse/suites/rails/gc_instrumentation_test.rb +10 -4
- data/test/multiverse/suites/resque/Envfile +3 -2
- data/test/multiverse/suites/resque/instrumentation_test.rb +26 -7
- data/test/new_relic/agent/busy_calculator_test.rb +8 -0
- data/test/new_relic/agent/worker_loop_test.rb +22 -15
- data/test/new_relic/control_test.rb +4 -0
- data/test/new_relic/fake_collector.rb +14 -0
- metadata +2 -2
data/Rakefile
CHANGED
@@ -47,7 +47,12 @@ desc 'Record build number and stage'
|
|
47
47
|
task :record_build, [ :build_number, :stage ] do |t, args|
|
48
48
|
build_string = args.build_number
|
49
49
|
build_string << ".#{args.stage}" if args.stage
|
50
|
+
|
51
|
+
gitsha = File.exists?(".git") ? `git rev-parse HEAD` : "Unknown"
|
52
|
+
gitsha.chomp!
|
53
|
+
|
50
54
|
File.open("lib/new_relic/build.rb", "w") do |f|
|
55
|
+
f.write("# GITSHA: #{gitsha}\n")
|
51
56
|
f.write("module NewRelic; module VERSION; BUILD='#{build_string}'; end; end\n")
|
52
57
|
end
|
53
58
|
end
|
@@ -31,10 +31,15 @@ module NewRelic
|
|
31
31
|
# instance variable accumulator. this is harvested when we send
|
32
32
|
# data to the server
|
33
33
|
def dispatcher_finish(end_time = nil)
|
34
|
+
# If #dispatcher_start hasn't been called at least once, abort early
|
35
|
+
return unless Thread.current[:busy_entries]
|
36
|
+
|
34
37
|
end_time ||= time_now
|
35
38
|
callers = Thread.current[:busy_entries] -= 1
|
39
|
+
|
36
40
|
# Ignore nested calls
|
37
41
|
return if callers > 0
|
42
|
+
|
38
43
|
@lock.synchronize do
|
39
44
|
if @entrypoint_stack.empty?
|
40
45
|
::NewRelic::Agent.logger.warn("Stack underflow tracking dispatcher entry and exit!\n #{caller.join(" \n")}")
|
@@ -12,7 +12,7 @@ module NewRelic
|
|
12
12
|
@should_run = true
|
13
13
|
@next_invocation_time = Time.now
|
14
14
|
@period = 60.0
|
15
|
-
@
|
15
|
+
@duration = opts[:duration] if opts[:duration]
|
16
16
|
@limit = opts[:limit] if opts[:limit]
|
17
17
|
@iterations = 0
|
18
18
|
end
|
@@ -26,6 +26,7 @@ module NewRelic
|
|
26
26
|
# call periods. The caller is responsible for creating the thread
|
27
27
|
# that runs this worker loop. This will run the task immediately.
|
28
28
|
def run(period=nil, &block)
|
29
|
+
@deadline = Time.now + @duration if @duration
|
29
30
|
@period = period if period
|
30
31
|
@next_invocation_time = (Time.now + @period)
|
31
32
|
@task = block
|
data/lib/new_relic/version.rb
CHANGED
data/newrelic_rpm.gemspec
CHANGED
@@ -27,7 +27,12 @@ EOS
|
|
27
27
|
"GUIDELINES_FOR_CONTRIBUTING.md",
|
28
28
|
"newrelic.yml"
|
29
29
|
]
|
30
|
-
|
30
|
+
|
31
|
+
file_list = `git ls-files`.split
|
32
|
+
build_file_path = 'lib/new_relic/build.rb'
|
33
|
+
file_list << build_file_path if File.exist?(build_file_path)
|
34
|
+
s.files = file_list
|
35
|
+
|
31
36
|
s.homepage = "http://www.github.com/newrelic/rpm"
|
32
37
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "New Relic Ruby Agent"]
|
33
38
|
s.require_paths = ["lib"]
|
@@ -2,8 +2,8 @@ gemfile <<-RB
|
|
2
2
|
if RUBY_VERSION == '1.8.6'
|
3
3
|
gem 'activerecord', '2.3.14'
|
4
4
|
elsif RUBY_PLATFORM == 'java'
|
5
|
+
gem 'activerecord-jdbcsqlite3-adapter', '1.2.2.1'
|
5
6
|
gem 'jdbc-sqlite3'
|
6
|
-
gem 'activerecord-jdbcsqlite3-adapter'
|
7
7
|
gem 'activerecord'
|
8
8
|
else
|
9
9
|
gem 'activerecord'
|
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'socket'
|
2
2
|
|
3
3
|
class ServiceTimeoutTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
PORT = 10_000 + ($$ % 10_000)
|
6
|
+
|
4
7
|
def setup
|
5
|
-
hk = TCPServer.new('127.0.0.1',
|
8
|
+
hk = TCPServer.new('127.0.0.1',PORT)
|
6
9
|
|
7
10
|
Thread.new {
|
8
11
|
client = hk.accept
|
@@ -14,8 +17,8 @@ class ServiceTimeoutTest < Test::Unit::TestCase
|
|
14
17
|
end
|
15
18
|
|
16
19
|
def test_service_timeout
|
17
|
-
server = NewRelic::Control::Server.new('localhost',
|
18
|
-
NewRelic::Agent.config.apply_config(:timeout =>
|
20
|
+
server = NewRelic::Control::Server.new('localhost',PORT,'127.0.0.1')
|
21
|
+
NewRelic::Agent.config.apply_config(:timeout => 0.1)
|
19
22
|
|
20
23
|
service = NewRelic::Agent::NewRelicService.new('deadbeef', server)
|
21
24
|
|
@@ -7,8 +7,15 @@ class StartUpTest < Test::Unit::TestCase
|
|
7
7
|
cmd = "bundle exec ruby -e '#{ruby}'"
|
8
8
|
|
9
9
|
sin, sout, serr = Open3.popen3(cmd)
|
10
|
+
output = sout.read + serr.read
|
10
11
|
|
11
|
-
jruby_noise =
|
12
|
-
|
12
|
+
jruby_noise = [
|
13
|
+
"JRuby limited openssl loaded. http://jruby.org/openssl\n",
|
14
|
+
"gem install jruby-openssl for full support.\n",
|
15
|
+
/Exception\: java\.lang.*\n/]
|
16
|
+
|
17
|
+
jruby_noise.each {|noise| output.gsub!(noise, "")}
|
18
|
+
|
19
|
+
assert_equal '', output
|
13
20
|
end
|
14
21
|
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
require './app'
|
2
2
|
|
3
|
+
# GC instrumentation only works with REE or 1.9.x
|
4
|
+
if (defined?(RUBY_DESCRIPTION) && RUBY_DESCRIPTION =~ /Enterprise/) ||
|
5
|
+
RUBY_VERSION >= '1.9.2'
|
6
|
+
|
3
7
|
class GcController < ApplicationController
|
4
8
|
include Rails.application.routes.url_helpers
|
5
9
|
def gc_action
|
@@ -44,13 +48,13 @@ class GCRailsInstrumentationTest < ActionController::TestCase
|
|
44
48
|
assert_in_delta(assigns[:duration],
|
45
49
|
NewRelic::Agent.agent.stats_engine \
|
46
50
|
.get_stats('GC/cumulative') \
|
47
|
-
.total_call_time, 0.
|
51
|
+
.total_call_time, 0.2,
|
48
52
|
'problem with unscoped GC metric')
|
49
53
|
assert_in_delta(assigns[:duration],
|
50
54
|
NewRelic::Agent.agent.stats_engine \
|
51
55
|
.get_stats('GC/cumulative', true, false,
|
52
|
-
'Controller/
|
53
|
-
.total_call_time, 0.
|
56
|
+
'Controller/gc/gc_action') \
|
57
|
+
.total_call_time, 0.2,
|
54
58
|
'problem with scoped GC metric')
|
55
59
|
end
|
56
60
|
|
@@ -58,7 +62,7 @@ class GCRailsInstrumentationTest < ActionController::TestCase
|
|
58
62
|
get :gc_action
|
59
63
|
|
60
64
|
trace = NewRelic::Agent.instance.transaction_sampler.last_sample
|
61
|
-
assert_in_delta(assigns[:duration], trace.params[:custom_params][:gc_time], 0.
|
65
|
+
assert_in_delta(assigns[:duration], trace.params[:custom_params][:gc_time], 0.2)
|
62
66
|
end
|
63
67
|
|
64
68
|
def enable_gc_stats
|
@@ -69,3 +73,5 @@ class GCRailsInstrumentationTest < ActionController::TestCase
|
|
69
73
|
end
|
70
74
|
end
|
71
75
|
end
|
76
|
+
|
77
|
+
end
|
@@ -11,11 +11,12 @@ gemfile <<-RB
|
|
11
11
|
RB
|
12
12
|
|
13
13
|
before_suite do
|
14
|
-
|
14
|
+
ENV["NEWRELIC_MULTIVERSE_REDIS_PORT"] = (20_000 + ($$ % 10_000)).to_s
|
15
|
+
system("echo 'port #{ENV["NEWRELIC_MULTIVERSE_REDIS_PORT"]}' | redis-server - > /dev/null &")
|
15
16
|
end
|
16
17
|
|
17
18
|
after_suite do
|
18
|
-
system(
|
19
|
+
system("redis-cli -p #{ENV["NEWRELIC_MULTIVERSE_REDIS_PORT"]} shutdown")
|
19
20
|
end
|
20
21
|
|
21
22
|
execute_mode 'spawn'
|
@@ -6,12 +6,14 @@ require 'logger'
|
|
6
6
|
require 'newrelic_rpm'
|
7
7
|
require 'fake_collector'
|
8
8
|
|
9
|
+
REDIS_PORT = ENV["NEWRELIC_MULTIVERSE_REDIS_PORT"]
|
10
|
+
|
9
11
|
class JobForTesting
|
10
12
|
@queue = :resque_test
|
11
13
|
|
12
14
|
def self.perform(key, val, sleep_duration=0)
|
13
15
|
sleep sleep_duration
|
14
|
-
Redis.new.set(key, val)
|
16
|
+
Redis.new(:port => REDIS_PORT).set(key, val)
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
@@ -19,7 +21,8 @@ class ResqueTest < Test::Unit::TestCase
|
|
19
21
|
JOB_COUNT = 5
|
20
22
|
|
21
23
|
def setup
|
22
|
-
@redis = Redis.new
|
24
|
+
@redis = Redis.new(:port => REDIS_PORT)
|
25
|
+
Resque.redis = @redis
|
23
26
|
|
24
27
|
$collector ||= NewRelic::FakeCollector.new
|
25
28
|
$collector.reset
|
@@ -33,11 +36,24 @@ class ResqueTest < Test::Unit::TestCase
|
|
33
36
|
Thread.new do
|
34
37
|
worker.work
|
35
38
|
end.abort_on_exception = true
|
36
|
-
|
39
|
+
|
40
|
+
wait_for_jobs
|
37
41
|
worker.shutdown
|
38
42
|
|
39
43
|
NewRelic::Agent.shutdown
|
40
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
def wait_for_jobs
|
47
|
+
# JRuby barfs in the timeout on trying to read from Redis.
|
48
|
+
time_for_jobs = 2
|
49
|
+
if defined?(JRuby)
|
50
|
+
sleep time_for_jobs
|
51
|
+
else
|
52
|
+
# Give a little time to complete, get out early if we're done....
|
53
|
+
Timeout::timeout(time_for_jobs) do
|
54
|
+
until Resque.info[:pending] == 0; end
|
55
|
+
end
|
56
|
+
end
|
41
57
|
end
|
42
58
|
|
43
59
|
def teardown
|
@@ -59,15 +75,18 @@ class ResqueTest < Test::Unit::TestCase
|
|
59
75
|
"wrong number of metric_data posts in #{$collector.agent_data.inspect}")
|
60
76
|
end
|
61
77
|
|
78
|
+
|
79
|
+
METRIC_VALUES_POSITION = 3
|
80
|
+
|
62
81
|
def test_agent_posts_correct_call_count
|
63
82
|
test_metric = 'OtherTransaction/ResqueJob/all'
|
64
|
-
metric_data = $collector.
|
83
|
+
metric_data = $collector.calls_for('metric_data').first
|
65
84
|
|
66
|
-
metric_names = metric_data
|
85
|
+
metric_names = metric_data[METRIC_VALUES_POSITION].map{|m| m[0]['name']}
|
67
86
|
assert(metric_names.include?(test_metric),
|
68
87
|
"#{metric_names.inspect} should include '#{test_metric}'")
|
69
88
|
|
70
|
-
call_count = metric_data
|
89
|
+
call_count = metric_data[METRIC_VALUES_POSITION].find{|m| m[0]['name'] == test_metric}[1][0]
|
71
90
|
assert_equal JOB_COUNT, call_count
|
72
91
|
end
|
73
92
|
end
|
@@ -85,4 +85,12 @@ class NewRelic::Agent::BusyCalculatorTest < Test::Unit::TestCase
|
|
85
85
|
assert_equal 0, @instance_busy.call_count
|
86
86
|
end
|
87
87
|
end
|
88
|
+
|
89
|
+
def test_finishing_without_starting_doesnt_raise
|
90
|
+
Thread.current[:busy_entries] = nil
|
91
|
+
assert_nothing_raised do
|
92
|
+
NewRelic::Agent::BusyCalculator.dispatcher_finish
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
88
96
|
end
|
@@ -18,6 +18,11 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
|
|
18
18
|
|
19
19
|
def test_with_duration
|
20
20
|
worker_loop = NewRelic::Agent::WorkerLoop.new(:duration => 0.1)
|
21
|
+
|
22
|
+
# Advance in small increments vs our period so time will pass over the
|
23
|
+
# nasty multiple calls to Time.now that WorkerLoop makes
|
24
|
+
Time.stubs(:now).returns(*ticks(0, 0.12, 0.005))
|
25
|
+
|
21
26
|
count = 0
|
22
27
|
worker_loop.run(0.04) do
|
23
28
|
count += 1
|
@@ -26,6 +31,19 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
|
|
26
31
|
assert_equal 2, count
|
27
32
|
end
|
28
33
|
|
34
|
+
def test_duration_clock_starts_with_run
|
35
|
+
# Purposefully testing time, but shouldn't be particularly fragile
|
36
|
+
worker_loop = NewRelic::Agent::WorkerLoop.new(:duration => 0.01)
|
37
|
+
sleep 0.02
|
38
|
+
|
39
|
+
called = false
|
40
|
+
worker_loop.run(0.001) do
|
41
|
+
called = true
|
42
|
+
end
|
43
|
+
|
44
|
+
assert(called, "Didn't run the loop even once")
|
45
|
+
end
|
46
|
+
|
29
47
|
def test_loop_limit
|
30
48
|
worker_loop = NewRelic::Agent::WorkerLoop.new(:limit => 2)
|
31
49
|
iterations = 0
|
@@ -33,21 +51,6 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
|
|
33
51
|
assert_equal 2, iterations
|
34
52
|
end
|
35
53
|
|
36
|
-
def test_density
|
37
|
-
# This shows how the tasks stay aligned with the period and don't drift.
|
38
|
-
count = 0
|
39
|
-
start = Time.now
|
40
|
-
@worker_loop.run(0.03) do
|
41
|
-
count +=1
|
42
|
-
if count == 3
|
43
|
-
@worker_loop.stop
|
44
|
-
next
|
45
|
-
end
|
46
|
-
end
|
47
|
-
elapsed = Time.now - start
|
48
|
-
assert_in_delta 0.09, elapsed, 0.03
|
49
|
-
end
|
50
|
-
|
51
54
|
def test_task_error__standard
|
52
55
|
expects_logging(:error, any_parameters)
|
53
56
|
# This loop task will run twice
|
@@ -78,4 +81,8 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
|
|
78
81
|
raise NewRelic::Agent::ServerError, "Runtime Error Test"
|
79
82
|
end
|
80
83
|
end
|
84
|
+
|
85
|
+
def ticks(start, finish, step)
|
86
|
+
(start..finish).step(step).to_a
|
87
|
+
end
|
81
88
|
end
|
@@ -67,6 +67,10 @@ class NewRelic::ControlTest < Test::Unit::TestCase
|
|
67
67
|
control.local_env
|
68
68
|
end
|
69
69
|
|
70
|
+
def test_settings_accessor
|
71
|
+
assert_not_nil control.settings
|
72
|
+
end
|
73
|
+
|
70
74
|
def test_root
|
71
75
|
assert File.directory?(NewRelic::Control.newrelic_root), NewRelic::Control.newrelic_root
|
72
76
|
if defined?(Rails)
|
@@ -82,15 +82,29 @@ module NewRelic
|
|
82
82
|
FakeCollector.determine_port
|
83
83
|
end
|
84
84
|
|
85
|
+
@seen_port_failure = false
|
86
|
+
|
85
87
|
def run(port=nil)
|
86
88
|
port ||= determine_port
|
87
89
|
return if @thread && @thread.alive?
|
88
90
|
serve_on_port(port) do
|
89
91
|
@thread = Thread.new do
|
92
|
+
begin
|
90
93
|
::Rack::Handler::WEBrick.run(self,
|
91
94
|
:Port => port,
|
92
95
|
:Logger => WEBrick::Log.new("/dev/null"),
|
93
96
|
:AccessLog => [nil, nil])
|
97
|
+
rescue Errno::EADDRINUSE => ex
|
98
|
+
msg = "Port #{port} for FakeCollector was in use"
|
99
|
+
if !@seen_port_failure
|
100
|
+
# This is slow, so only do it the first collision we detect
|
101
|
+
lsof = `lsof | grep #{port}`
|
102
|
+
msg = msg + "\n#{lsof}"
|
103
|
+
@seen_port_failure = true
|
104
|
+
end
|
105
|
+
|
106
|
+
raise Errno::EADDRINUSE.new(msg)
|
107
|
+
end
|
94
108
|
end
|
95
109
|
@thread.abort_on_exception = true
|
96
110
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newrelic_rpm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.5.6.
|
4
|
+
version: 3.5.6.46.beta
|
5
5
|
prerelease: 9
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-01-
|
15
|
+
date: 2013-01-22 00:00:00.000000000 Z
|
16
16
|
dependencies: []
|
17
17
|
description: ! 'New Relic is a performance management system, developed by New Relic,
|
18
18
|
|