newrelic_rpm 3.9.4.245 → 3.9.5.251

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +57 -0
  3. data/Guardfile +1 -0
  4. data/lib/new_relic/agent/agent.rb +3 -3
  5. data/lib/new_relic/agent/audit_logger.rb +5 -2
  6. data/lib/new_relic/agent/configuration/default_source.rb +11 -5
  7. data/lib/new_relic/agent/error_collector.rb +14 -1
  8. data/lib/new_relic/agent/hostname.rb +22 -1
  9. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +8 -2
  10. data/lib/new_relic/agent/instrumentation/queue_time.rb +9 -6
  11. data/lib/new_relic/agent/method_tracer.rb +51 -172
  12. data/lib/new_relic/agent/method_tracer_helpers.rb +90 -0
  13. data/lib/new_relic/agent/new_relic_service.rb +33 -11
  14. data/lib/new_relic/agent/new_relic_service/encoders.rb +9 -5
  15. data/lib/new_relic/agent/request_sampler.rb +20 -12
  16. data/lib/new_relic/agent/rules_engine.rb +31 -78
  17. data/lib/new_relic/agent/rules_engine/replacement_rule.rb +76 -0
  18. data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +48 -0
  19. data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
  20. data/lib/new_relic/agent/sql_sampler.rb +39 -10
  21. data/lib/new_relic/agent/stats_engine/metric_stats.rb +1 -0
  22. data/lib/new_relic/agent/stats_engine/stats_hash.rb +7 -13
  23. data/lib/new_relic/agent/system_info.rb +96 -10
  24. data/lib/new_relic/agent/threading/agent_thread.rb +4 -1
  25. data/lib/new_relic/agent/threading/backtrace_node.rb +67 -57
  26. data/lib/new_relic/agent/threading/thread_profile.rb +30 -15
  27. data/lib/new_relic/agent/transaction.rb +11 -4
  28. data/lib/new_relic/environment_report.rb +21 -20
  29. data/lib/new_relic/version.rb +1 -1
  30. data/test/agent_helper.rb +12 -0
  31. data/test/fixtures/cross_agent_tests/README.md +1 -0
  32. data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_1core_1logical.txt +3 -0
  33. data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_1core_2logical.txt +14 -0
  34. data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_2core_2logical.txt +14 -0
  35. data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_4core_4logical.txt +28 -0
  36. data/test/fixtures/{proc_cpuinfo.txt → cross_agent_tests/proc_cpuinfo/2pack_12core_24logical.txt} +0 -0
  37. data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_20core_40logical.txt +999 -0
  38. data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_2core_2logical.txt +51 -0
  39. data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_2core_4logical.txt +28 -0
  40. data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_4core_4logical.txt +28 -0
  41. data/test/fixtures/cross_agent_tests/proc_cpuinfo/4pack_4core_4logical.txt +103 -0
  42. data/test/fixtures/cross_agent_tests/proc_cpuinfo/8pack_8core_8logical.txt +199 -0
  43. data/test/fixtures/cross_agent_tests/proc_cpuinfo/README.md +24 -0
  44. data/test/fixtures/cross_agent_tests/proc_cpuinfo/Xpack_Xcore_2logical.txt +43 -0
  45. data/test/fixtures/cross_agent_tests/transaction_segment_terms.json +101 -0
  46. data/test/multiverse/lib/multiverse/suite.rb +1 -1
  47. data/test/multiverse/suites/agent_only/agent_run_id_handling_test.rb +40 -0
  48. data/test/multiverse/suites/agent_only/labels_test.rb +9 -14
  49. data/test/multiverse/suites/agent_only/marshaling_test.rb +4 -6
  50. data/test/multiverse/suites/agent_only/rename_rule_test.rb +41 -4
  51. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +11 -3
  52. data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +8 -8
  53. data/test/multiverse/suites/rack/example_app.rb +20 -0
  54. data/test/multiverse/suites/rack/http_response_code_test.rb +51 -0
  55. data/test/multiverse/suites/sidekiq/Envfile +13 -6
  56. data/test/multiverse/suites/sidekiq/sidekiq_server.rb +4 -3
  57. data/test/new_relic/agent/audit_logger_test.rb +27 -0
  58. data/test/new_relic/agent/error_collector_test.rb +26 -5
  59. data/test/new_relic/agent/hostname_test.rb +66 -14
  60. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +8 -12
  61. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +7 -45
  62. data/test/new_relic/agent/method_tracer_test.rb +52 -1
  63. data/test/new_relic/agent/new_relic_service_test.rb +76 -0
  64. data/test/new_relic/agent/request_sampler_test.rb +7 -0
  65. data/test/new_relic/agent/rules_engine_test.rb +87 -56
  66. data/test/new_relic/agent/sql_sampler_test.rb +50 -14
  67. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +2 -2
  68. data/test/new_relic/agent/stats_engine/samplers_test.rb +1 -1
  69. data/test/new_relic/agent/{stats_hash_test.rb → stats_engine/stats_hash_test.rb} +1 -38
  70. data/test/new_relic/agent/system_info_test.rb +45 -0
  71. data/test/new_relic/agent/threading/agent_thread_test.rb +30 -0
  72. data/test/new_relic/agent/threading/backtrace_node_test.rb +27 -44
  73. data/test/new_relic/agent/threading/thread_profile_test.rb +35 -14
  74. data/test/new_relic/agent/transaction_test.rb +13 -10
  75. data/test/new_relic/environment_report_test.rb +7 -6
  76. data/test/new_relic/fake_collector.rb +10 -6
  77. data/test/new_relic/multiverse_helpers.rb +4 -11
  78. data/test/new_relic/rack/agent_hooks_test.rb +1 -1
  79. data/test/performance/lib/performance/baseline_compare_reporter.rb +24 -7
  80. data/test/performance/lib/performance/result.rb +3 -1
  81. data/test/performance/lib/performance/runner.rb +10 -0
  82. data/test/performance/lib/performance/timer.rb +6 -10
  83. data/test/performance/script/runner +18 -1
  84. data/test/performance/suites/queue_time.rb +21 -0
  85. data/test/performance/suites/stats_hash.rb +34 -0
  86. data/test/performance/suites/thread_profiling.rb +26 -0
  87. metadata +25 -4
  88. metadata.gz.sig +0 -0
@@ -88,6 +88,36 @@ module NewRelic::Agent::Threading
88
88
  assert called
89
89
  end
90
90
 
91
+ def test_standard_error_is_caught
92
+ expects_logging(:error, includes("exited"), any_parameters)
93
+
94
+ t = AgentThread.create("fail") { raise "O_o" }
95
+ t.join
96
+
97
+ assert_thread_completed(t)
98
+ end
99
+
100
+ def test_exception_is_reraised
101
+ expects_logging(:error, includes("exited"), any_parameters)
102
+
103
+ assert_raises(Exception) do
104
+ begin
105
+ t = AgentThread.create("fail") { raise Exception.new }
106
+ t.join
107
+ ensure
108
+ assert_thread_died_from_exception(t)
109
+ end
110
+ end
111
+ end
112
+
113
+ def assert_thread_completed(t)
114
+ assert_equal false, t.status
115
+ end
116
+
117
+ def assert_thread_died_from_exception(t)
118
+ assert_equal nil, t.status
119
+ end
120
+
91
121
  TRACE = [
92
122
  "/Users/jclark/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/eventmachine-0.12.10/lib/eventmachine.rb:100:in `catch'",
93
123
  "/Users/jclark/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/newrelic_rpm-3.5.3.452.dev/lib/new_relic/agent/agent.rb:200:in `start_worker_thread'",
@@ -10,7 +10,7 @@ module NewRelic::Agent::Threading
10
10
  SINGLE_LINE = "irb.rb:69:in `catch'"
11
11
 
12
12
  def setup
13
- @node = BacktraceNode.new(nil)
13
+ @node = BacktraceRoot.new
14
14
  @single_trace = [
15
15
  "irb.rb:69:in `catch'",
16
16
  "irb.rb:69:in `start'",
@@ -36,22 +36,29 @@ module NewRelic::Agent::Threading
36
36
  node
37
37
  end
38
38
 
39
+ def convert_nodes_to_array(nodes)
40
+ nodes.each {|n| n.mark_for_array_conversion }
41
+ nodes.each {|n| n.complete_array_conversion }
42
+ end
43
+
39
44
  def test_single_node_converts_to_array
40
45
  line = "irb.rb:69:in `catch'"
41
46
  node = BacktraceNode.new(line)
47
+ convert_nodes_to_array([node])
42
48
 
43
49
  assert_equal([
44
50
  ["irb.rb", "catch", 69],
45
51
  0, 0,
46
52
  []],
47
- node.to_array)
53
+ node.as_array)
48
54
  end
49
55
 
50
56
  def test_multiple_nodes_converts_to_array
51
57
  line = "irb.rb:69:in `catch'"
52
58
  child_line = "bacon.rb:42:in `yum'"
53
59
  node = create_node(line)
54
- create_node(child_line, node)
60
+ child_node = create_node(child_line, node)
61
+ convert_nodes_to_array([node, child_node])
55
62
 
56
63
  assert_equal([
57
64
  ["irb.rb", "catch", 69],
@@ -63,19 +70,20 @@ module NewRelic::Agent::Threading
63
70
  []
64
71
  ]
65
72
  ]],
66
- node.to_array)
73
+ node.as_array)
67
74
  end
68
75
 
69
76
  def test_gracefully_handle_bad_values_in_to_array
70
77
  node = BacktraceNode.new(SINGLE_LINE)
71
78
  node.stubs(:parse_backtrace_frame).returns(["irb.rb", "catch", "blarg"])
72
79
  node.runnable_count = Rational(10, 1)
80
+ convert_nodes_to_array([node])
73
81
 
74
82
  assert_equal([
75
83
  ["irb.rb", "catch", 0],
76
84
  10, 0,
77
85
  []],
78
- node.to_array)
86
+ node.as_array)
79
87
  end
80
88
 
81
89
  def test_add_child_twice
@@ -88,44 +96,10 @@ module NewRelic::Agent::Threading
88
96
  assert_equal 1, parent.children.size
89
97
  end
90
98
 
91
- def test_prune_keeps_children
92
- parent = create_node(SINGLE_LINE)
93
- child = create_node(SINGLE_LINE, parent)
94
-
95
- parent.prune!([])
96
-
97
- assert_equal [child], parent.children
98
- end
99
-
100
- def test_prune_removes_children
101
- parent = create_node(SINGLE_LINE)
102
- child = create_node(SINGLE_LINE, parent)
103
-
104
- parent.prune!([child])
105
-
106
- assert_equal [], parent.children
107
- end
108
-
109
- def test_prune_removes_grandchildren
110
- parent = create_node(SINGLE_LINE)
111
- child = create_node(SINGLE_LINE, parent)
112
- grandchild = create_node(SINGLE_LINE, child)
113
-
114
- parent.prune!([grandchild])
115
-
116
- assert_equal [child], parent.children
117
- assert_equal [], child.children
118
- end
119
-
120
- def test_aggregate_empty_trace
121
- @node.aggregate([])
122
- assert @node.empty?
123
- end
124
-
125
99
  def test_aggregate_builds_tree_from_first_trace
126
100
  @node.aggregate(@single_trace)
127
101
 
128
- root = BacktraceNode.new(nil)
102
+ root = BacktraceRoot.new
129
103
  tree = create_node(@single_trace[-1], root, 1)
130
104
  child = create_node(@single_trace[-2], tree, 1)
131
105
  create_node(@single_trace[-3], child, 1)
@@ -137,7 +111,7 @@ module NewRelic::Agent::Threading
137
111
  @node.aggregate(@single_trace)
138
112
  @node.aggregate(@single_trace)
139
113
 
140
- root = BacktraceNode.new(nil)
114
+ root = BacktraceRoot.new
141
115
  tree = create_node(@single_trace[-1], root, 2)
142
116
  child = create_node(@single_trace[-2], tree, 2)
143
117
  create_node(@single_trace[-3], child, 2)
@@ -161,7 +135,7 @@ module NewRelic::Agent::Threading
161
135
  @node.aggregate(backtrace1)
162
136
  @node.aggregate(backtrace2)
163
137
 
164
- root = BacktraceNode.new(nil)
138
+ root = BacktraceRoot.new
165
139
 
166
140
  tree = create_node(backtrace1.last, root, 2)
167
141
 
@@ -178,12 +152,21 @@ module NewRelic::Agent::Threading
178
152
  @node.aggregate(@single_trace)
179
153
  @node.aggregate(@single_trace)
180
154
 
181
- root = BacktraceNode.new(nil)
155
+ root = BacktraceRoot.new
182
156
  tree = create_node(@single_trace[-1], root, 2)
183
157
  child = create_node(@single_trace[-2], tree, 2)
184
158
  create_node(@single_trace[-3], child, 2)
185
159
 
186
160
  assert_backtrace_trees_equal(root, @node)
187
- end
161
+ end
162
+
163
+ def test_aggregate_limits_recorded_depth
164
+ deep_backtrace = (0..2000).to_a.map { |i| "foo.rb:#{i}:in `foo'" }
165
+
166
+ root = BacktraceRoot.new
167
+ root.aggregate(deep_backtrace)
168
+
169
+ assert_equal(MAX_THREAD_PROFILE_DEPTH, root.flattened.size)
170
+ end
188
171
  end
189
172
  end
@@ -41,33 +41,30 @@ if NewRelic::Agent::Threading::BacktraceService.is_supported?
41
41
  def test_prune_tree
42
42
  @profile.aggregate(@single_trace, :request, Thread.current)
43
43
 
44
- @profile.truncate_to_node_count!(1)
44
+ @profile.convert_N_trace_nodes_to_arrays(1)
45
45
 
46
- assert_equal 0, @profile.traces[:request].children.first.children.size
46
+ assert_equal 1, count_backtrace_nodes(@profile.traces[:request])
47
47
  end
48
48
 
49
49
  def test_prune_keeps_highest_counts
50
50
  @profile.aggregate(@single_trace, :request, Thread.current)
51
- @profile.aggregate(@single_trace, :other, Thread.current)
52
- @profile.aggregate(@single_trace, :other, Thread.current)
51
+ @profile.aggregate(@single_trace, :other , Thread.current)
52
+ @profile.aggregate(@single_trace, :other , Thread.current)
53
53
 
54
- @profile.truncate_to_node_count!(1)
54
+ @profile.convert_N_trace_nodes_to_arrays(1)
55
55
 
56
- assert_empty @profile.traces[:request]
57
- assert_equal 1, @profile.traces[:other].children.size
58
- assert_equal [], @profile.traces[:other].children.first.children
56
+ assert_equal 0, count_backtrace_nodes(@profile.traces[:request])
57
+ assert_equal 1, count_backtrace_nodes(@profile.traces[:other ])
59
58
  end
60
59
 
61
60
  def test_prune_keeps_highest_count_then_depths
62
61
  @profile.aggregate(@single_trace, :request, Thread.current)
63
- @profile.aggregate(@single_trace, :other, Thread.current)
62
+ @profile.aggregate(@single_trace, :other , Thread.current)
64
63
 
65
- @profile.truncate_to_node_count!(2)
64
+ @profile.convert_N_trace_nodes_to_arrays(2)
66
65
 
67
- assert_equal 1, @profile.traces[:request].children.size
68
- assert_equal 1, @profile.traces[:other].children.size
69
- assert_equal [], @profile.traces[:request].children.first.children
70
- assert_equal [], @profile.traces[:other].children.first.children
66
+ assert_equal 1, count_backtrace_nodes(@profile.traces[:request])
67
+ assert_equal 1, count_backtrace_nodes(@profile.traces[:other ])
71
68
  end
72
69
 
73
70
  def build_well_known_trace(args={})
@@ -245,6 +242,30 @@ if NewRelic::Agent::Threading::BacktraceService.is_supported?
245
242
  def encoder
246
243
  NewRelic::Agent::NewRelicService::JsonMarshaller.new.default_encoder
247
244
  end
245
+
246
+ def count_backtrace_nodes(bt_node)
247
+ trees = bt_node.as_array
248
+
249
+ count = 0
250
+
251
+ trees.each do |tree|
252
+ count += rec_count_tree_nodes(tree)
253
+ end
254
+
255
+ count
256
+ end
257
+
258
+ def rec_count_tree_nodes(tree)
259
+ count = 1 # 1 for this node
260
+
261
+ children = tree[3]
262
+
263
+ children.each do |child|
264
+ count += rec_count_tree_nodes(child)
265
+ end
266
+
267
+ count
268
+ end
248
269
  end
249
270
 
250
271
  end
@@ -253,17 +253,20 @@ class NewRelic::Agent::TransactionTest < Minitest::Test
253
253
  end
254
254
 
255
255
  def test_end_applies_transaction_name_rules
256
- in_transaction('Controller/foo/1/bar/22') do |txn|
257
- rule = NewRelic::Agent::RulesEngine::Rule.new('match_expression' => '[0-9]+',
258
- 'replacement' => '*',
259
- 'replace_all' => true)
260
- NewRelic::Agent.instance.transaction_rules << rule
261
- NewRelic::Agent::Transaction.tl_current.freeze_name_and_execute_if_not_ignored
262
- assert_equal 'Controller/foo/*/bar/*', txn.best_name
256
+ rules = [
257
+ {
258
+ 'match_expression' => '[0-9]+',
259
+ 'replacement' => '*',
260
+ 'replace_all' => true
261
+ }
262
+ ]
263
+
264
+ with_transaction_renaming_rules(rules) do
265
+ in_transaction('Controller/foo/1/bar/22') do |txn|
266
+ NewRelic::Agent::Transaction.tl_current.freeze_name_and_execute_if_not_ignored
267
+ assert_equal 'Controller/foo/*/bar/*', txn.best_name
268
+ end
263
269
  end
264
- ensure
265
- NewRelic::Agent.instance.instance_variable_set(:@transaction_rules,
266
- NewRelic::Agent::RulesEngine.new)
267
270
  end
268
271
 
269
272
  def test_end_fires_a_transaction_finished_event
@@ -61,13 +61,13 @@ class EnvironmentReportTest < Minitest::Test
61
61
 
62
62
  def test_gathers_system_info
63
63
  NewRelic::Agent::SystemInfo.stubs({
64
- :processor_count => 8,
65
- :processor_arch => 'x86_64',
66
- :os_version => 'WiggleOS 1.1.1',
67
- :ruby_os_identifier => 'wiggleos'
64
+ :num_logical_processors => 8,
65
+ :processor_arch => 'x86_64',
66
+ :os_version => 'WiggleOS 1.1.1',
67
+ :ruby_os_identifier => 'wiggleos'
68
68
  })
69
69
  report = ::NewRelic::EnvironmentReport.new
70
- assert_equal(8, report['Processors'])
70
+ assert_equal(8, report['Logical Processors'])
71
71
  assert_equal('x86_64', report['Arch'])
72
72
  assert_equal('WiggleOS 1.1.1', report['OS version'])
73
73
  assert_equal('wiggleos', report['OS'])
@@ -83,7 +83,8 @@ class EnvironmentReportTest < Minitest::Test
83
83
  "Ruby patchlevel",
84
84
  'JRuby version',
85
85
  'Java VM version',
86
- 'Processors',
86
+ 'Logical Processors',
87
+ 'Physical Cores',
87
88
  'Database adapter',
88
89
  'Framework',
89
90
  'Dispatcher',
@@ -142,10 +142,13 @@ module NewRelic
142
142
  puts body
143
143
  end
144
144
 
145
+ query_params = req.GET
146
+
145
147
  @agent_data << AgentPost.create(:action => method,
146
148
  :body => body,
147
149
  :run_id => run_id,
148
- :format => format)
150
+ :format => format,
151
+ :query_params => query_params)
149
152
  end
150
153
  res.finish
151
154
  end
@@ -172,12 +175,13 @@ module NewRelic
172
175
  end
173
176
 
174
177
  class AgentPost
175
- attr_accessor :action, :body, :run_id, :format
178
+ attr_accessor :action, :body, :run_id, :format, :query_params
176
179
  def initialize(opts={})
177
- @action = opts[:action]
178
- @body = opts[:body]
179
- @run_id = opts[:run_id]
180
- @format = opts[:format]
180
+ @action = opts[:action]
181
+ @body = opts[:body]
182
+ @run_id = opts[:run_id]
183
+ @format = opts[:format]
184
+ @query_params = opts[:query_params]
181
185
  end
182
186
 
183
187
  def self.create(opts={})
@@ -33,14 +33,13 @@ module MultiverseHelpers
33
33
 
34
34
  def setup_agent(opts = {}, &block)
35
35
  setup_collector
36
- make_sure_agent_reconnects(opts)
37
36
 
38
37
  # Give caller a shot to setup before we start
39
38
  # Don't just yield, as that won't necessary have the intended receiver
40
39
  # (the test case instance itself)
41
40
  self.instance_exec($collector, &block) if block_given? && self.respond_to?(:instance_exec)
42
41
 
43
- NewRelic::Agent.manual_start(opts)
42
+ trigger_agent_reconnect(opts)
44
43
  end
45
44
 
46
45
  def teardown_agent
@@ -76,7 +75,7 @@ module MultiverseHelpers
76
75
  teardown_agent
77
76
  end
78
77
 
79
- def make_sure_agent_reconnects(opts)
78
+ def trigger_agent_reconnect(opts={})
80
79
  # Clean-up if others don't (or we're first test after auto-loading of agent)
81
80
  if NewRelic::Agent.instance.started?
82
81
  NewRelic::Agent.shutdown
@@ -87,15 +86,9 @@ module MultiverseHelpers
87
86
  NewRelic::Agent.instance.instance_variable_set(:@connect_state, :pending)
88
87
 
89
88
  # Almost always want a test to force a new connect when setting up
90
- default_options(opts,
91
- :sync_startup => true,
92
- :force_reconnect => true)
93
- end
89
+ defaults = { :sync_startup => true, :force_reconnect => true }
94
90
 
95
- def default_options(options, defaults={})
96
- defaults.each do |(k, v)|
97
- options.merge!({k => v}) unless options.key?(k)
98
- end
91
+ NewRelic::Agent.manual_start(defaults.merge(opts))
99
92
  end
100
93
 
101
94
  #
@@ -23,7 +23,7 @@ class AgentHooksTest < Minitest::Test
23
23
  end
24
24
 
25
25
  def test_after_call
26
- result = stub
26
+ result = [stub, stub, stub]
27
27
  @app.stubs(:call).returns(result)
28
28
 
29
29
  NewRelic::Agent.instance.events.expects(:notify).with(:start_transaction)
@@ -58,22 +58,39 @@ module Performance
58
58
  delta = new_result.elapsed - old_result.elapsed
59
59
  percent_delta = delta / old_result.elapsed * 100.0
60
60
 
61
+ allocations_before = old_result.measurements[:allocations]
62
+ allocations_after = new_result.measurements[:allocations]
63
+ if allocations_before && allocations_after
64
+ allocations_delta = allocations_after - allocations_before
65
+ allocations_delta_percent = allocations_delta.to_f / allocations_before * 100
66
+ else
67
+ allocations_delta_percent = 0
68
+ end
69
+
61
70
  rows << [
62
71
  identifier,
63
72
  old_result.elapsed,
64
73
  new_result.elapsed,
65
- percent_delta
74
+ percent_delta,
75
+ allocations_before,
76
+ allocations_after,
77
+ allocations_delta_percent
66
78
  ]
67
79
  end
68
80
 
81
+ format_percent_delta = Proc.new { |v|
82
+ prefix = v > 0 ? "+" : ""
83
+ sprintf("#{prefix}%.1f%%", v)
84
+ }
85
+
69
86
  table = Table.new(rows) do
70
87
  column :name
71
- column :before, "%.2f s"
72
- column :after, "%.2f s"
73
- column :delta do |v|
74
- prefix = v > 0 ? "+" : ''
75
- sprintf("#{prefix}%.1f%%", v)
76
- end
88
+ column :before, "%.2f s"
89
+ column :after, "%.2f s"
90
+ column :delta, &format_percent_delta
91
+ column :allocs_before
92
+ column :allocs_after
93
+ column :allocs_delta, &format_percent_delta
77
94
  end
78
95
 
79
96
  puts table.render