newrelic_rpm 3.14.1.311 → 3.14.2.312

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +174 -11
  3. data/CHANGELOG +22 -0
  4. data/Rakefile +5 -0
  5. data/lib/new_relic/agent/agent.rb +22 -7
  6. data/lib/new_relic/agent/aws_info.rb +1 -1
  7. data/lib/new_relic/agent/custom_event_aggregator.rb +19 -44
  8. data/lib/new_relic/agent/error_event_aggregator.rb +11 -103
  9. data/lib/new_relic/agent/event_aggregator.rb +130 -0
  10. data/lib/new_relic/agent/event_buffer.rb +7 -0
  11. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +18 -2
  12. data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +12 -4
  13. data/lib/new_relic/agent/new_relic_service.rb +6 -4
  14. data/lib/new_relic/agent/sampled_buffer.rb +9 -6
  15. data/lib/new_relic/agent/stats_engine/metric_stats.rb +1 -2
  16. data/lib/new_relic/agent/stats_engine/stats_hash.rb +2 -1
  17. data/lib/new_relic/agent/supported_versions.rb +1 -1
  18. data/lib/new_relic/agent/synthetics_event_aggregator.rb +52 -0
  19. data/lib/new_relic/agent/synthetics_event_buffer.rb +0 -2
  20. data/lib/new_relic/agent/transaction.rb +14 -7
  21. data/lib/new_relic/agent/transaction/request_attributes.rb +7 -2
  22. data/lib/new_relic/agent/transaction_error_primitive.rb +72 -0
  23. data/lib/new_relic/agent/transaction_event_aggregator.rb +33 -210
  24. data/lib/new_relic/agent/transaction_event_primitive.rb +106 -0
  25. data/lib/new_relic/agent/transaction_event_recorder.rb +48 -0
  26. data/lib/new_relic/agent/transaction_metrics.rb +9 -1
  27. data/lib/new_relic/agent/transction_event_recorder.rb +35 -0
  28. data/lib/new_relic/recipes/capistrano3.rb +1 -1
  29. data/lib/new_relic/version.rb +1 -1
  30. data/lib/tasks/versions.html.erb +13 -11
  31. data/lib/tasks/versions.postface.html +8 -0
  32. data/lib/tasks/versions.preface.html +3 -0
  33. data/lib/tasks/versions.rake +15 -5
  34. data/test/agent_helper.rb +1 -1
  35. data/test/environments/rails31/Gemfile +2 -0
  36. data/test/environments/rails32/Gemfile +2 -0
  37. data/test/environments/rails32/Rakefile +2 -1
  38. data/test/environments/rails32/config/database.yml +1 -6
  39. data/test/multiverse/suites/active_record/Envfile +1 -0
  40. data/test/multiverse/suites/agent_only/agent_attributes_test.rb +18 -0
  41. data/test/multiverse/suites/agent_only/custom_analytics_events_test.rb +21 -6
  42. data/test/multiverse/suites/agent_only/error_events_test.rb +14 -6
  43. data/test/multiverse/suites/agent_only/transaction_events_test.rb +31 -0
  44. data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +2 -0
  45. data/test/multiverse/suites/capistrano/Envfile +9 -3
  46. data/test/multiverse/suites/capistrano2/Envfile +4 -0
  47. data/test/multiverse/suites/config_file_loading/Envfile +1 -1
  48. data/test/multiverse/suites/curb/Envfile +1 -1
  49. data/test/multiverse/suites/datamapper/Envfile +3 -0
  50. data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +7 -3
  51. data/test/multiverse/suites/grape/grape_test.rb +2 -0
  52. data/test/multiverse/suites/padrino/Envfile +4 -3
  53. data/test/multiverse/suites/padrino/config/newrelic.yml +2 -0
  54. data/test/multiverse/suites/rack/config/newrelic.yml +18 -0
  55. data/test/multiverse/suites/rack/nested_non_rack_app_test.rb +1 -1
  56. data/test/multiverse/suites/rack/puma_rack_builder_test.rb +17 -14
  57. data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +16 -13
  58. data/test/multiverse/suites/rack/rack_unsupported_version_test.rb +1 -1
  59. data/test/multiverse/suites/rails/Envfile +5 -0
  60. data/test/multiverse/suites/rails/parameter_capture_test.rb +9 -0
  61. data/test/multiverse/suites/rake/Envfile +2 -1
  62. data/test/multiverse/suites/redis/redis_instrumentation_test.rb +1 -1
  63. data/test/multiverse/suites/sidekiq/Envfile +18 -0
  64. data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +11 -10
  65. data/test/multiverse/suites/sidekiq/test_model.rb +12 -0
  66. data/test/multiverse/suites/sinatra/ignoring_test.rb +43 -25
  67. data/test/multiverse/suites/sinatra/nested_middleware_test.rb +10 -2
  68. data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +4 -0
  69. data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +8 -2
  70. data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +4 -0
  71. data/test/multiverse/suites/sinatra/sinatra_parameter_capture_test.rb +2 -0
  72. data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +79 -10
  73. data/test/new_relic/agent/agent_test.rb +3 -3
  74. data/test/new_relic/agent/aws_info_test.rb +1 -2
  75. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +2 -0
  76. data/test/new_relic/agent/custom_event_aggregator_test.rb +43 -4
  77. data/test/new_relic/agent/error_collector_test.rb +1 -1
  78. data/test/new_relic/agent/error_event_aggregator_test.rb +13 -81
  79. data/test/new_relic/agent/event_aggregator_test.rb +178 -0
  80. data/test/new_relic/agent/event_buffer_test_cases.rb +16 -0
  81. data/test/new_relic/agent/instrumentation/sinatra/transaction_namer_test.rb +7 -0
  82. data/test/new_relic/agent/new_relic_service_test.rb +7 -1
  83. data/test/new_relic/agent/pipe_channel_manager_test.rb +45 -3
  84. data/test/new_relic/agent/rpm_agent_test.rb +1 -0
  85. data/test/new_relic/agent/stats_engine/stats_hash_test.rb +2 -2
  86. data/test/new_relic/agent/synthetics_event_aggregator_test.rb +179 -0
  87. data/test/new_relic/agent/transaction/request_attributes_test.rb +8 -0
  88. data/test/new_relic/agent/transaction_error_primitive_test.rb +117 -0
  89. data/test/new_relic/agent/transaction_event_aggregator_test.rb +148 -374
  90. data/test/new_relic/agent/transaction_event_primitive_test.rb +195 -0
  91. data/test/new_relic/agent/transaction_event_recorder_test.rb +80 -0
  92. data/test/new_relic/agent/transaction_metrics_test.rb +7 -7
  93. data/test/new_relic/agent/transaction_test.rb +4 -4
  94. data/test/new_relic/agent/utilization_data_test.rb +7 -7
  95. data/test/new_relic/fake_collector.rb +10 -17
  96. data/test/new_relic/license_test.rb +2 -0
  97. data/test/new_relic/marshalling_test_cases.rb +1 -1
  98. data/test/nullverse/default_source_require_test.rb +21 -0
  99. data/test/nullverse/nullverse_helper.rb +10 -0
  100. data/test/performance/suites/active_record.rb +1 -1
  101. data/test/performance/suites/sql_obfuscation.rb +7 -6
  102. data/test/script/ci.sh +10 -165
  103. data/test/script/install_mongodb.sh +6 -0
  104. metadata +21 -6
  105. data/test/script/build_test_gem.sh +0 -57
  106. data/test/script/ci_agent-tests_runner.sh +0 -82
  107. data/test/script/ci_bench.sh +0 -52
  108. data/test/script/ci_multiverse_runner.sh +0 -63
@@ -0,0 +1,130 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ require 'new_relic/agent/sampled_buffer'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ class EventAggregator
10
+ class << self
11
+ def named named = nil
12
+ named ? @named = named.to_s.freeze : @named
13
+ end
14
+
15
+ def capacity_key key = nil
16
+ key ? @capacity_key = key : @capacity_key
17
+ end
18
+
19
+ def enabled_key key = nil
20
+ key ? @enabled_key = key : @enabled_key
21
+ end
22
+
23
+ def buffer_class klass = nil
24
+ if klass
25
+ @buffer_class = klass
26
+ else
27
+ @buffer_class ||= SampledBuffer
28
+ end
29
+ end
30
+ end
31
+
32
+ def initialize
33
+ @lock = Mutex.new
34
+ @buffer = self.class.buffer_class.new NewRelic::Agent.config[self.class.capacity_key]
35
+ @enabled = false
36
+ @notified_full = false
37
+ register_capacity_callback
38
+ register_enabled_callback
39
+ after_initialize
40
+ end
41
+
42
+ # interface method for subclasses to override to provide post-initialization setup
43
+ def after_initialize
44
+ end
45
+
46
+ # interface method for subclasses to override to provide post harvest functionality
47
+ def after_harvest metadata
48
+ end
49
+
50
+ def enabled?
51
+ @enabled
52
+ end
53
+
54
+ def has_metadata?
55
+ true
56
+ end
57
+
58
+ def harvest!
59
+ metadata = nil
60
+ samples = []
61
+ @lock.synchronize do
62
+ samples.concat @buffer.to_a
63
+ metadata = @buffer.metadata
64
+ reset_buffer!
65
+ end
66
+ after_harvest metadata
67
+ [reservoir_metadata(metadata), samples]
68
+ end
69
+
70
+ # Merges samples from payload back into buffer and optionally adjusts the count of
71
+ # the buffer to ensure accuracy of buffer of metadata. We want to make sure not to
72
+ # double count samples being merged back in from a failed harvest, yet we do not
73
+ # want to under-count samples being merged from the PipeService.
74
+ def merge! payload, adjust_count = true
75
+ @lock.synchronize do
76
+ _, samples = payload
77
+
78
+ if adjust_count
79
+ @buffer.decrement_lifetime_counts_by samples.count
80
+ end
81
+
82
+ samples.each { |s| @buffer.append s }
83
+ end
84
+ end
85
+
86
+ def reset!
87
+ @lock.synchronize do
88
+ reset_buffer!
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def reservoir_metadata metadata
95
+ {
96
+ :reservoir_size => metadata[:capacity],
97
+ :events_seen => metadata[:seen]
98
+ }
99
+ end
100
+
101
+ def register_capacity_callback
102
+ NewRelic::Agent.config.register_callback(self.class.capacity_key) do |max_samples|
103
+ NewRelic::Agent.logger.debug "#{self.class.named} max_samples set to #{max_samples}"
104
+ @lock.synchronize do
105
+ @buffer.capacity = max_samples
106
+ end
107
+ end
108
+ end
109
+
110
+ def register_enabled_callback
111
+ NewRelic::Agent.config.register_callback(self.class.enabled_key) do |enabled|
112
+ # intentionally unsynchronized for liveness
113
+ @enabled = enabled
114
+ ::NewRelic::Agent.logger.debug "#{self.class.named} will #{enabled ? '' : 'not '}be sent to the New Relic service."
115
+ end
116
+ end
117
+
118
+ def notify_if_full
119
+ return unless !@notified_full && @buffer.full?
120
+ NewRelic::Agent.logger.debug "#{self.class.named} capacity of #{@buffer.capacity} reached, beginning sampling"
121
+ @notified_full = true
122
+ end
123
+
124
+ def reset_buffer!
125
+ @buffer.reset!
126
+ @notified_full = false
127
+ end
128
+ end
129
+ end
130
+ end
@@ -78,6 +78,13 @@ module NewRelic
78
78
  @items.dup
79
79
  end
80
80
 
81
+ def metadata
82
+ {
83
+ :capacity => @capacity,
84
+ :captured => @items.size,
85
+ :seen => @seen
86
+ }
87
+ end
81
88
  end
82
89
  end
83
90
  end
@@ -67,6 +67,23 @@ module NewRelic
67
67
  end
68
68
  end
69
69
 
70
+ # the trailing unless is for the benefit for Ruby 1.8.7 and can be removed
71
+ # when it is deprecated.
72
+ CONTENT_LENGTH = 'Content-Length'.freeze unless defined?(CONTENT_LENGTH)
73
+
74
+ def capture_response_content_length(state, result)
75
+ if result.is_a?(Array) && state.current_transaction
76
+ _, headers, _ = result
77
+ state.current_transaction.response_content_length = headers[CONTENT_LENGTH]
78
+ end
79
+ end
80
+
81
+ def capture_response_attributes(state, result)
82
+ capture_http_response_code(state, result)
83
+ capture_response_content_type(state, result)
84
+ capture_response_content_length(state, result)
85
+ end
86
+
70
87
  def call(env)
71
88
  first_middleware = note_transaction_started(env)
72
89
 
@@ -79,8 +96,7 @@ module NewRelic
79
96
  result = (target == self) ? traced_call(env) : target.call(env)
80
97
 
81
98
  if first_middleware
82
- capture_http_response_code(state, result)
83
- capture_response_content_type(state, result)
99
+ capture_response_attributes(state, result)
84
100
  events.notify(:after_call, env, result)
85
101
  end
86
102
 
@@ -9,22 +9,30 @@ module NewRelic
9
9
  module TransactionNamer
10
10
  extend self
11
11
 
12
- def transaction_name_for_route(env, request)
13
- name = route_for_sinatra(env)
14
- name = route_name_for_padrino(request) if name.nil?
12
+ SINATRA_ROUTE = 'sinatra.route'
15
13
 
16
- transaction_name(name, request) unless name.nil?
14
+ def transaction_name_for_route(env, request)
15
+ if env.key? SINATRA_ROUTE
16
+ env[SINATRA_ROUTE]
17
+ else
18
+ name = route_for_sinatra(env)
19
+ name = route_name_for_padrino(request) if name.nil?
20
+ transaction_name(name, request) unless name.nil?
21
+ end
17
22
  end
18
23
 
19
24
  def initial_transaction_name(request)
20
25
  transaction_name(::NewRelic::Agent::UNKNOWN_METRIC, request)
21
26
  end
22
27
 
28
+ ROOT = '/'.freeze
29
+
23
30
  def transaction_name(route_text, request)
24
31
  verb = http_verb(request)
25
32
 
26
33
  route_text = route_text.source if route_text.is_a?(Regexp)
27
34
  name = route_text.gsub(%r{^[/^\\A]*(.*?)[/\$\?\\z]*$}, '\1')
35
+ name = ROOT if name.empty?
28
36
  name = "#{verb} #{name}" unless verb.nil?
29
37
  name
30
38
  rescue => e
@@ -170,13 +170,15 @@ module NewRelic
170
170
  end
171
171
 
172
172
  def analytic_event_data(data)
173
- invoke_remote(:analytic_event_data, [@agent_id, data],
174
- :item_count => data.size)
173
+ _, items = data
174
+ invoke_remote(:analytic_event_data, [@agent_id, *data],
175
+ :item_count => items.size)
175
176
  end
176
177
 
177
178
  def custom_event_data(data)
178
- invoke_remote(:custom_event_data, [@agent_id, data],
179
- :item_count => data.size)
179
+ _, items = data
180
+ invoke_remote(:custom_event_data, [@agent_id, *data],
181
+ :item_count => items.size)
180
182
  end
181
183
 
182
184
  def error_event_data(data)
@@ -20,14 +20,9 @@ module NewRelic
20
20
  @seen_lifetime = 0
21
21
  end
22
22
 
23
- def reset!
24
- @captured_lifetime += @items.size
25
- @seen_lifetime += @seen
26
- super
27
- end
28
-
29
23
  def append(x = nil, &blk)
30
24
  @seen += 1
25
+ @seen_lifetime += 1
31
26
  append_event(x, &blk)
32
27
  end
33
28
 
@@ -37,6 +32,7 @@ module NewRelic
37
32
  if @items.size < @capacity
38
33
  x = blk.call if block_given?
39
34
  @items << x
35
+ @captured_lifetime += 1
40
36
  return x
41
37
  else
42
38
  m = rand(@seen) # [0, @seen)
@@ -59,6 +55,13 @@ module NewRelic
59
55
  def sample_rate_lifetime
60
56
  @captured_lifetime > 0 ? (@captured_lifetime.to_f / @seen_lifetime) : 0.0
61
57
  end
58
+
59
+ def metadata
60
+ super.merge!(
61
+ :captured_lifetime => @captured_lifetime,
62
+ :seen_lifetime => @seen_lifetime
63
+ )
64
+ end
62
65
  end
63
66
  end
64
67
  end
@@ -93,8 +93,7 @@ module NewRelic
93
93
  def record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics=nil, value=nil, aux=nil, &blk)
94
94
  txn = state.current_transaction
95
95
  if txn
96
- txn.metrics.record_scoped(scoped_metric, value, aux, &blk)
97
- txn.metrics.record_unscoped(scoped_metric, value, aux, &blk)
96
+ txn.metrics.record_scoped_and_unscoped(scoped_metric, value, aux, &blk)
98
97
  if summary_metrics
99
98
  txn.metrics.record_unscoped(summary_metrics, value, aux, &blk)
100
99
  end
@@ -153,6 +153,7 @@ module NewRelic
153
153
  txn_metrics.each_scoped do |name, stats|
154
154
  spec = NewRelic::MetricSpec.new(name, scope)
155
155
  merge_or_insert(@scoped, spec, stats)
156
+ merge_or_insert(@unscoped, name, stats)
156
157
  end
157
158
  end
158
159
 
@@ -160,7 +161,7 @@ module NewRelic
160
161
  if target.has_key?(name)
161
162
  target[name].merge!(stats)
162
163
  else
163
- target[name] = stats
164
+ target[name] = stats.dup
164
165
  end
165
166
  end
166
167
  end
@@ -180,7 +180,7 @@ module NewRelic
180
180
  :sidekiq =>
181
181
  {
182
182
  :type => :background,
183
- :supported => ["~>2.8"],
183
+ :supported => ["~>2.8", "~>3.4.2", "~>4.0"],
184
184
  :url => "https://rubygems.org/gems/sidekiq",
185
185
  :feed => "https://rubygems.org/gems/sidekiq/versions.atom"
186
186
  },
@@ -0,0 +1,52 @@
1
+ # -*- ruby -*-
2
+ # encoding: utf-8
3
+ # This file is distributed under New Relic's license terms.
4
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
5
+
6
+ require 'new_relic/agent/event_aggregator'
7
+ require 'new_relic/agent/synthetics_event_buffer'
8
+
9
+ module NewRelic
10
+ module Agent
11
+ class SyntheticsEventAggregator < EventAggregator
12
+
13
+ named :SyntheticsEventAggregator
14
+ capacity_key :'synthetics.events_limit'
15
+ enabled_key :'analytics_events.enabled'
16
+ buffer_class SyntheticsEventBuffer
17
+
18
+ def append_or_reject event
19
+ return unless enabled?
20
+
21
+ @lock.synchronize do
22
+ @buffer.append_with_reject event
23
+ end
24
+ end
25
+
26
+ # slightly different semantics than the EventAggregator for merge
27
+ def merge! payload
28
+ _, events = payload
29
+ @lock.synchronize do
30
+ events.each { |e| @buffer.append_with_reject e}
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def after_harvest metadata
37
+ record_dropped_synthetics metadata
38
+ end
39
+
40
+ def record_dropped_synthetics metadata
41
+ num_dropped = metadata[:seen] - metadata[:captured]
42
+ return unless num_dropped > 0
43
+
44
+ NewRelic::Agent.logger.debug("Synthetics transaction event limit (#{metadata[:capacity]}) reached. Further synthetics events this harvest period dropped.")
45
+
46
+ engine = NewRelic::Agent.instance.stats_engine
47
+ engine.tl_record_supportability_metric_count("SyntheticsEventAggregator/synthetics_events_dropped", num_dropped)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -2,7 +2,6 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
 
5
- require 'new_relic/agent/event_buffer'
6
5
  require 'new_relic/agent/sized_buffer'
7
6
 
8
7
  module NewRelic
@@ -35,7 +34,6 @@ module NewRelic
35
34
  main_event, _ = event
36
35
  main_event[TIMESTAMP]
37
36
  end
38
-
39
37
  end
40
38
  end
41
39
  end
@@ -53,6 +53,7 @@ module NewRelic
53
53
  :jruby_cpu_start,
54
54
  :process_cpu_start,
55
55
  :http_response_code,
56
+ :response_content_length,
56
57
  :response_content_type
57
58
 
58
59
  attr_reader :guid,
@@ -283,8 +284,6 @@ module NewRelic
283
284
  @ignore_enduser = false
284
285
  @ignore_trace = false
285
286
 
286
- @error_recorded = false
287
-
288
287
  @attributes = Attributes.new(NewRelic::Agent.instance.attribute_filter)
289
288
 
290
289
  merge_request_parameters(@filtered_params)
@@ -524,9 +523,11 @@ module NewRelic
524
523
  record_queue_time
525
524
 
526
525
  generate_payload(state, start_time, end_time)
526
+
527
527
  record_exceptions
528
- merge_metrics
528
+ record_transaction_event
529
529
 
530
+ merge_metrics
530
531
  send_transaction_finished_event
531
532
  end
532
533
 
@@ -539,6 +540,10 @@ module NewRelic
539
540
  add_agent_attribute(:httpResponseCode, http_response_code.to_s, default_destinations)
540
541
  end
541
542
 
543
+ if response_content_length
544
+ add_agent_attribute(:'response.headers.contentLength', response_content_length.to_i, default_destinations)
545
+ end
546
+
542
547
  if response_content_type
543
548
  add_agent_attribute(:'response.headers.contentType', response_content_type, default_destinations)
544
549
  end
@@ -602,7 +607,7 @@ module NewRelic
602
607
  :duration => duration,
603
608
  :metrics => @metrics,
604
609
  :attributes => @attributes,
605
- :error => error_recorded?
610
+ :error => false
606
611
  }
607
612
  append_cat_info(state, duration, @payload)
608
613
  append_apdex_perf_zone(duration, @payload)
@@ -730,14 +735,16 @@ module NewRelic
730
735
  end
731
736
 
732
737
  def record_exceptions
738
+ error_recorded = false
733
739
  @exceptions.each do |exception, options|
734
740
  options[:uri] ||= request_path if request_path
735
741
  options[:port] = request_port if request_port
736
742
  options[:metric] = best_name
737
743
  options[:attributes] = @attributes
738
744
 
739
- @error_recorded = !!agent.error_collector.notice_error(exception, options) || @error_recorded
745
+ error_recorded = !!agent.error_collector.notice_error(exception, options) || error_recorded
740
746
  end
747
+ payload[:error] = error_recorded if payload
741
748
  end
742
749
 
743
750
  # Do not call this. Invoke the class method instead.
@@ -749,8 +756,8 @@ module NewRelic
749
756
  end
750
757
  end
751
758
 
752
- def error_recorded?
753
- @error_recorded
759
+ def record_transaction_event
760
+ agent.transaction_event_recorder.record payload
754
761
  end
755
762
 
756
763
  QUEUE_TIME_METRIC = 'WebFrontend/QueueTime'.freeze