newrelic_rpm 6.1.0.352 → 6.6.0.358

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +34 -96
  4. data/CHANGELOG.md +139 -0
  5. data/lib/new_relic/agent/agent.rb +51 -134
  6. data/lib/new_relic/agent/commands/agent_command_router.rb +2 -21
  7. data/lib/new_relic/agent/configuration/default_source.rb +53 -41
  8. data/lib/new_relic/agent/configuration/environment_source.rb +4 -2
  9. data/lib/new_relic/agent/configuration/event_harvest_config.rb +39 -0
  10. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
  11. data/lib/new_relic/agent/configuration/manager.rb +13 -1
  12. data/lib/new_relic/agent/configuration/server_source.rb +34 -1
  13. data/lib/new_relic/agent/connect/request_builder.rb +69 -0
  14. data/lib/new_relic/agent/connect/response_handler.rb +61 -0
  15. data/lib/new_relic/agent/error_collector.rb +2 -2
  16. data/lib/new_relic/agent/error_event_aggregator.rb +2 -1
  17. data/lib/new_relic/agent/error_trace_aggregator.rb +1 -0
  18. data/lib/new_relic/agent/event_aggregator.rb +26 -32
  19. data/lib/new_relic/agent/hostname.rb +1 -1
  20. data/lib/new_relic/agent/inbound_request_monitor.rb +2 -2
  21. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +24 -42
  22. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +46 -74
  23. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +70 -53
  24. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +168 -0
  25. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +41 -48
  26. data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +4 -4
  27. data/lib/new_relic/agent/instrumentation/grape.rb +2 -3
  28. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +76 -0
  29. data/lib/new_relic/agent/instrumentation/{rails5 → rails_notifications}/action_cable.rb +5 -6
  30. data/lib/new_relic/agent/instrumentation/{rails5 → rails_notifications}/action_controller.rb +3 -3
  31. data/lib/new_relic/agent/instrumentation/{rails4 → rails_notifications}/action_view.rb +3 -3
  32. data/lib/new_relic/agent/javascript_instrumentor.rb +1 -1
  33. data/lib/new_relic/agent/new_relic_service.rb +0 -4
  34. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +0 -1
  35. data/lib/new_relic/agent/parameter_filtering.rb +18 -5
  36. data/lib/new_relic/agent/priority_sampled_buffer.rb +2 -0
  37. data/lib/new_relic/agent/span_event_aggregator.rb +2 -5
  38. data/lib/new_relic/agent/threading/backtrace_service.rb +3 -3
  39. data/lib/new_relic/agent/threading/thread_profile.rb +9 -23
  40. data/lib/new_relic/agent/transaction.rb +0 -2
  41. data/lib/new_relic/agent/transaction/trace.rb +3 -8
  42. data/lib/new_relic/agent/transaction/trace_builder.rb +0 -1
  43. data/lib/new_relic/agent/transaction_event_recorder.rb +3 -3
  44. data/lib/new_relic/agent/transaction_sampler.rb +1 -5
  45. data/lib/new_relic/agent/transaction_time_aggregator.rb +19 -4
  46. data/lib/new_relic/control/class_methods.rb +7 -1
  47. data/lib/new_relic/control/frameworks/{rails5.rb → rails_notifications.rb} +1 -1
  48. data/lib/new_relic/rack/browser_monitoring.rb +10 -8
  49. data/lib/new_relic/version.rb +1 -1
  50. data/lib/tasks/config.rake +1 -2
  51. data/newrelic_rpm.gemspec +2 -9
  52. data/test/agent_helper.rb +18 -5
  53. metadata +18 -51
  54. data/lib/new_relic/agent/commands/xray_session.rb +0 -55
  55. data/lib/new_relic/agent/commands/xray_session_collection.rb +0 -161
  56. data/lib/new_relic/agent/instrumentation/active_record_4.rb +0 -42
  57. data/lib/new_relic/agent/instrumentation/active_record_5.rb +0 -41
  58. data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +0 -104
  59. data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +0 -32
  60. data/lib/new_relic/agent/instrumentation/rails5/action_view.rb +0 -27
  61. data/lib/new_relic/agent/transaction/xray_sample_buffer.rb +0 -64
  62. data/lib/new_relic/control/frameworks/rails6.rb +0 -14
@@ -2,8 +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 'objspace'
6
-
7
5
  # This module powers the Busy calculation for the Capacity report in
8
6
  # APM (https://rpm.newrelic.com/accounts/.../applications/.../optimize/capacity_analysis).
9
7
  #
@@ -102,12 +100,27 @@ module NewRelic
102
100
  end
103
101
 
104
102
  def thread_is_alive?(thread_id)
105
- thread = ObjectSpace._id2ref(thread_id)
103
+ thread = thread_by_id thread_id
106
104
  thread && thread.alive?
107
105
  rescue StandardError
108
106
  false
109
107
  end
110
108
 
109
+ # ObjectSpace is faster on MRI, but disabled by default on JRuby for
110
+ # perfomance reasons. We have two implmentations of `thread_by_id`
111
+ # based on ruby implementation.
112
+ if RUBY_ENGINE == 'jruby'
113
+ def thread_by_id thread_id
114
+ Thread.list.detect { |t| t.object_id == thread_id }
115
+ end
116
+ else
117
+ require 'objspace'
118
+
119
+ def thread_by_id thread_id
120
+ ObjectSpace._id2ref(thread_id)
121
+ end
122
+ end
123
+
111
124
  def set_transaction_start_time(timestamp, thread_id = current_thread)
112
125
  @stats[thread_id].transaction_started_at = timestamp
113
126
  end
@@ -131,7 +144,9 @@ module NewRelic
131
144
  end
132
145
 
133
146
  def log_missing_elapsed_transaction_time
134
- transaction_name = Tracer.current_transaction.best_name
147
+ transaction_name = Tracer.current_transaction &&
148
+ Tracer.current_transaction.best_name ||
149
+ "unknown"
135
150
  NewRelic::Agent.logger.warn("Unable to calculate elapsed transaction time for #{transaction_name}")
136
151
  end
137
152
  end
@@ -49,13 +49,19 @@ module NewRelic
49
49
  # maybe it is already loaded by some external system
50
50
  # i.e. rpm_contrib or user extensions?
51
51
  end
52
- NewRelic::Control::Frameworks.const_get(framework.to_s.capitalize)
52
+ NewRelic::Control::Frameworks.const_get(camelize(framework.to_s))
53
53
  end
54
54
 
55
55
  # The root directory for the plugin or gem
56
56
  def newrelic_root
57
57
  File.expand_path(File.join("..", "..", "..", ".."), __FILE__)
58
58
  end
59
+
60
+ def camelize(snake_case_name)
61
+ snake_case_name.gsub(/(\_|^)[a-z]/) do |substring|
62
+ substring[-1].capitalize!
63
+ end
64
+ end
59
65
  end
60
66
  extend ClassMethods
61
67
  end
@@ -7,7 +7,7 @@ require 'new_relic/control/frameworks/rails4'
7
7
  module NewRelic
8
8
  class Control
9
9
  module Frameworks
10
- class Rails5 < NewRelic::Control::Frameworks::Rails4
10
+ class RailsNotifications < NewRelic::Control::Frameworks::Rails4
11
11
  end
12
12
  end
13
13
  end
@@ -29,15 +29,16 @@ module NewRelic::Rack
29
29
  GT = ">".freeze
30
30
 
31
31
  def traced_call(env)
32
- result = @app.call(env) # [status, headers, response]
32
+ result = @app.call(env)
33
+ (status, headers, response) = result
33
34
 
34
35
  js_to_inject = NewRelic::Agent.browser_timing_header
35
- if (js_to_inject != "") && should_instrument?(env, result[0], result[1])
36
- response_string = autoinstrument_source(result[2], result[1], js_to_inject)
36
+ if (js_to_inject != "") && should_instrument?(env, status, headers)
37
+ response_string = autoinstrument_source(response, headers, js_to_inject)
37
38
 
38
39
  env[ALREADY_INSTRUMENTED_KEY] = true
39
40
  if response_string
40
- response = Rack::Response.new(response_string, result[0], result[1])
41
+ response = Rack::Response.new(response_string, status, headers)
41
42
  response.finish
42
43
  else
43
44
  result
@@ -55,7 +56,7 @@ module NewRelic::Rack
55
56
  !env[ALREADY_INSTRUMENTED_KEY] &&
56
57
  is_html?(headers) &&
57
58
  !is_attachment?(headers) &&
58
- !is_streaming?(env)
59
+ !is_streaming?(env, headers)
59
60
  end
60
61
 
61
62
  def is_html?(headers)
@@ -66,10 +67,11 @@ module NewRelic::Rack
66
67
  headers[CONTENT_DISPOSITION] && headers[CONTENT_DISPOSITION].include?(ATTACHMENT)
67
68
  end
68
69
 
69
- def is_streaming?(env)
70
- return false unless defined?(ActionController::Live)
70
+ def is_streaming?(env, headers)
71
+ return true if headers && headers['Transfer-Encoding'] == 'chunked'
71
72
 
72
- env['action_controller.instance'].class.included_modules.include?(ActionController::Live)
73
+ defined?(ActionController::Live) &&
74
+ env['action_controller.instance'].class.included_modules.include?(ActionController::Live)
73
75
  end
74
76
 
75
77
  CHARSET_RE = /<\s*meta[^>]+charset\s*=[^>]*>/im.freeze
@@ -11,7 +11,7 @@ module NewRelic
11
11
  end
12
12
 
13
13
  MAJOR = 6
14
- MINOR = 1
14
+ MINOR = 6
15
15
  TINY = 0
16
16
 
17
17
  begin
@@ -17,8 +17,7 @@ namespace :newrelic do
17
17
  }
18
18
 
19
19
  NAME_OVERRIDES = {
20
- "slow_sql" => "Slow SQL",
21
- "xray_session" => "X-Ray Session"
20
+ "slow_sql" => "Slow SQL"
22
21
  }
23
22
 
24
23
  def output(format)
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.version = NewRelic::VERSION::STRING
11
11
  s.required_ruby_version = '>= 2.0.0'
12
12
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
13
- s.authors = [ "Matthew Wear", "Chris Pine", "Erin Dees", "Rachel Klein" ]
13
+ s.authors = [ "Matthew Wear", "Chris Pine", "Rachel Klein", "Justin Foote" ]
14
14
  s.date = Time.now.strftime('%Y-%m-%d')
15
15
  s.licenses = ['New Relic']
16
16
  s.description = <<-EOS
@@ -45,15 +45,8 @@ EOS
45
45
  s.add_development_dependency 'minitest', '~> 4.7.5'
46
46
  s.add_development_dependency 'mocha', '~> 0.13.0'
47
47
  s.add_development_dependency 'yard'
48
- s.add_development_dependency 'rails', '~> 3.2.13'
49
- s.add_development_dependency 'json', '>= 2.0.2' if RUBY_VERSION >= '2.4.0' # possible bundler issue?
50
48
  s.add_development_dependency 'pry-nav', '~> 0.2.4'
51
49
  s.add_development_dependency 'pry-stack_explorer', '~> 0.4.9'
52
50
  s.add_development_dependency 'hometown', '~> 0.2.5'
53
-
54
- if RUBY_PLATFORM == 'java'
55
- s.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
56
- else
57
- s.add_development_dependency 'sqlite3', '~> 1.3.13'
58
- end
51
+ s.add_development_dependency 'bundler', '< 2.0'
59
52
  end
@@ -452,6 +452,13 @@ def with_config(config_hash, at_start=true)
452
452
  end
453
453
  end
454
454
 
455
+ def with_server_source config_hash, at_start=true
456
+ with_config config_hash, at_start do
457
+ NewRelic::Agent.config.notify_server_source_added
458
+ yield
459
+ end
460
+ end
461
+
455
462
  def with_config_low_priority(config_hash)
456
463
  with_config(config_hash, false) do
457
464
  yield
@@ -521,7 +528,7 @@ def constant_path(name, opts={})
521
528
  path = [Object]
522
529
  parts = name.gsub(/^::/, '').split('::')
523
530
  parts.each do |part|
524
- if !path.last.const_defined?(part)
531
+ if !path.last.constants.include?(part.to_sym)
525
532
  return allow_partial ? path : nil
526
533
  end
527
534
  path << path.last.const_get(part)
@@ -529,11 +536,17 @@ def constant_path(name, opts={})
529
536
  path
530
537
  end
531
538
 
539
+ def get_parent(constant_name)
540
+ parent_name = constant_name.gsub(/::[^:]*$/, '')
541
+ const_path = constant_path(parent_name)
542
+ const_path ? const_path[-1] : nil
543
+ end
544
+
532
545
  def undefine_constant(constant_symbol)
533
- const_path = constant_path(constant_symbol.to_s)
534
- return yield unless const_path
535
- parent = const_path[-2]
536
- const_name = constant_symbol.to_s.gsub(/.*::/, '')
546
+ const_str = constant_symbol.to_s
547
+ parent = get_parent(const_str)
548
+ const_name = const_str.gsub(/.*::/, '')
549
+ return yield unless parent && parent.constants.include?(const_name.to_sym)
537
550
  removed_constant = parent.send(:remove_const, const_name)
538
551
  yield
539
552
  ensure
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_rpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0.352
4
+ version: 6.6.0.358
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Wear
8
8
  - Chris Pine
9
- - Erin Dees
10
9
  - Rachel Klein
10
+ - Justin Foote
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2019-02-21 00:00:00.000000000 Z
14
+ date: 2019-08-29 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rake
@@ -69,34 +69,6 @@ dependencies:
69
69
  - - ">="
70
70
  - !ruby/object:Gem::Version
71
71
  version: '0'
72
- - !ruby/object:Gem::Dependency
73
- name: rails
74
- requirement: !ruby/object:Gem::Requirement
75
- requirements:
76
- - - "~>"
77
- - !ruby/object:Gem::Version
78
- version: 3.2.13
79
- type: :development
80
- prerelease: false
81
- version_requirements: !ruby/object:Gem::Requirement
82
- requirements:
83
- - - "~>"
84
- - !ruby/object:Gem::Version
85
- version: 3.2.13
86
- - !ruby/object:Gem::Dependency
87
- name: json
88
- requirement: !ruby/object:Gem::Requirement
89
- requirements:
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- version: 2.0.2
93
- type: :development
94
- prerelease: false
95
- version_requirements: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- version: 2.0.2
100
72
  - !ruby/object:Gem::Dependency
101
73
  name: pry-nav
102
74
  requirement: !ruby/object:Gem::Requirement
@@ -140,19 +112,19 @@ dependencies:
140
112
  - !ruby/object:Gem::Version
141
113
  version: 0.2.5
142
114
  - !ruby/object:Gem::Dependency
143
- name: sqlite3
115
+ name: bundler
144
116
  requirement: !ruby/object:Gem::Requirement
145
117
  requirements:
146
- - - "~>"
118
+ - - "<"
147
119
  - !ruby/object:Gem::Version
148
- version: 1.3.13
120
+ version: '2.0'
149
121
  type: :development
150
122
  prerelease: false
151
123
  version_requirements: !ruby/object:Gem::Requirement
152
124
  requirements:
153
- - - "~>"
125
+ - - "<"
154
126
  - !ruby/object:Gem::Version
155
- version: 1.3.13
127
+ version: '2.0'
156
128
  description: |
157
129
  New Relic is a performance management system, developed by New Relic,
158
130
  Inc (http://www.newrelic.com). New Relic provides you with deep
@@ -206,12 +178,11 @@ files:
206
178
  - lib/new_relic/agent/commands/agent_command.rb
207
179
  - lib/new_relic/agent/commands/agent_command_router.rb
208
180
  - lib/new_relic/agent/commands/thread_profiler_session.rb
209
- - lib/new_relic/agent/commands/xray_session.rb
210
- - lib/new_relic/agent/commands/xray_session_collection.rb
211
181
  - lib/new_relic/agent/configuration.rb
212
182
  - lib/new_relic/agent/configuration/default_source.rb
213
183
  - lib/new_relic/agent/configuration/dotted_hash.rb
214
184
  - lib/new_relic/agent/configuration/environment_source.rb
185
+ - lib/new_relic/agent/configuration/event_harvest_config.rb
215
186
  - lib/new_relic/agent/configuration/high_security_source.rb
216
187
  - lib/new_relic/agent/configuration/manager.rb
217
188
  - lib/new_relic/agent/configuration/manual_source.rb
@@ -219,6 +190,8 @@ files:
219
190
  - lib/new_relic/agent/configuration/security_policy_source.rb
220
191
  - lib/new_relic/agent/configuration/server_source.rb
221
192
  - lib/new_relic/agent/configuration/yaml_source.rb
193
+ - lib/new_relic/agent/connect/request_builder.rb
194
+ - lib/new_relic/agent/connect/response_handler.rb
222
195
  - lib/new_relic/agent/cross_app_monitor.rb
223
196
  - lib/new_relic/agent/cross_app_payload.rb
224
197
  - lib/new_relic/agent/cross_app_tracing.rb
@@ -268,9 +241,8 @@ files:
268
241
  - lib/new_relic/agent/instrumentation/active_job.rb
269
242
  - lib/new_relic/agent/instrumentation/active_merchant.rb
270
243
  - lib/new_relic/agent/instrumentation/active_record.rb
271
- - lib/new_relic/agent/instrumentation/active_record_4.rb
272
- - lib/new_relic/agent/instrumentation/active_record_5.rb
273
244
  - lib/new_relic/agent/instrumentation/active_record_helper.rb
245
+ - lib/new_relic/agent/instrumentation/active_record_notifications.rb
274
246
  - lib/new_relic/agent/instrumentation/active_record_prepend.rb
275
247
  - lib/new_relic/agent/instrumentation/active_record_subscriber.rb
276
248
  - lib/new_relic/agent/instrumentation/active_storage.rb
@@ -282,7 +254,6 @@ files:
282
254
  - lib/new_relic/agent/instrumentation/curb.rb
283
255
  - lib/new_relic/agent/instrumentation/data_mapper.rb
284
256
  - lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb
285
- - lib/new_relic/agent/instrumentation/evented_subscriber.rb
286
257
  - lib/new_relic/agent/instrumentation/excon.rb
287
258
  - lib/new_relic/agent/instrumentation/excon/connection.rb
288
259
  - lib/new_relic/agent/instrumentation/excon/middleware.rb
@@ -299,6 +270,7 @@ files:
299
270
  - lib/new_relic/agent/instrumentation/mongo.rb
300
271
  - lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb
301
272
  - lib/new_relic/agent/instrumentation/net.rb
273
+ - lib/new_relic/agent/instrumentation/notifications_subscriber.rb
302
274
  - lib/new_relic/agent/instrumentation/padrino.rb
303
275
  - lib/new_relic/agent/instrumentation/passenger_instrumentation.rb
304
276
  - lib/new_relic/agent/instrumentation/queue_time.rb
@@ -306,12 +278,10 @@ files:
306
278
  - lib/new_relic/agent/instrumentation/rails/action_controller.rb
307
279
  - lib/new_relic/agent/instrumentation/rails/action_web_service.rb
308
280
  - lib/new_relic/agent/instrumentation/rails3/action_controller.rb
309
- - lib/new_relic/agent/instrumentation/rails4/action_controller.rb
310
- - lib/new_relic/agent/instrumentation/rails4/action_view.rb
311
- - lib/new_relic/agent/instrumentation/rails5/action_cable.rb
312
- - lib/new_relic/agent/instrumentation/rails5/action_controller.rb
313
- - lib/new_relic/agent/instrumentation/rails5/action_view.rb
314
281
  - lib/new_relic/agent/instrumentation/rails_middleware.rb
282
+ - lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb
283
+ - lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb
284
+ - lib/new_relic/agent/instrumentation/rails_notifications/action_view.rb
315
285
  - lib/new_relic/agent/instrumentation/rainbows_instrumentation.rb
316
286
  - lib/new_relic/agent/instrumentation/rake.rb
317
287
  - lib/new_relic/agent/instrumentation/redis.rb
@@ -388,7 +358,6 @@ files:
388
358
  - lib/new_relic/agent/transaction/trace_node.rb
389
359
  - lib/new_relic/agent/transaction/tracing.rb
390
360
  - lib/new_relic/agent/transaction/transaction_sample_buffer.rb
391
- - lib/new_relic/agent/transaction/xray_sample_buffer.rb
392
361
  - lib/new_relic/agent/transaction_error_primitive.rb
393
362
  - lib/new_relic/agent/transaction_event_aggregator.rb
394
363
  - lib/new_relic/agent/transaction_event_primitive.rb
@@ -422,8 +391,7 @@ files:
422
391
  - lib/new_relic/control/frameworks/rails.rb
423
392
  - lib/new_relic/control/frameworks/rails3.rb
424
393
  - lib/new_relic/control/frameworks/rails4.rb
425
- - lib/new_relic/control/frameworks/rails5.rb
426
- - lib/new_relic/control/frameworks/rails6.rb
394
+ - lib/new_relic/control/frameworks/rails_notifications.rb
427
395
  - lib/new_relic/control/frameworks/ruby.rb
428
396
  - lib/new_relic/control/frameworks/sinatra.rb
429
397
  - lib/new_relic/control/instance_methods.rb
@@ -489,8 +457,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
489
457
  - !ruby/object:Gem::Version
490
458
  version: 1.3.1
491
459
  requirements: []
492
- rubyforge_project:
493
- rubygems_version: 2.7.7
460
+ rubygems_version: 3.0.3
494
461
  signing_key:
495
462
  specification_version: 4
496
463
  summary: New Relic Ruby Agent
@@ -1,55 +0,0 @@
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 'forwardable'
6
-
7
- module NewRelic
8
- module Agent
9
- module Commands
10
- class XraySession
11
- extend Forwardable
12
-
13
- attr_reader :id, :command_arguments
14
- attr_reader :xray_session_name, :key_transaction_name,
15
- :requested_trace_count, :duration, :sample_period
16
-
17
- def initialize(command_arguments)
18
- @command_arguments = command_arguments
19
- @id = command_arguments.fetch("x_ray_id", nil)
20
- @xray_session_name = command_arguments.fetch("xray_session_name", "")
21
- @key_transaction_name = command_arguments.fetch("key_transaction_name", "")
22
- @requested_trace_count = command_arguments.fetch("requested_trace_count", 100)
23
- @duration = command_arguments.fetch("duration", 86400)
24
- @sample_period = command_arguments.fetch("sample_period", 0.1)
25
- @run_profiler = command_arguments.fetch("run_profiler", true)
26
- end
27
-
28
- def active?
29
- @active
30
- end
31
-
32
- def run_profiler?
33
- @run_profiler && NewRelic::Agent.config[:'xray_session.allow_profiles']
34
- end
35
-
36
- def activate
37
- @active = true
38
- @start_time = Time.now
39
- end
40
-
41
- def deactivate
42
- @active = false
43
- end
44
-
45
- def requested_period
46
- @sample_period
47
- end
48
-
49
- def finished?
50
- @start_time + @duration < Time.now
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,161 +0,0 @@
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 'forwardable'
6
- require 'thread'
7
- require 'new_relic/agent/commands/xray_session'
8
-
9
- module NewRelic
10
- module Agent
11
- module Commands
12
- class XraySessionCollection
13
- extend Forwardable
14
-
15
- def initialize(backtrace_service, event_listener)
16
- @backtrace_service = backtrace_service
17
-
18
- # This lock protects access to the sessions hash, but it's expected
19
- # that individual session objects within the hash will be manipulated
20
- # outside the lock. This is safe because manipulation of the session
21
- # objects is expected from only a single thread (the harvest thread)
22
- @sessions_lock = Mutex.new
23
- @sessions = {}
24
-
25
- if event_listener
26
- event_listener.subscribe(:before_harvest, &method(:cleanup_finished_sessions))
27
- end
28
- end
29
-
30
- def handle_active_xray_sessions(agent_command)
31
- # If X-Rays are disabled, just be quiet about it and don't start the
32
- # command. Other hosts might be running the X-Ray, so we don't need
33
- # to bark on every get_agent_commands.
34
- if !NewRelic::Agent.config[:'xray_session.enabled']
35
- NewRelic::Agent.logger.debug("Not responding to X-Ray command because of config 'xray_session.enabled' = #{NewRelic::Agent.config[:'xray_session.enabled']}")
36
- return
37
- end
38
-
39
- incoming_ids = agent_command.arguments["xray_ids"]
40
- deactivate_for_incoming_sessions(incoming_ids)
41
- activate_sessions(incoming_ids)
42
- end
43
-
44
- def session_id_for_transaction_name(name)
45
- @sessions_lock.synchronize do
46
- @sessions.each do |id, session|
47
- return id if session.key_transaction_name == name
48
- end
49
- end
50
- nil
51
- end
52
-
53
- NO_PROFILES = [].freeze
54
-
55
- def harvest_thread_profiles
56
- return NO_PROFILES unless NewRelic::Agent::Threading::BacktraceService.is_supported?
57
-
58
- profiles = active_thread_profiling_sessions.map do |session|
59
- NewRelic::Agent.logger.debug("Harvesting profile for X-Ray session #{session.inspect}")
60
- @backtrace_service.harvest(session.key_transaction_name)
61
- end
62
- profiles.reject! {|p| p.empty?}
63
- profiles.compact
64
- end
65
-
66
- def stop_all_sessions
67
- deactivate_for_incoming_sessions([])
68
- end
69
-
70
- def cleanup_finished_sessions
71
- finished_session_ids.each do |id|
72
- NewRelic::Agent.logger.debug("Finished X-Ray session #{id} by duration. Removing it from active sessions.")
73
- remove_session_by_id(id)
74
- end
75
- end
76
-
77
-
78
- ### Internals
79
-
80
- def new_relic_service
81
- NewRelic::Agent.instance.service
82
- end
83
-
84
- # These are unsynchonized and should only be used for testing
85
- def_delegators :@sessions, :[], :include?
86
-
87
- def active_thread_profiling_sessions
88
- @sessions_lock.synchronize do
89
- @sessions.values.select { |s| s.active? && s.run_profiler? }
90
- end
91
- end
92
-
93
- ### Session activation
94
-
95
- def activate_sessions(incoming_ids)
96
- lookup_metadata_for(ids_to_activate(incoming_ids)).each do |raw|
97
- add_session(XraySession.new(raw))
98
- end
99
- end
100
-
101
- def ids_to_activate(incoming_ids)
102
- @sessions_lock.synchronize { incoming_ids - @sessions.keys }
103
- end
104
-
105
- # Please don't hold the @sessions_lock across me! Calling the service
106
- # is time-consuming, and will block request threads. Which is rude.
107
- def lookup_metadata_for(ids_to_activate)
108
- return [] if ids_to_activate.empty?
109
-
110
- NewRelic::Agent.logger.debug("Retrieving metadata for X-Ray sessions #{ids_to_activate.inspect}")
111
- new_relic_service.get_xray_metadata(ids_to_activate)
112
- end
113
-
114
- def add_session(session)
115
- NewRelic::Agent.logger.debug("Adding X-Ray session #{session.inspect}")
116
- NewRelic::Agent.increment_metric("Supportability/XraySessions/Starts")
117
-
118
- @sessions_lock.synchronize { @sessions[session.id] = session }
119
-
120
- session.activate
121
- if session.run_profiler?
122
- @backtrace_service.subscribe(session.key_transaction_name, session.command_arguments)
123
- end
124
- end
125
-
126
- ### Session deactivation
127
-
128
- def deactivate_for_incoming_sessions(incoming_ids)
129
- ids_to_remove(incoming_ids).each do |session_id|
130
- remove_session_by_id(session_id)
131
- end
132
- end
133
-
134
- def ids_to_remove(incoming_ids)
135
- @sessions_lock.synchronize { @sessions.keys - incoming_ids }
136
- end
137
-
138
- def remove_session_by_id(id)
139
- session = @sessions_lock.synchronize { @sessions.delete(id) }
140
-
141
- if session
142
- NewRelic::Agent.logger.debug("Removing X-Ray session #{session.inspect}")
143
- NewRelic::Agent.increment_metric("Supportability/XraySessions/Stops")
144
-
145
- if session.run_profiler?
146
- @backtrace_service.unsubscribe(session.key_transaction_name)
147
- end
148
- session.deactivate
149
- end
150
- end
151
-
152
- def finished_session_ids
153
- @sessions_lock.synchronize do
154
- @sessions.map{|k, s| k if s.finished?}.compact
155
- end
156
- end
157
-
158
- end
159
- end
160
- end
161
- end