newrelic_rpm 2.9.9 → 2.10.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of newrelic_rpm might be problematic. Click here for more details.
- data/CHANGELOG +117 -49
- data/bin/mongrel_rpm +2 -2
- data/install.rb +42 -33
- data/lib/new_relic/agent.rb +149 -39
- data/lib/new_relic/agent/agent.rb +139 -122
- data/lib/new_relic/agent/busy_calculator.rb +91 -0
- data/lib/new_relic/agent/collection_helper.rb +11 -2
- data/lib/new_relic/agent/error_collector.rb +33 -27
- data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +30 -26
- data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +316 -105
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
- data/lib/new_relic/agent/instrumentation/memcache.rb +18 -12
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +2 -1
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +258 -0
- data/lib/new_relic/agent/instrumentation/net.rb +7 -11
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rack.rb +109 -0
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -5
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +7 -7
- data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
- data/lib/new_relic/agent/method_tracer.rb +305 -150
- data/lib/new_relic/agent/sampler.rb +34 -0
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +11 -1
- data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
- data/lib/new_relic/agent/samplers/memory_sampler.rb +22 -10
- data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
- data/lib/new_relic/agent/shim_agent.rb +10 -0
- data/lib/new_relic/agent/stats_engine.rb +16 -278
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
- data/lib/new_relic/agent/stats_engine/samplers.rb +81 -0
- data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
- data/lib/new_relic/agent/transaction_sampler.rb +73 -67
- data/lib/new_relic/agent/worker_loop.rb +69 -68
- data/lib/new_relic/commands/deployments.rb +4 -6
- data/lib/new_relic/control.rb +121 -60
- data/lib/new_relic/control/external.rb +13 -0
- data/lib/new_relic/control/merb.rb +2 -0
- data/lib/new_relic/control/rails.rb +16 -6
- data/lib/new_relic/control/ruby.rb +8 -5
- data/lib/new_relic/control/sinatra.rb +18 -0
- data/lib/new_relic/delayed_job_injection.rb +25 -0
- data/lib/new_relic/histogram.rb +89 -0
- data/lib/new_relic/local_environment.rb +64 -30
- data/lib/new_relic/metric_data.rb +15 -6
- data/lib/new_relic/metric_parser.rb +14 -1
- data/lib/new_relic/metric_parser/active_record.rb +14 -0
- data/lib/new_relic/metric_parser/controller.rb +5 -2
- data/lib/new_relic/metric_parser/external.rb +50 -0
- data/lib/new_relic/metric_parser/other_transaction.rb +15 -0
- data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
- data/lib/new_relic/metric_spec.rb +39 -20
- data/lib/new_relic/metrics.rb +9 -7
- data/lib/new_relic/noticed_error.rb +6 -8
- data/lib/new_relic/rack/metric_app.rb +5 -4
- data/lib/new_relic/rack/{newrelic.ru → mongrel_rpm.ru} +4 -4
- data/lib/new_relic/rack/newrelic.yml +1 -0
- data/lib/new_relic/{rack.rb → rack_app.rb} +0 -0
- data/lib/new_relic/recipes.rb +1 -1
- data/lib/new_relic/stats.rb +40 -26
- data/lib/new_relic/transaction_analysis.rb +5 -2
- data/lib/new_relic/transaction_sample.rb +134 -55
- data/lib/new_relic/version.rb +27 -20
- data/lib/new_relic_api.rb +67 -47
- data/lib/newrelic_rpm.rb +5 -5
- data/lib/tasks/tests.rake +2 -0
- data/newrelic.yml +69 -29
- data/test/active_record_fixtures.rb +2 -2
- data/test/config/newrelic.yml +4 -7
- data/test/config/test_control.rb +1 -2
- data/test/new_relic/agent/active_record_instrumentation_test.rb +115 -31
- data/test/new_relic/agent/agent_controller_test.rb +274 -0
- data/test/new_relic/agent/agent_test_controller.rb +42 -6
- data/test/new_relic/agent/busy_calculator_test.rb +79 -0
- data/test/new_relic/agent/collection_helper_test.rb +10 -3
- data/test/new_relic/agent/error_collector_test.rb +35 -17
- data/test/new_relic/agent/method_tracer_test.rb +60 -20
- data/test/new_relic/agent/metric_data_test.rb +2 -2
- data/test/new_relic/agent/metric_frame_test.rb +51 -0
- data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
- data/test/new_relic/agent/{agent_test.rb → rpm_agent_test.rb} +26 -5
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
- data/test/new_relic/{samplers_test.rb → agent/stats_engine/samplers_test.rb} +23 -22
- data/test/new_relic/agent/{stats_engine_test.rb → stats_engine/stats_engine_test.rb} +19 -101
- data/test/new_relic/agent/task_instrumentation_test.rb +176 -0
- data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -2
- data/test/new_relic/agent/transaction_sample_test.rb +53 -38
- data/test/new_relic/agent/transaction_sampler_test.rb +101 -33
- data/test/new_relic/agent/worker_loop_test.rb +16 -14
- data/test/new_relic/control_test.rb +26 -13
- data/test/new_relic/metric_parser_test.rb +31 -1
- data/test/new_relic/metric_spec_test.rb +2 -2
- data/test/new_relic/stats_test.rb +0 -8
- data/test/new_relic/version_number_test.rb +31 -1
- data/test/test_helper.rb +37 -1
- data/ui/controllers/newrelic_controller.rb +19 -11
- data/ui/helpers/google_pie_chart.rb +5 -11
- data/ui/helpers/newrelic_helper.rb +40 -35
- data/ui/views/layouts/newrelic_default.rhtml +7 -7
- data/ui/views/newrelic/_sample.rhtml +5 -1
- data/ui/views/newrelic/images/new-relic-rpm-desktop.gif +0 -0
- data/ui/views/newrelic/images/textmate.png +0 -0
- data/ui/views/newrelic/index.rhtml +13 -1
- data/ui/views/newrelic/show_sample.rhtml +5 -2
- data/ui/views/newrelic/stylesheets/style.css +54 -3
- metadata +65 -145
- data/Manifest +0 -143
- data/Rakefile +0 -22
- data/init.rb +0 -38
- data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +0 -127
- data/lib/new_relic/agent/instrumentation/error_instrumentation.rb +0 -14
- data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +0 -13
- data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +0 -38
- data/lib/new_relic/agent/patch_const_missing.rb +0 -125
- data/lib/new_relic/agent/samplers/mongrel_sampler.rb +0 -22
- data/lib/new_relic/metric_parser/database.rb +0 -23
- data/newrelic_rpm.gemspec +0 -35
- data/test/new_relic/agent/classloader_patch_test.rb +0 -56
- data/test/new_relic/agent/controller_test.rb +0 -107
- data/test/new_relic/agent/dispatcher_instrumentation_test.rb +0 -70
@@ -8,14 +8,37 @@ class NewRelic::ControlTest < Test::Unit::TestCase
|
|
8
8
|
NewRelic::Agent.manual_start
|
9
9
|
@c = NewRelic::Control.instance
|
10
10
|
end
|
11
|
+
def shutdown
|
12
|
+
NewRelic::Agent.shutdown
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_monitor_mode
|
16
|
+
assert ! @c.monitor_mode?
|
17
|
+
@c.settings.delete 'enabled'
|
18
|
+
@c.settings.delete 'monitor_mode'
|
19
|
+
assert !@c.monitor_mode?
|
20
|
+
@c['enabled'] = false
|
21
|
+
assert ! @c.monitor_mode?
|
22
|
+
@c['enabled'] = true
|
23
|
+
assert @c.monitor_mode?
|
24
|
+
@c['monitor_mode'] = nil
|
25
|
+
assert !@c.monitor_mode?
|
26
|
+
@c['monitor_mode'] = false
|
27
|
+
assert !@c.monitor_mode?
|
28
|
+
@c['monitor_mode'] = true
|
29
|
+
assert @c.monitor_mode?
|
30
|
+
ensure
|
31
|
+
@c['enabled'] = false
|
32
|
+
@c['monitor_mode'] = false
|
33
|
+
end
|
11
34
|
|
12
35
|
def test_test_config
|
13
36
|
assert_equal :rails, c.app
|
14
37
|
assert_equal :test, c.framework
|
15
38
|
assert_match /test/i, c.dispatcher_instance_id
|
16
39
|
assert_equal nil, c.dispatcher
|
17
|
-
|
18
|
-
assert_equal false, c['
|
40
|
+
assert !c['enabled']
|
41
|
+
assert_equal false, c['monitor_mode']
|
19
42
|
c.local_env
|
20
43
|
end
|
21
44
|
|
@@ -26,8 +49,6 @@ class NewRelic::ControlTest < Test::Unit::TestCase
|
|
26
49
|
|
27
50
|
def test_info
|
28
51
|
props = NewRelic::Control.instance.local_env.snapshot
|
29
|
-
list = props.assoc('Plugin List').last.sort
|
30
|
-
assert_not_nil list # can't really guess what might be in here.
|
31
52
|
assert_match /jdbc|postgres|mysql|sqlite/, props.assoc('Database adapter').last
|
32
53
|
end
|
33
54
|
|
@@ -51,7 +72,7 @@ class NewRelic::ControlTest < Test::Unit::TestCase
|
|
51
72
|
assert_equal c['sval'], 'sure'
|
52
73
|
end
|
53
74
|
def test_config_apdex
|
54
|
-
assert_equal 1.1, c
|
75
|
+
assert_equal 1.1, c.apdex_t
|
55
76
|
end
|
56
77
|
def test_transaction_threshold
|
57
78
|
assert_equal 'Apdex_f', c['transaction_tracer']['transaction_threshold']
|
@@ -60,14 +81,6 @@ class NewRelic::ControlTest < Test::Unit::TestCase
|
|
60
81
|
def test_log_file_name
|
61
82
|
assert_match /newrelic_agent.log$/, c.instance_variable_get('@log_file')
|
62
83
|
end
|
63
|
-
def test_environment_info
|
64
|
-
NewRelic::Control.instance.send :append_environment_info
|
65
|
-
snapshot = NewRelic::Control.instance.local_env.snapshot
|
66
|
-
assert snapshot.assoc('Plugin List').last.include?('newrelic_rpm'), snapshot.inspect
|
67
|
-
end
|
68
|
-
def test_config_apdex
|
69
|
-
assert_equal 1.1, c['apdex_t']
|
70
|
-
end
|
71
84
|
|
72
85
|
def test_transaction_threshold__apdex
|
73
86
|
forced_start
|
@@ -47,7 +47,7 @@ class MetricParserTest < Test::Unit::TestCase
|
|
47
47
|
assert !m.is_web_service?
|
48
48
|
|
49
49
|
assert_not_nil m.base_metric_name
|
50
|
-
|
50
|
+
assert_equal 0, m.base_metric_name.index('Controller/')
|
51
51
|
end
|
52
52
|
|
53
53
|
end
|
@@ -139,4 +139,34 @@ class MetricParserTest < Test::Unit::TestCase
|
|
139
139
|
m = NewRelic::MetricParser.for_metric_named("Errors/Type/MyType")
|
140
140
|
assert_equal m.short_name, 'MyType'
|
141
141
|
end
|
142
|
+
def test_external
|
143
|
+
m = NewRelic::MetricParser.for_metric_named("External/all")
|
144
|
+
assert m.all?
|
145
|
+
assert !m.hosts_all?
|
146
|
+
assert_equal "All External", m.developer_name
|
147
|
+
assert_equal "calls to external systems", m.tooltip_name
|
148
|
+
assert_equal "External Services", m.legend_name
|
149
|
+
assert_nil m.operation
|
150
|
+
assert_nil m.library
|
151
|
+
|
152
|
+
m = NewRelic::MetricParser.for_metric_named("External/venus/all")
|
153
|
+
assert !m.all?
|
154
|
+
assert m.hosts_all?
|
155
|
+
assert_equal "venus", m.developer_name
|
156
|
+
assert_equal "calls to venus", m.tooltip_name
|
157
|
+
assert_equal "All venus calls", m.legend_name
|
158
|
+
assert_nil m.operation
|
159
|
+
assert_equal 'all', m.library
|
160
|
+
|
161
|
+
m = NewRelic::MetricParser.for_metric_named("External/venus/Net::Http/get")
|
162
|
+
assert !m.all?
|
163
|
+
assert !m.hosts_all?
|
164
|
+
assert_equal "Net::Http[venus]: get", m.developer_name
|
165
|
+
assert_equal "calls to Net::Http[venus]: get", m.tooltip_name
|
166
|
+
assert_equal "Net::Http[venus]: get", m.legend_name
|
167
|
+
assert_equal 'get', m.operation
|
168
|
+
assert_equal 'Net::Http', m.library
|
169
|
+
|
170
|
+
|
171
|
+
end
|
142
172
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__),'..', 'test_helper'))
|
2
2
|
##require "new_relic/stats"
|
3
|
-
class NewRelic::
|
3
|
+
class NewRelic::MetricSpecTest < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def test_simple
|
6
6
|
stats = NewRelic::MethodTraceStats.new
|
@@ -20,7 +20,7 @@ class NewRelic::StatsTest < Test::Unit::TestCase
|
|
20
20
|
|
21
21
|
assert spec1.eql?(NewRelic::MetricSpec.new('Controller'))
|
22
22
|
assert spec2.eql?(NewRelic::MetricSpec.new('Controller', nil))
|
23
|
-
assert
|
23
|
+
assert spec1.eql?(spec2)
|
24
24
|
assert !spec2.eql?(NewRelic::MetricSpec.new('Controller', '/dude'))
|
25
25
|
end
|
26
26
|
|
@@ -93,14 +93,6 @@ class NewRelic::StatsTest < Test::Unit::TestCase
|
|
93
93
|
assert_equal(s1.calls_per_minute, 2)
|
94
94
|
end
|
95
95
|
|
96
|
-
def test_calls_per_second
|
97
|
-
s1 = NewRelic::TestObjectForStats.new
|
98
|
-
s1.call_count = 90
|
99
|
-
s1.begin_time = Time.at(0)
|
100
|
-
s1.end_time = Time.at(30)
|
101
|
-
assert_equal(s1.calls_per_second, 3)
|
102
|
-
end
|
103
|
-
|
104
96
|
def test_total_call_time_per_minute
|
105
97
|
s1 = NewRelic::TestObjectForStats.new
|
106
98
|
s1.begin_time = Time.at(0)
|
@@ -19,15 +19,33 @@ class NewRelic::VersionNumberTest < Test::Unit::TestCase
|
|
19
19
|
assert v1 > v3
|
20
20
|
assert v3 < v0
|
21
21
|
end
|
22
|
+
def test_bug
|
23
|
+
v0 = NewRelic::VersionNumber.new '2.8.999'
|
24
|
+
v1 = NewRelic::VersionNumber.new '2.9.10'
|
25
|
+
assert v1 > v0
|
26
|
+
assert v0 <= v1
|
27
|
+
end
|
22
28
|
def test_long_version
|
23
29
|
v0 = NewRelic::VersionNumber.new '1.2.3.4'
|
24
30
|
v1 = NewRelic::VersionNumber.new '1.2.3.3'
|
25
31
|
v3 = NewRelic::VersionNumber.new '1.3'
|
26
32
|
assert v0 > v1
|
33
|
+
assert v0 < '1.2.3.5'
|
34
|
+
assert ! (v0 < '1.2.3.4')
|
27
35
|
assert v3 > v0
|
28
36
|
end
|
29
37
|
def test_sort
|
30
|
-
values = %w[1.1.1
|
38
|
+
values = %w[1.1.1
|
39
|
+
1.1.99
|
40
|
+
1.1.999
|
41
|
+
2.0.6
|
42
|
+
2.6.5
|
43
|
+
2.7
|
44
|
+
2.7.1
|
45
|
+
2.7.2
|
46
|
+
2.7.2.0
|
47
|
+
3
|
48
|
+
999]
|
31
49
|
assert_equal values, values.map{|v| NewRelic::VersionNumber.new v}.sort.map(&:to_s)
|
32
50
|
end
|
33
51
|
def test_compare_string
|
@@ -39,6 +57,18 @@ class NewRelic::VersionNumberTest < Test::Unit::TestCase
|
|
39
57
|
assert v3 < '1.2.0'
|
40
58
|
assert v0 == '1.2.0'
|
41
59
|
end
|
60
|
+
def test_4_numbers
|
61
|
+
v0 = NewRelic::VersionNumber.new '1.2.0'
|
62
|
+
v1 = NewRelic::VersionNumber.new '1.2.0.1'
|
63
|
+
v2 = NewRelic::VersionNumber.new '1.2.1.0'
|
64
|
+
v3 = NewRelic::VersionNumber.new '1.2.1.1'
|
65
|
+
assert v0 < v1
|
66
|
+
assert v1 < v2
|
67
|
+
assert v2 < v3
|
68
|
+
assert v0 < v3
|
69
|
+
assert v0 < '1.2.0.1'
|
70
|
+
assert v0 > '1.1.0.1'
|
71
|
+
end
|
42
72
|
def test_string
|
43
73
|
assert_equal '1.2.0', NewRelic::VersionNumber.new('1.2.0').to_s
|
44
74
|
assert_equal '1.2', NewRelic::VersionNumber.new('1.2').to_s
|
data/test/test_helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module NewRelic; TEST = true; end unless defined? NewRelic::TEST
|
2
|
-
|
2
|
+
#ENV['NEWRELIC_ENABLE'] = 'true'
|
3
|
+
ENV['RAILS_ENV'] = 'test'
|
3
4
|
NEWRELIC_PLUGIN_DIR = File.expand_path(File.join(File.dirname(__FILE__),".."))
|
4
5
|
$LOAD_PATH << File.join(NEWRELIC_PLUGIN_DIR,"test")
|
5
6
|
$LOAD_PATH << File.join(NEWRELIC_PLUGIN_DIR,"ui/helpers")
|
@@ -15,3 +16,38 @@ def assert_between(floor, ceiling, value, message = nil)
|
|
15
16
|
assert floor <= value && value <= ceiling,
|
16
17
|
message || "expected #{floor} <= #{value} <= #{ceiling}"
|
17
18
|
end
|
19
|
+
|
20
|
+
def compare_metrics expected_list, actual_list
|
21
|
+
actual = Set.new actual_list
|
22
|
+
actual.delete('GC/cumulative') # in case we are in REE
|
23
|
+
expected = Set.new expected_list
|
24
|
+
assert_equal expected.to_a.sort, actual.to_a.sort, "extra: #{(actual - expected).to_a.join(", ")}; missing: #{(expected - actual).to_a.join(", ")}"
|
25
|
+
end
|
26
|
+
=begin Enable this to see test names as they run
|
27
|
+
Test::Unit::TestCase.class_eval do
|
28
|
+
def run_with_info *args, &block
|
29
|
+
puts "#{self.class.name.underscore}/#{@method_name}"
|
30
|
+
run_without_info *args, &block
|
31
|
+
end
|
32
|
+
alias_method_chain :run, :info
|
33
|
+
end
|
34
|
+
=end
|
35
|
+
module TransactionSampleTestHelper
|
36
|
+
def make_sql_transaction(*sql)
|
37
|
+
sampler = NewRelic::Agent::TransactionSampler.new
|
38
|
+
sampler.notice_first_scope_push Time.now.to_f
|
39
|
+
sampler.notice_transaction '/path', nil, :jim => "cool"
|
40
|
+
sampler.notice_push_scope "a"
|
41
|
+
|
42
|
+
sampler.notice_transaction '/path/2', nil, :jim => "cool"
|
43
|
+
|
44
|
+
sql.each {|sql_statement| sampler.notice_sql(sql_statement, {:adapter => "test"}, 0 ) }
|
45
|
+
|
46
|
+
sleep 1.0
|
47
|
+
yield if block_given?
|
48
|
+
sampler.notice_pop_scope "a"
|
49
|
+
sampler.notice_scope_empty
|
50
|
+
|
51
|
+
sampler.samples[0]
|
52
|
+
end
|
53
|
+
end
|
@@ -40,20 +40,28 @@ class NewrelicController < ActionController::Base
|
|
40
40
|
|
41
41
|
write_inheritable_attribute('do_not_trace', true)
|
42
42
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
def image
|
48
|
-
forward_to_file '/newrelic/images/', params[:content_type]
|
43
|
+
def profile
|
44
|
+
NewRelic::Control.instance.profiling = params['start'] == 'true'
|
45
|
+
get_samples
|
46
|
+
redirect_to :action => 'index'
|
49
47
|
end
|
50
48
|
|
51
|
-
def
|
52
|
-
|
49
|
+
def file
|
50
|
+
file_name=params[:file].join
|
51
|
+
file_name=~/^.*[.]([^.]*)$/
|
52
|
+
ext=$1
|
53
|
+
case ext
|
54
|
+
when 'css' then
|
55
|
+
forward_to_file '/newrelic/stylesheets/', 'text/css'
|
56
|
+
when 'gif','jpg','png' then
|
57
|
+
forward_to_file '/newrelic/images/', "image/#{ext}"
|
58
|
+
when 'js' then
|
59
|
+
forward_to_file '/newrelic/javascript/', 'text/javascript'
|
60
|
+
else
|
61
|
+
raise "Unknown type '#{ext}' (#{file_name})"
|
62
|
+
end
|
53
63
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
64
|
+
|
57
65
|
def index
|
58
66
|
get_samples
|
59
67
|
end
|
@@ -7,7 +7,6 @@ class GooglePieChart
|
|
7
7
|
def initialize
|
8
8
|
# an array of [label, value]
|
9
9
|
@data = []
|
10
|
-
|
11
10
|
self.width = 300
|
12
11
|
self.height = 200
|
13
12
|
end
|
@@ -20,18 +19,13 @@ class GooglePieChart
|
|
20
19
|
# render the chart to html by creating an image object and
|
21
20
|
# placing the correct URL to the google charts api
|
22
21
|
def render
|
23
|
-
labels =
|
24
|
-
values =
|
22
|
+
labels = []
|
23
|
+
values = []
|
25
24
|
@data.each do |label, value|
|
26
|
-
labels << CGI::escape(label)
|
27
|
-
values << (value * 100 / @max).round.to_s
|
25
|
+
labels << CGI::escape(label)
|
26
|
+
values << (value > 0 ? value * 100 / @max : value).round.to_s
|
28
27
|
end
|
29
|
-
|
30
|
-
# strip of the last separator char for labels and values
|
31
|
-
labels = labels[0..-2]
|
32
|
-
values = values[0..-2]
|
33
|
-
|
34
|
-
params = {:cht => 'p', :chs => "#{width}x#{height}", :chd => "t:#{values}", :chl => labels }
|
28
|
+
params = {:cht => 'p', :chs => "#{width}x#{height}", :chd => "t:#{values.join(',')}", :chl => labels.join('|') }
|
35
29
|
params['chco'] = color if color
|
36
30
|
|
37
31
|
url = "http://chart.apis.google.com/chart?#{to_query(params)}"
|
@@ -15,17 +15,13 @@ module NewrelicHelper
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def trace_row_display_limit_reached
|
18
|
-
|
18
|
+
(!@detail_segment_count.nil? && @detail_segment_count > trace_row_display_limit) || @sample.sql_segments.length > trace_row_display_limit
|
19
19
|
end
|
20
20
|
|
21
21
|
# return the sample but post processed to strip out segments that normally don't show
|
22
22
|
# up in production (after the first execution, at least) such as application code loading
|
23
23
|
def stripped_sample(sample = @sample)
|
24
|
-
|
25
|
-
sample.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)')
|
26
|
-
else
|
27
|
-
sample
|
28
|
-
end
|
24
|
+
sample.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)')
|
29
25
|
end
|
30
26
|
|
31
27
|
# return the highest level in the call stack for the trace that is not rails or
|
@@ -48,11 +44,11 @@ module NewrelicHelper
|
|
48
44
|
exclude_file_from_stack_trace?(file, include_rails)
|
49
45
|
end
|
50
46
|
end
|
51
|
-
|
47
|
+
|
52
48
|
def render_backtrace
|
53
49
|
if @segment[:backtrace]
|
54
50
|
content_tag('h3', 'Application Stack Trace') +
|
55
|
-
|
51
|
+
render(:partial => agent_views_path('stack_trace'), :locals => {:segment => @segment})
|
56
52
|
end
|
57
53
|
end
|
58
54
|
|
@@ -76,7 +72,7 @@ module NewrelicHelper
|
|
76
72
|
rescue
|
77
73
|
# catch all other exceptions. We're going to create an invalid link below, but that's okay.
|
78
74
|
end
|
79
|
-
|
75
|
+
|
80
76
|
if using_textmate?
|
81
77
|
"txmt://open?url=file://#{file}&line=#{line}"
|
82
78
|
else
|
@@ -109,10 +105,10 @@ module NewrelicHelper
|
|
109
105
|
def write_stack_trace_line(trace_line)
|
110
106
|
link_to h(trace_line), url_for_source(trace_line)
|
111
107
|
end
|
112
|
-
|
108
|
+
|
113
109
|
# write a link to the source for a trace
|
114
110
|
def link_to_source(trace)
|
115
|
-
image_url = url_for(:controller => :newrelic, :action => :
|
111
|
+
image_url = url_for(:controller => :newrelic, :action => :file, :file => (using_textmate? ? "textmate.png" : "file_icon.png"))
|
116
112
|
|
117
113
|
link_to image_tag(image_url, :alt => (title = 'View Source'), :title => title), url_for_source(application_caller(trace))
|
118
114
|
end
|
@@ -125,7 +121,7 @@ module NewrelicHelper
|
|
125
121
|
def format_timestamp(time)
|
126
122
|
time.strftime("%H:%M:%S")
|
127
123
|
end
|
128
|
-
|
124
|
+
|
129
125
|
def colorize(value, yellow_threshold = 0.05, red_threshold = 0.15, s=to_ms(value))
|
130
126
|
if value > yellow_threshold
|
131
127
|
color = (value > red_threshold ? 'red' : 'orange')
|
@@ -136,11 +132,11 @@ module NewrelicHelper
|
|
136
132
|
end
|
137
133
|
|
138
134
|
def expanded_image_path()
|
139
|
-
url_for(:controller => :newrelic, :action => :
|
135
|
+
url_for(:controller => :newrelic, :action => :file, :file => 'arrow-open.png')
|
140
136
|
end
|
141
137
|
|
142
138
|
def collapsed_image_path()
|
143
|
-
url_for(:controller => :newrelic, :action => :
|
139
|
+
url_for(:controller => :newrelic, :action => :file, :file => 'arrow-close.png')
|
144
140
|
end
|
145
141
|
|
146
142
|
def explain_sql_url(segment)
|
@@ -202,17 +198,17 @@ module NewrelicHelper
|
|
202
198
|
classes = []
|
203
199
|
|
204
200
|
classes << "segment#{segment.parent_segment.segment_id}" if depth > 1
|
205
|
-
|
206
|
-
classes << "view_segment" if segment.metric_name.
|
201
|
+
|
202
|
+
classes << "view_segment" if segment.metric_name.index('View') == 0
|
207
203
|
classes << "summary_segment" if segment.is_a?(NewRelic::TransactionSample::CompositeSegment)
|
208
|
-
|
204
|
+
|
209
205
|
classes.join(' ')
|
210
206
|
end
|
211
|
-
|
207
|
+
|
212
208
|
# render_segment_details should be called before calling this method
|
213
209
|
def render_indentation_classes(depth)
|
214
210
|
styles = []
|
215
|
-
|
211
|
+
(1..depth).each do |d|
|
216
212
|
styles << ".segment_indent_level#{d} { display: inline-block; margin-left: #{(d-1)*20}px }"
|
217
213
|
end
|
218
214
|
content_tag("style", styles.join(' '))
|
@@ -240,17 +236,16 @@ module NewrelicHelper
|
|
240
236
|
end
|
241
237
|
end
|
242
238
|
|
243
|
-
private
|
239
|
+
private
|
244
240
|
def file_and_line(stack_trace_line)
|
245
241
|
stack_trace_line.match(/(.*):(\d+)/)[1..2]
|
246
242
|
end
|
247
243
|
|
248
244
|
def using_textmate?
|
249
|
-
|
250
|
-
false
|
245
|
+
NewRelic::Control.instance.use_textmate?
|
251
246
|
end
|
252
247
|
|
253
|
-
|
248
|
+
|
254
249
|
def render_segment_details(segment, depth=0)
|
255
250
|
@detail_segment_count ||= 0
|
256
251
|
@detail_segment_count += 1
|
@@ -273,17 +268,20 @@ private
|
|
273
268
|
|
274
269
|
html
|
275
270
|
end
|
276
|
-
|
271
|
+
|
277
272
|
def exclude_file_from_stack_trace?(file, include_rails)
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
273
|
+
return false if include_rails
|
274
|
+
return true if file !~ /\.(rb|java)/
|
275
|
+
%w[/actionmailer/
|
276
|
+
/activerecord
|
277
|
+
/activeresource
|
278
|
+
/activesupport
|
279
|
+
/lib/mongrel
|
280
|
+
/actionpack
|
281
|
+
/passenger/
|
282
|
+
/railties
|
283
|
+
benchmark.rb].each { |s| return true if file.include? s }
|
284
|
+
false
|
287
285
|
end
|
288
286
|
|
289
287
|
def show_view_link(title, page_name)
|
@@ -297,14 +295,14 @@ private
|
|
297
295
|
when 'jpg'; 'image/jpg'
|
298
296
|
when 'css'; 'text/css'
|
299
297
|
when 'js'; 'text/javascript'
|
300
|
-
|
298
|
+
else 'text/plain'
|
301
299
|
end
|
302
300
|
end
|
303
301
|
def to_ms(number)
|
304
302
|
(number*1000).round
|
305
303
|
end
|
306
304
|
def to_percentage(value)
|
307
|
-
|
305
|
+
(value * 100).round if value
|
308
306
|
end
|
309
307
|
def with_delimiter(val)
|
310
308
|
return '0' if val.nil?
|
@@ -312,4 +310,11 @@ private
|
|
312
310
|
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
|
313
311
|
parts.join '.'
|
314
312
|
end
|
313
|
+
|
314
|
+
def profile_table(profile)
|
315
|
+
out = StringIO.new
|
316
|
+
printer = RubyProf::GraphHtmlPrinter.new(profile)
|
317
|
+
printer.print(out, :min_percent=>0.5)
|
318
|
+
out.string[/<body>(.*)<\/body>/im, 0].gsub('<table>', '<table class=profile>')
|
319
|
+
end
|
315
320
|
end
|