newrelic_rpm 8.15.0 → 8.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/CHANGELOG.md +65 -38
  4. data/lib/new_relic/agent/configuration/default_source.rb +56 -17
  5. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +6 -19
  6. data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +39 -0
  7. data/lib/new_relic/agent/instrumentation/action_dispatch.rb +31 -0
  8. data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +64 -0
  9. data/lib/new_relic/agent/instrumentation/action_mailbox.rb +30 -0
  10. data/lib/new_relic/agent/instrumentation/action_mailbox_subscriber.rb +33 -0
  11. data/lib/new_relic/agent/instrumentation/action_mailer.rb +30 -0
  12. data/lib/new_relic/agent/instrumentation/action_mailer_subscriber.rb +85 -0
  13. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +7 -7
  14. data/lib/new_relic/agent/instrumentation/active_job.rb +14 -1
  15. data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +41 -0
  16. data/lib/new_relic/agent/instrumentation/active_storage.rb +4 -0
  17. data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +2 -30
  18. data/lib/new_relic/agent/instrumentation/active_support.rb +21 -6
  19. data/lib/new_relic/agent/instrumentation/active_support_subscriber.rb +41 -0
  20. data/lib/new_relic/agent/instrumentation/custom_events.rb +12 -0
  21. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +41 -0
  22. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +4 -4
  23. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +13 -1
  24. data/lib/new_relic/version.rb +1 -1
  25. data/newrelic.yml +10 -1
  26. data/newrelic_rpm.gemspec +1 -0
  27. data/test/agent_helper.rb +1 -1
  28. metadata +26 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f47710c44016e66769de790e72f361e78671a66d676ce1251bb65fe932dfb617
4
- data.tar.gz: 16886676b0209e4822017475ec470ad11ec20ebb65354a2bd2c022b4d3d3b90e
3
+ metadata.gz: 36c4100794a9189b995fb7c649be61e3770b1e47ea5c961624c6519bea637770
4
+ data.tar.gz: bd4cf6f4a56bdad905768d3306ab26649c8ff9564619ec0b4099db63043bc1f9
5
5
  SHA512:
6
- metadata.gz: f334495833c77703fb5f439617ba4b61c4e07e2138775e510f1c293afa4496ddfe9528582e2cfddcf85e9b04dddfa36dcc58ff110bbd0d05d02aaa2128346633
7
- data.tar.gz: b1eea25ed1b3881d974af3f179cbafc1caf605ffa2941e6a3a4be046aa7afd99643c6865fb0b88ac9817f3e5e630784842502c0aad02af4fcd79418b37eab5fd
6
+ metadata.gz: 9a97a4611de30a1d96ea4afb7b24220dd86f289761fb17cac531acbaeb09ed55be183127a78fbb7c5dac153f68305d6f8e87164be7fe0ab97ef3faf5e42ce2d5
7
+ data.tar.gz: 8a5e4c91f9c89ba0e3317984865127ad30b9746b469f67246c9da20257ed4a2851d0148f191b19288655aec642d79edbcd71d98f0cd2ebe60c7c7e95e8696336
data/.rubocop.yml CHANGED
@@ -1470,6 +1470,7 @@ Style/MethodCallWithArgsParentheses:
1470
1470
  - source
1471
1471
  - stub
1472
1472
  - stub_const
1473
+ - use
1473
1474
  AllowedPatterns: [^assert, ^refute]
1474
1475
 
1475
1476
  Style/MethodCallWithoutArgsParentheses:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # New Relic Ruby Agent Release Notes
2
2
 
3
+ ## 8.16.0
4
+
5
+ Version 8.16.0 introduces more Ruby on Rails instrumentation (especially for Rails 6 and 7) for various Action\*/Active\* libraries whose actions produce [Active Support notifications events](https://guides.rubyonrails.org/active_support_instrumentation.html).
6
+
7
+ - **Add Various Ruby on Rails Library Instrumentations**
8
+
9
+ New instrumentation is now automatically provided by several Action\*/Active\* libaries that generate Active Support notifications. With each Ruby on Rails release, new the Rails libraries add new events and sometimes existing events have their payload parameters updated as well. The New Relic Ruby agent will now automatically process more of these events and parameters with New Relic segments created for each event. At a minimum, each segment gives timing information for the event. In several cases, all non-sensitive event payload parameters are also passed along in the segment.
10
+
11
+ The agent now newly supports or has updated support for the following libraries:
12
+
13
+ - Action Cable (for WebSockets) [PR#1749](https://github.com/newrelic/newrelic-ruby-agent/pull/1749)
14
+ - Action Controller (for the 'C' in MVC) [PR#1744](https://github.com/newrelic/newrelic-ruby-agent/pull/1744/)
15
+ - Action Mailbox (for sending mail) [PR#1740](https://github.com/newrelic/newrelic-ruby-agent/pull/1740)
16
+ - Action Mailer (for routing mail) [PR#1740](https://github.com/newrelic/newrelic-ruby-agent/pull/1740)
17
+ - Active Job (for background jobs) [PR#1742](https://github.com/newrelic/newrelic-ruby-agent/pull/1761)
18
+ - Active Support (for caching operations) [PR#1742](https://github.com/newrelic/newrelic-ruby-agent/pull/1742)
19
+
20
+ The instrumentations for each of these libaries are all enabled by default, but can be independently disabled via configuration by using the following parameters:
21
+
22
+ | Configuration name | Default | Behavior |
23
+ | --------------------------- | ------- | ------------------------------------------------------ |
24
+ | `disable_action_cable` | `false` | If `true`, disables Action Cable instrumentation. |
25
+ | `disable_action_controller` | `false` | If `true`, disables Action Controller instrumentation. |
26
+ | `disable_action_mailbox` | `false` | If `true`, disables Action Mailbox instrumentation. |
27
+ | `disable_action_mailer` | `false` | If `true`, disables Action Mailer instrumentation. |
28
+ | `disable_activejob` | `false` | If `true`, disables Active Job instrumentation. |
29
+ | `disable_active_support` | `false` | If `true`, disables Active Support instrumentation. |
30
+
3
31
  ## 8.15.0
4
32
 
5
33
  Version 8.15.0 of the agent confirms compatibility with Ruby 3.2.0, adds instrumentation for concurrent-ruby, and confirms Sinatra 3 compatibility with Padrino 0.15.2. It also enables batching and compression for Infinite Tracing.
@@ -12,18 +40,18 @@ Version 8.15.0 of the agent confirms compatibility with Ruby 3.2.0, adds instrum
12
40
 
13
41
  Instrumentation for the [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby) gem has been added to the agent for versions 1.1.5 and above. When a transaction is already in progress and a call to a `Concurrent::` method that routes through `Concurrent::ThreadPoolExecutor#post` is made, a segment will be added to the transaction. Any content within the block passed to the `Concurrent::` method that is instrumented by the agent, such as a call to `Net::HTTP.get`, will have a nested segment created. [PR#1682](https://github.com/newrelic/newrelic-ruby-agent/pull/1682)
14
42
 
15
- | Configuration name | Default | Behavior |
16
- | --------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
43
+ | Configuration name | Default | Behavior |
44
+ | --------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
17
45
  | `instrumentation.concurrent_ruby` | auto | Controls auto-instrumentation of the concurrent-ruby library at start up. May be one of `auto`, `prepend`, `chain`, `disabled`. |
18
46
 
19
47
  - **Infinite Tracing: Use batching and compression**
20
48
 
21
49
  For [Infinite Tracing](https://docs.newrelic.com/docs/distributed-tracing/infinite-tracing/introduction-infinite-tracing/), which Ruby applications can leverage with the `newrelic-infinite_tracing` gem, payloads will now be batched and compressed to signficantly decrease the amount of outbound network traffic. [PR#1723](https://github.com/newrelic/newrelic-ruby-agent/pull/1723)
22
50
 
23
- | Configuration name | Default | Behavior |
24
- | --------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
25
- | `infinite_tracing.batching` | true | If true (the default), data sent to the Trace Observer will be batched instead of each span being sent individually |
26
- | `infinite_tracing.compression_level` | high | Configure the compression level for data sent to the Trace Observer. May be one of [none|low|medium|high]. 'high' is the default. Set the level to 'none' to disable compression. |
51
+ | Configuration name | Default | Behavior |
52
+ | ------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------- | --- | ------ | ----------------------------------------------------------------------------- |
53
+ | `infinite_tracing.batching` | true | If true (the default), data sent to the Trace Observer will be batched instead of each span being sent individually |
54
+ | `infinite_tracing.compression_level` | high | Configure the compression level for data sent to the Trace Observer. May be one of [none | low | medium | high]. 'high' is the default. Set the level to 'none' to disable compression. |
27
55
 
28
56
  - **Add Support for Padrino 0.15.2 and Sinatra 3**
29
57
 
@@ -294,36 +322,35 @@ Version 8.11.0 of the agent updates the `newrelic deployments` command to work w
294
322
 
295
323
  - **Deprecate instrumentation versions with low adoption and/or versions over five years old**
296
324
 
297
-
298
- This release deprecates the following instrumentation:
299
- | Deprecated | Replacement |
300
- | ----------- | ----------- |
301
- | ActiveMerchant < 1.65.0 | ActiveMerchant >= 1.65.0 |
302
- | Acts As Solr (all versions) | none |
303
- | Authlogic (all versions) | none |
304
- | Bunny < 2.7.0 | bunny >= 2.7.0 |
305
- | Dalli < 3.2.1 | Dalli >= 3.2.1 |
306
- | DataMapper (all versions) | none |
307
- | Delayed Job < 4.1.0 | Delayed Job >= 4.1.0 |
308
- | Excon < 0.56.0 | Excon >= 0.56.0 |
309
- | Grape < 0.19.2 | Grape >= 0.19.2 |
310
- | HTTPClient < 2.8.3 | HTTPClient 2.8.3 |
311
- | HTTP.rb < 2.2.2 | HTTP.rb >= 2.2.2 |
312
- | Mongo < 2.4.1 | Mongo >= 2.4.1 |
313
- | Padrino < 0.15.0 | Padrino >= 0.15.0 |
314
- | Passenger < 5.1.3 | Passenger >= 5.1.3 |
315
- | Puma < 3.9.0 | Puma >= 3.9.0 |
316
- | Rack < 1.6.8 | Rack >= 1.6.8 |
317
- | Rails 3.2.x | Rails >= 4.x |
318
- | Rainbows (all versions) | none |
319
- | Sequel < 4.45.0 | Sequel >= 4.45.0 |
320
- | Sidekiq < 5.0.0 | Sidekiq >= 5.0.0 |
321
- | Sinatra < 2.0.0 | Sinatra >= 2.0.0 |
322
- | Sunspot (all versions) | none |
323
- | Typhoeus < 1.3.0 | Typhoeus >= 1.3.0 |
324
- | Unicorn < 5.3.0 | Unicorn >= 5.3.0 |
325
-
326
- For the gems with deprecated versions, we will no longer test those versions in our multiverse suite. They may, however, still be compatible with the agent. We will no longer fix bug reports for issues related to these gem versions.
325
+ This release deprecates the following instrumentation:
326
+ | Deprecated | Replacement |
327
+ | ----------- | ----------- |
328
+ | ActiveMerchant < 1.65.0 | ActiveMerchant >= 1.65.0 |
329
+ | Acts As Solr (all versions) | none |
330
+ | Authlogic (all versions) | none |
331
+ | Bunny < 2.7.0 | bunny >= 2.7.0 |
332
+ | Dalli < 3.2.1 | Dalli >= 3.2.1 |
333
+ | DataMapper (all versions) | none |
334
+ | Delayed Job < 4.1.0 | Delayed Job >= 4.1.0 |
335
+ | Excon < 0.56.0 | Excon >= 0.56.0 |
336
+ | Grape < 0.19.2 | Grape >= 0.19.2 |
337
+ | HTTPClient < 2.8.3 | HTTPClient 2.8.3 |
338
+ | HTTP.rb < 2.2.2 | HTTP.rb >= 2.2.2 |
339
+ | Mongo < 2.4.1 | Mongo >= 2.4.1 |
340
+ | Padrino < 0.15.0 | Padrino >= 0.15.0 |
341
+ | Passenger < 5.1.3 | Passenger >= 5.1.3 |
342
+ | Puma < 3.9.0 | Puma >= 3.9.0 |
343
+ | Rack < 1.6.8 | Rack >= 1.6.8 |
344
+ | Rails 3.2.x | Rails >= 4.x |
345
+ | Rainbows (all versions) | none |
346
+ | Sequel < 4.45.0 | Sequel >= 4.45.0 |
347
+ | Sidekiq < 5.0.0 | Sidekiq >= 5.0.0 |
348
+ | Sinatra < 2.0.0 | Sinatra >= 2.0.0 |
349
+ | Sunspot (all versions) | none |
350
+ | Typhoeus < 1.3.0 | Typhoeus >= 1.3.0 |
351
+ | Unicorn < 5.3.0 | Unicorn >= 5.3.0 |
352
+
353
+ For the gems with deprecated versions, we will no longer test those versions in our multiverse suite. They may, however, still be compatible with the agent. We will no longer fix bug reports for issues related to these gem versions.
327
354
 
328
355
  - **Clarify documentation for `rake.tasks` configuration**
329
356
 
@@ -3157,7 +3184,7 @@ reported to New Relic. The second ignores only the Apdex metric for a single
3157
3184
  transaction. The third disables javascript injection for browser monitoring
3158
3185
  for the current transaction.
3159
3186
 
3160
- These methods differ from the existing newrelic*ignore** method in that they
3187
+ These methods differ from the existing newrelic*ignore\*\* method in that they
3161
3188
  may be called *during\* a transaction based on some dynamic runtime criteria,
3162
3189
  as opposed to at the class level on startup.
3163
3190
 
@@ -3254,7 +3281,7 @@ traces from in the Transaction Trace drill-down.
3254
3281
  - High security mode V2
3255
3282
 
3256
3283
  The Ruby agent now supports V2 of New Relic's high security mode. To enable
3257
- it, you must add 'high_security: true' to your newrelic.yml file, _and_ enable
3284
+ it, you must add 'high\_security: true' to your newrelic.yml file, _and_ enable
3258
3285
  high security mode through the New Relic web interface. The local agent
3259
3286
  setting must be in agreement with the server-side setting, or the agent will
3260
3287
  shut down and no data will be collected.
@@ -364,9 +364,8 @@ module NewRelic
364
364
  :type => Array,
365
365
  :allowed_from_server => false,
366
366
  :description => <<-DESCRIPTION
367
- An array of ActiveSupport custom events names to subscribe to and provide
368
- instrumentation for. For example,
369
- - my.custom.event
367
+ An array of ActiveSupport custom event names to subscribe to and instrument. For example,
368
+ - one.custom.event
370
369
  - another.event
371
370
  - a.third.event
372
371
  DESCRIPTION
@@ -466,7 +465,7 @@ When `true`, the agent captures HTTP request parameters and attaches them to tra
466
465
  :public => true,
467
466
  :type => String,
468
467
  :allowed_from_server => false,
469
- :description => 'A dictionary of [label names](/docs/data-analysis/user-interface-functions/labels-categories-organize-your-apps-servers) and values that will be applied to the data sent from this agent. May also be expressed as a semicolon-delimited `;` string of colon-separated `:` pairs. For example, `<var>Server</var>:<var>One</var>;<var>Data Center</var>:<var>Primary</var>`.'
468
+ :description => 'A dictionary of [label names](/docs/data-analysis/user-interface-functions/labels-categories-organize-your-apps-servers) and values that will be applied to the data sent from this agent. May also be expressed as a semicolon-delimited `;` string of colon-separated `:` pairs. For example, `Server:One;Data Center:Primary`.'
470
469
  },
471
470
  :log_file_name => {
472
471
  :default => 'newrelic_agent.log',
@@ -1138,25 +1137,65 @@ A map of error classes to a list of messages. When an error of one of the classe
1138
1137
  :default => false,
1139
1138
  :public => true,
1140
1139
  :type => Boolean,
1141
- :dynamic_name => true,
1142
1140
  :allowed_from_server => false,
1143
1141
  :description => 'If `true`, disables Action Cable instrumentation.'
1144
1142
  },
1143
+ # TODO: by subscribing to process_middleware.action_dispatch events,
1144
+ # we duplicate the efforts already performed by non-notifications
1145
+ # based instrumentation. In future, we ought to determine the
1146
+ # extent of the overlap and duplication and end up with only this
1147
+ # notifications based approach existing and the monkey patching
1148
+ # approach removed entirely. NOTE that we will likely not want to
1149
+ # do so until we are okay with dropping support for Rails < v6,
1150
+ # given that these events are available only for v6+.
1151
+ :disable_action_dispatch => {
1152
+ :default => true,
1153
+ :public => false,
1154
+ :type => Boolean,
1155
+ :allowed_from_server => false,
1156
+ :description => 'If `true`, disables Action Dispatch instrumentation.'
1157
+ },
1158
+ :disable_action_controller => {
1159
+ :default => false,
1160
+ :public => true,
1161
+ :type => Boolean,
1162
+ :allowed_from_server => false,
1163
+ :description => 'If `true`, disables Action Controller instrumentation.'
1164
+ },
1165
+ :disable_action_mailbox => {
1166
+ :default => false,
1167
+ :public => true,
1168
+ :type => Boolean,
1169
+ :allowed_from_server => false,
1170
+ :description => 'If `true`, disables Action Mailbox instrumentation.'
1171
+ },
1172
+ :disable_action_mailer => {
1173
+ :default => false,
1174
+ :public => true,
1175
+ :type => Boolean,
1176
+ :allowed_from_server => false,
1177
+ :description => 'If `true`, disables Action Mailer instrumentation.'
1178
+ },
1145
1179
  :disable_activejob => {
1146
1180
  :default => false,
1147
1181
  :public => true,
1148
1182
  :type => Boolean,
1149
- :dynamic_name => true,
1150
1183
  :allowed_from_server => false,
1151
- :description => 'If `true`, disables ActiveJob instrumentation.'
1184
+ :description => 'If `true`, disables Active Job instrumentation.'
1152
1185
  },
1153
1186
  :disable_active_storage => {
1154
1187
  :default => false,
1155
1188
  :public => true,
1156
1189
  :type => Boolean,
1157
- :dynamic_name => true,
1158
1190
  :allowed_from_server => false,
1159
- :description => 'If `true`, disables ActiveStorage instrumentation.'
1191
+ :description => 'If `true`, disables Active Storage instrumentation.'
1192
+ },
1193
+ :disable_active_support => {
1194
+ :default => false,
1195
+ :public => true,
1196
+ :type => Boolean,
1197
+ :allowed_from_server => false,
1198
+ :description => 'If `true`, disables Active Support instrumentation.'
1160
1199
  },
1161
1200
  :disable_activerecord_instrumentation => {
1162
1201
  :default => value_of(:skip_ar_instrumentation),
@@ -1164,7 +1203,7 @@ A map of error classes to a list of messages. When an error of one of the classe
1164
1203
  :public => true,
1165
1204
  :type => Boolean,
1166
1205
  :allowed_from_server => false,
1167
- :description => 'If `true`, disables active record instrumentation.'
1206
+ :description => 'If `true`, disables Active Record instrumentation.'
1168
1207
  },
1169
1208
  :disable_active_record_notifications => {
1170
1209
  :default => false,
@@ -1172,7 +1211,7 @@ A map of error classes to a list of messages. When an error of one of the classe
1172
1211
  :type => Boolean,
1173
1212
  :dynamic_name => true,
1174
1213
  :allowed_from_server => false,
1175
- :description => 'If `true`, disables instrumentation for ActiveRecord 4, 5, and 6.'
1214
+ :description => 'If `true`, disables instrumentation for Active Record 4+'
1176
1215
  },
1177
1216
  :disable_bunny => {
1178
1217
  :default => false,
@@ -1537,9 +1576,9 @@ If `true`, disables agent middleware for Sinatra. This middleware is responsible
1537
1576
  :type => String,
1538
1577
  :allowed_from_server => false,
1539
1578
  :external => :infinite_tracing,
1540
- :description => "Configures the hostname for the Trace Observer Host. " \
1579
+ :description => "Configures the hostname for the trace observer Host. " \
1541
1580
  "When configured, enables tail-based sampling by sending all recorded spans " \
1542
- "to a Trace Observer for further sampling decisions, irrespective of any usual " \
1581
+ "to a trace observer for further sampling decisions, irrespective of any usual " \
1543
1582
  "agent sampling decision."
1544
1583
  },
1545
1584
  :'infinite_tracing.trace_observer.port' => {
@@ -1548,7 +1587,7 @@ If `true`, disables agent middleware for Sinatra. This middleware is responsible
1548
1587
  :type => Integer,
1549
1588
  :allowed_from_server => false,
1550
1589
  :external => :infinite_tracing,
1551
- :description => "Configures the TCP/IP port for the Trace Observer Host"
1590
+ :description => "Configures the TCP/IP port for the trace observer Host"
1552
1591
  },
1553
1592
  # Instrumentation
1554
1593
  :'instrumentation.active_support_logger' => {
@@ -2336,8 +2375,8 @@ If `true`, disables agent middleware for Sinatra. This middleware is responsible
2336
2375
  :type => Boolean,
2337
2376
  :allowed_from_server => false,
2338
2377
  :external => :infinite_tracing,
2339
- :description => "If true (the default), data sent to the Trace Observer will be batched\ninstead of each " \
2340
- "span being sent individually"
2378
+ :description => "If `true` (the default), data sent to the trace observer is batched\ninstead of sending " \
2379
+ "each span individually."
2341
2380
  },
2342
2381
  :'infinite_tracing.compression_level' => {
2343
2382
  :default => :high,
@@ -2345,7 +2384,7 @@ If `true`, disables agent middleware for Sinatra. This middleware is responsible
2345
2384
  :type => Symbol,
2346
2385
  :allowed_from_server => false,
2347
2386
  :external => :infinite_tracing,
2348
- :description => "Configure the compression level for data sent to the Trace Observer\nMay be one of " \
2387
+ :description => "Configure the compression level for data sent to the trace observer\nMay be one of " \
2349
2388
  "[none|low|medium|high]\n'high' is the default. Set the level to 'none' to disable compression"
2350
2389
  },
2351
2390
  :js_agent_file => {
@@ -10,9 +10,7 @@ module NewRelic
10
10
  class ActionCableSubscriber < NotificationsSubscriber
11
11
  PERFORM_ACTION = 'perform_action.action_cable'.freeze
12
12
 
13
- def start(name, id, payload) # THREAD_LOCAL_ACCESS
14
- return unless state.is_execution_traced?
15
-
13
+ def start_segment(name, id, payload) # THREAD_LOCAL_ACCESS
16
14
  finishable = if name == PERFORM_ACTION
17
15
  Tracer.start_transaction_or_segment(
18
16
  name: transaction_name_from_payload(payload),
@@ -22,21 +20,6 @@ module NewRelic
22
20
  Tracer.start_segment(name: metric_name_from_payload(name, payload))
23
21
  end
24
22
  push_segment(id, finishable)
25
- rescue => e
26
- log_notification_error(e, name, 'start')
27
- end
28
-
29
- def finish(name, id, payload) # THREAD_LOCAL_ACCESS
30
- return unless state.is_execution_traced?
31
-
32
- if exception = exception_object(payload)
33
- NewRelic::Agent.notice_error(exception)
34
- end
35
-
36
- finishable = pop_segment(id)
37
- finishable.finish if finishable
38
- rescue => e
39
- log_notification_error(e, name, 'finish')
40
23
  end
41
24
 
42
25
  private
@@ -46,7 +29,11 @@ module NewRelic
46
29
  end
47
30
 
48
31
  def metric_name_from_payload(name, payload)
49
- "Ruby/ActionCable/#{payload[:channel_class]}/#{action_name(name)}"
32
+ "Ruby/ActionCable/#{metric_name(payload)}/#{action_name(name)}"
33
+ end
34
+
35
+ def metric_name(payload)
36
+ payload[:broadcasting] || payload[:channel_class]
50
37
  end
51
38
 
52
39
  DOT_ACTION_CABLE = '.action_cable'.freeze
@@ -0,0 +1,39 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/notifications_subscriber'
6
+ require 'new_relic/agent/instrumentation/ignore_actions'
7
+ require 'new_relic/agent/parameter_filtering'
8
+
9
+ module NewRelic
10
+ module Agent
11
+ module Instrumentation
12
+ class ActionControllerOtherSubscriber < NotificationsSubscriber
13
+ def add_segment_params(segment, payload)
14
+ segment.params[:filter] = payload[:filter] if payload[:filter]
15
+ segment.params[:keys] = payload[:keys] if payload[:keys]
16
+ segment.params[:original_path] = payload[:request].original_fullpath if payload[:request]
17
+
18
+ if payload[:context]
19
+ segment.params[:action] = payload[:context][:action]
20
+ segment.params[:controller] = payload[:context][:controller]
21
+ end
22
+ end
23
+
24
+ def metric_name(name, payload)
25
+ controller_name = controller_name_for_metric(payload)
26
+ "Ruby/ActionController#{"/#{controller_name}" if controller_name}/#{name.gsub(/\.action_controller/, '')}"
27
+ end
28
+
29
+ def controller_name_for_metric(payload)
30
+ # redirect_to
31
+ return payload[:request].controller_class.controller_path if payload[:request] && payload[:request].controller_class
32
+
33
+ # unpermitted_parameters
34
+ ::NewRelic::LanguageSupport.constantize(payload[:context][:controller]).controller_path if payload[:context] && payload[:context][:controller]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,31 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/action_dispatch_subscriber'
6
+
7
+ DependencyDetection.defer do
8
+ named :action_dispatch
9
+
10
+ depends_on do
11
+ !NewRelic::Agent.config[:disable_action_dispatch]
12
+ end
13
+
14
+ depends_on do
15
+ defined?(ActiveSupport) &&
16
+ defined?(ActionDispatch) &&
17
+ defined?(ActionPack) &&
18
+ ActionPack.respond_to?(:gem_version) &&
19
+ ActionPack.gem_version >= Gem::Version.new('6.0.0') && # notifications for dispatch added in Rails 6
20
+ !NewRelic::Agent::Instrumentation::ActionDispatchSubscriber.subscribed?
21
+ end
22
+
23
+ executes do
24
+ NewRelic::Agent.logger.info('Installing ActionDispatch instrumentation')
25
+ end
26
+
27
+ executes do
28
+ ActiveSupport::Notifications.subscribe(/\A[^\.]+\.action_dispatch\z/,
29
+ NewRelic::Agent::Instrumentation::ActionDispatchSubscriber.new)
30
+ end
31
+ end
@@ -0,0 +1,64 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/notifications_subscriber'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ module Instrumentation
10
+ class ActionDispatchSubscriber < NotificationsSubscriber
11
+ def start(name, id, payload)
12
+ return unless state.is_execution_traced?
13
+
14
+ start_segment(name, id, payload)
15
+ rescue => e
16
+ log_notification_error(e, name, 'start')
17
+ end
18
+
19
+ def finish(name, id, payload)
20
+ return unless state.is_execution_traced?
21
+
22
+ finish_segment(id, payload)
23
+ rescue => e
24
+ log_notification_error(e, name, 'finish')
25
+ end
26
+
27
+ def start_segment(name, id, payload)
28
+ segment = Tracer.start_segment(name: metric_name(name, payload))
29
+ push_segment(id, segment)
30
+ end
31
+
32
+ def finish_segment(id, payload)
33
+ if segment = pop_segment(id)
34
+ if exception = exception_object(payload)
35
+ segment.notice_error(exception)
36
+ end
37
+ segment.finish
38
+ end
39
+ end
40
+
41
+ def metric_name(name, payload)
42
+ middleware = payload[:middleware]
43
+ method = method_from_name(name)
44
+ "Ruby/ActionDispatch/#{middleware}/#{method}"
45
+ end
46
+
47
+ PATTERN = /\A([^\.]+)\.action_dispatch\z/
48
+ UNKNOWN = 'unknown'.freeze
49
+
50
+ METHOD_NAME_MAPPING = Hash.new do |h, k|
51
+ if PATTERN =~ k
52
+ h[k] = $1
53
+ else
54
+ h[k] = UNKNOWN
55
+ end
56
+ end
57
+
58
+ def method_from_name(name)
59
+ METHOD_NAME_MAPPING[name]
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,30 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/action_mailbox_subscriber'
6
+
7
+ DependencyDetection.defer do
8
+ named :action_mailbox
9
+
10
+ depends_on do
11
+ !NewRelic::Agent.config[:disable_action_mailbox]
12
+ end
13
+
14
+ depends_on do
15
+ defined?(ActiveSupport) &&
16
+ defined?(ActionMailbox) &&
17
+ ActionMailbox.respond_to?(:gem_version) && # 'require "action_mailbox"' doesn't require version...
18
+ ActionMailbox.gem_version >= Gem::Version.new('7.1.0.alpha') && # notifications added in Rails 7.1
19
+ !NewRelic::Agent::Instrumentation::ActionMailboxSubscriber.subscribed?
20
+ end
21
+
22
+ executes do
23
+ NewRelic::Agent.logger.info('Installing ActionMailbox instrumentation')
24
+ end
25
+
26
+ executes do
27
+ ActiveSupport::Notifications.subscribe(/\A[^\.]+\.action_mailbox\z/,
28
+ NewRelic::Agent::Instrumentation::ActionMailboxSubscriber.new)
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/notifications_subscriber'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ module Instrumentation
10
+ class ActionMailboxSubscriber < NotificationsSubscriber
11
+ def metric_name(name, payload)
12
+ mailbox = payload[:mailbox].class.name
13
+ method = method_from_name(name)
14
+ "Ruby/ActionMailbox/#{mailbox}/#{method}"
15
+ end
16
+
17
+ PATTERN = /\A([^\.]*)\.action_mailbox\z/
18
+
19
+ METHOD_NAME_MAPPING = Hash.new do |h, k|
20
+ if PATTERN =~ k
21
+ h[k] = $1
22
+ else
23
+ h[k] = NewRelic::UNKNOWN
24
+ end
25
+ end
26
+
27
+ def method_from_name(name)
28
+ METHOD_NAME_MAPPING[name]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/action_mailer_subscriber'
6
+
7
+ DependencyDetection.defer do
8
+ named :action_mailer
9
+
10
+ depends_on do
11
+ !NewRelic::Agent.config[:disable_action_mailer]
12
+ end
13
+
14
+ depends_on do
15
+ defined?(ActiveSupport) &&
16
+ defined?(ActionMailer) &&
17
+ ActionMailer.respond_to?(:gem_version) &&
18
+ ActionMailer.gem_version >= Gem::Version.new('5.0') &&
19
+ !NewRelic::Agent::Instrumentation::ActionMailerSubscriber.subscribed?
20
+ end
21
+
22
+ executes do
23
+ NewRelic::Agent.logger.info('Installing ActionMailer instrumentation')
24
+ end
25
+
26
+ executes do
27
+ ActiveSupport::Notifications.subscribe(/\A(?:[^\.]+)\.action_mailer\z/,
28
+ NewRelic::Agent::Instrumentation::ActionMailerSubscriber.new)
29
+ end
30
+ end
@@ -0,0 +1,85 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/notifications_subscriber'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ module Instrumentation
10
+ # NOTE: as of v7.1.0.0.alpha, deliver.action_mailer will provide
11
+ # an empty payload hash ({}) to #start, so in this subscriber class
12
+ # we defer params population until #finish and start the segment with
13
+ # a temporary name that is later replaced
14
+ class ActionMailerSubscriber < NotificationsSubscriber
15
+ BASE_NAME = 'Ruby/ActionMailer'
16
+ PAYLOAD_KEYS = %i[action data key mailer message_id perform_deliveries subject]
17
+ PATTERN = /\A([^\.]+)\.action_mailer\z/
18
+ UNKNOWN_MAILER = %r{^#{BASE_NAME}/#{UNKNOWN}/}
19
+
20
+ METHOD_NAME_MAPPING = Hash.new do |h, k|
21
+ if PATTERN =~ k
22
+ h[k] = $1
23
+ else
24
+ h[k] = NewRelic::UNKNOWN
25
+ end
26
+ end
27
+
28
+ def start(name, id, payload)
29
+ return unless state.is_execution_traced?
30
+
31
+ start_segment(name, id, payload)
32
+ rescue => e
33
+ log_notification_error(e, name, 'start')
34
+ end
35
+
36
+ def finish(name, id, payload)
37
+ return unless state.is_execution_traced?
38
+
39
+ finish_segment(id, payload)
40
+ rescue => e
41
+ log_notification_error(e, name, 'finish')
42
+ end
43
+
44
+ private
45
+
46
+ def start_segment(name, id, payload)
47
+ segment = Tracer.start_segment(name: metric_name(name, payload))
48
+ push_segment(id, segment)
49
+ end
50
+
51
+ def finish_segment(id, payload)
52
+ segment = pop_segment(id)
53
+ return unless segment
54
+
55
+ if segment.name.match?(UNKNOWN_MAILER) && payload.key?(:mailer)
56
+ segment.name = segment.name.sub(UNKNOWN_MAILER, "#{BASE_NAME}/#{payload[:mailer]}/")
57
+ end
58
+
59
+ PAYLOAD_KEYS.each do |key|
60
+ segment.params[key] = payload[key] if payload.key?(key)
61
+ end
62
+
63
+ notice_exception(segment, payload)
64
+ segment.finish
65
+ end
66
+
67
+ def notice_exception(segment, payload)
68
+ if exception = exception_object(payload)
69
+ segment.notice_error(exception)
70
+ end
71
+ end
72
+
73
+ def metric_name(name, payload)
74
+ mailer = payload[:mailer] || UNKNOWN
75
+ method = method_from_name(name)
76
+ "#{BASE_NAME}/#{mailer}/#{method}"
77
+ end
78
+
79
+ def method_from_name(name)
80
+ METHOD_NAME_MAPPING[name]
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -10,28 +10,25 @@ module NewRelic
10
10
  module Agent
11
11
  module Instrumentation
12
12
  class ActionViewSubscriber < NotificationsSubscriber
13
- def start(name, id, payload) # THREAD_LOCAL_ACCESS
13
+ def start_segment(name, id, payload)
14
14
  parent = segment_stack[id].last
15
15
  metric_name = format_metric_name(name, payload, parent)
16
16
 
17
17
  event = ActionViewEvent.new(metric_name, payload[:identifier])
18
- if state.is_execution_traced? && recordable?(name, metric_name)
18
+
19
+ if recordable?(name, metric_name)
19
20
  event.finishable = Tracer.start_segment(name: metric_name)
20
21
  end
21
22
  push_segment(id, event)
22
- rescue => e
23
- log_notification_error(e, name, 'start')
24
23
  end
25
24
 
26
- def finish(name, id, payload)
25
+ def finish_segment(id, payload)
27
26
  if segment = pop_segment(id)
28
27
  if exception = exception_object(payload)
29
28
  segment.notice_error(exception)
30
29
  end
31
30
  segment.finish
32
31
  end
33
- rescue => e
34
- log_notification_error(e, name, 'finish')
35
32
  end
36
33
 
37
34
  def format_metric_name(event_name, payload, parent)
@@ -61,12 +58,15 @@ module NewRelic
61
58
  RENDER_TEMPLATE_EVENT_NAME = 'render_template.action_view'.freeze
62
59
  RENDER_PARTIAL_EVENT_NAME = 'render_partial.action_view'.freeze
63
60
  RENDER_COLLECTION_EVENT_NAME = 'render_collection.action_view'.freeze
61
+ RENDER_LAYOUT_EVENT_NAME = 'render_layout.action_view'.freeze
64
62
 
65
63
  def metric_action(name)
66
64
  case name
67
65
  when /#{RENDER_TEMPLATE_EVENT_NAME}$/o then 'Rendering'
68
66
  when RENDER_PARTIAL_EVENT_NAME then 'Partial'
69
67
  when RENDER_COLLECTION_EVENT_NAME then 'Partial'
68
+ when RENDER_LAYOUT_EVENT_NAME then 'Layout'
69
+ else NewRelic::UNKNOWN
70
70
  end
71
71
  end
72
72
 
@@ -12,7 +12,7 @@ DependencyDetection.defer do
12
12
  end
13
13
 
14
14
  executes do
15
- NewRelic::Agent.logger.info('Installing ActiveJob instrumentation')
15
+ NewRelic::Agent.logger.info('Installing base ActiveJob instrumentation')
16
16
 
17
17
  ActiveSupport.on_load(:active_job) do
18
18
  ActiveJob::Base.around_enqueue do |job, block|
@@ -26,6 +26,19 @@ DependencyDetection.defer do
26
26
  NewRelic::Agent::PrependSupportability.record_metrics_for(ActiveJob::Base)
27
27
  end
28
28
  end
29
+
30
+ executes do
31
+ if defined?(ActiveSupport) &&
32
+ ActiveJob.respond_to?(:gem_version) &&
33
+ ActiveJob.gem_version >= Gem::Version.new('6.0.0') &&
34
+ !NewRelic::Agent.config[:disable_activejob] &&
35
+ !NewRelic::Agent::Instrumentation::ActiveJobSubscriber.subscribed?
36
+ NewRelic::Agent.logger.info('Installing notifications based ActiveJob instrumentation')
37
+
38
+ ActiveSupport::Notifications.subscribe(/\A[^\.]+\.active_job\z/,
39
+ NewRelic::Agent::Instrumentation::ActiveJobSubscriber.new)
40
+ end
41
+ end
29
42
  end
30
43
 
31
44
  module NewRelic
@@ -0,0 +1,41 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/notifications_subscriber'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ module Instrumentation
10
+ class ActiveJobSubscriber < NotificationsSubscriber
11
+ PAYLOAD_KEYS = %i[adapter db_runtime error job wait]
12
+
13
+ def add_segment_params(segment, payload)
14
+ PAYLOAD_KEYS.each do |key|
15
+ segment.params[key] = payload[key] if payload.key?(key)
16
+ end
17
+ end
18
+
19
+ def metric_name(name, payload)
20
+ queue = payload[:job].queue_name
21
+ method = method_from_name(name)
22
+ "Ruby/ActiveJob/#{queue}/#{method}"
23
+ end
24
+
25
+ PATTERN = /\A([^\.]+)\.active_job\z/
26
+
27
+ METHOD_NAME_MAPPING = Hash.new do |h, k|
28
+ if PATTERN =~ k
29
+ h[k] = $1
30
+ else
31
+ h[k] = NewRelic::UNKNOWN
32
+ end
33
+ end
34
+
35
+ def method_from_name(name)
36
+ METHOD_NAME_MAPPING[name]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -7,6 +7,10 @@ require 'new_relic/agent/instrumentation/active_storage_subscriber'
7
7
  DependencyDetection.defer do
8
8
  named :active_storage
9
9
 
10
+ depends_on do
11
+ !NewRelic::Agent.config[:disable_active_storage]
12
+ end
13
+
10
14
  depends_on do
11
15
  defined?(ActiveStorage) &&
12
16
  !NewRelic::Agent::Instrumentation::ActiveStorageSubscriber.subscribed?
@@ -8,36 +8,9 @@ module NewRelic
8
8
  module Agent
9
9
  module Instrumentation
10
10
  class ActiveStorageSubscriber < NotificationsSubscriber
11
- def start(name, id, payload)
12
- return unless state.is_execution_traced?
13
-
14
- start_segment(name, id, payload)
15
- rescue => e
16
- log_notification_error(e, name, 'start')
17
- end
18
-
19
- def finish(name, id, payload)
20
- return unless state.is_execution_traced?
21
-
22
- finish_segment(id, payload)
23
- rescue => e
24
- log_notification_error(e, name, 'finish')
25
- end
26
-
27
- def start_segment(name, id, payload)
28
- segment = Tracer.start_segment(name: metric_name(name, payload))
11
+ def add_segment_params(segment, payload)
29
12
  segment.params[:key] = payload[:key]
30
13
  segment.params[:exist] = payload[:exist] if payload.key?(:exist)
31
- push_segment(id, segment)
32
- end
33
-
34
- def finish_segment(id, payload)
35
- if segment = pop_segment(id)
36
- if exception = exception_object(payload)
37
- segment.notice_error(exception)
38
- end
39
- segment.finish
40
- end
41
14
  end
42
15
 
43
16
  def metric_name(name, payload)
@@ -47,13 +20,12 @@ module NewRelic
47
20
  end
48
21
 
49
22
  PATTERN = /\Aservice_([^\.]*)\.active_storage\z/
50
- UNKNOWN = "unknown".freeze
51
23
 
52
24
  METHOD_NAME_MAPPING = Hash.new do |h, k|
53
25
  if PATTERN =~ k
54
26
  h[k] = $1
55
27
  else
56
- h[k] = UNKNOWN
28
+ h[k] = NewRelic::UNKNOWN
57
29
  end
58
30
  end
59
31
 
@@ -2,11 +2,26 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- # This is a helper file that will allow apps using ActiveSupport without Rails
6
- # to still leverage all ActiveSupport based instrumentation functionality
7
- # offered by the agent that would otherwise be gated by the detection of Rails.
5
+ require 'new_relic/agent/instrumentation/active_support_subscriber'
8
6
 
9
- # ActiveSupport notifications custom events
10
- if !defined?(Rails) && defined?(ActiveSupport::Notifications) && defined?(ActiveSupport::IsolatedExecutionState)
11
- require_relative 'rails_notifications/custom_events'
7
+ DependencyDetection.defer do
8
+ named :active_support
9
+
10
+ depends_on do
11
+ !NewRelic::Agent.config[:disable_active_support]
12
+ end
13
+
14
+ depends_on do
15
+ defined?(ActiveSupport) &&
16
+ !NewRelic::Agent::Instrumentation::ActiveSupportSubscriber.subscribed?
17
+ end
18
+
19
+ executes do
20
+ NewRelic::Agent.logger.info('Installing ActiveSupport instrumentation')
21
+ end
22
+
23
+ executes do
24
+ ActiveSupport::Notifications.subscribe(/\.active_support$/,
25
+ NewRelic::Agent::Instrumentation::ActiveSupportSubscriber.new)
26
+ end
12
27
  end
@@ -0,0 +1,41 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/agent/instrumentation/notifications_subscriber'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ module Instrumentation
10
+ class ActiveSupportSubscriber < NotificationsSubscriber
11
+ def add_segment_params(segment, payload)
12
+ segment.params[:key] = payload[:key]
13
+ segment.params[:store] = payload[:store]
14
+ segment.params[:hit] = payload[:hit] if payload.key?(:hit)
15
+ segment.params[:super_operation] = payload[:super_operation] if payload.key?(:super_operation)
16
+ segment
17
+ end
18
+
19
+ def metric_name(name, payload)
20
+ store = payload[:store]
21
+ method = method_from_name(name)
22
+ "Ruby/ActiveSupport#{"/#{store}" if store}/#{method}"
23
+ end
24
+
25
+ PATTERN = /\Acache_([^\.]*)\.active_support\z/
26
+
27
+ METHOD_NAME_MAPPING = Hash.new do |h, k|
28
+ if PATTERN =~ k
29
+ h[k] = $1
30
+ else
31
+ h[k] = NewRelic::UNKNOWN
32
+ end
33
+ end
34
+
35
+ def method_from_name(name)
36
+ METHOD_NAME_MAPPING[name]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,12 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ # This is a helper file that will allow apps using ActiveSupport without Rails
6
+ # to still leverage all ActiveSupport based instrumentation functionality
7
+ # offered by the agent that would otherwise be gated by the detection of Rails.
8
+
9
+ # ActiveSupport notifications custom events
10
+ if !defined?(Rails) && defined?(ActiveSupport::Notifications) && defined?(ActiveSupport::IsolatedExecutionState)
11
+ require_relative 'rails_notifications/custom_events'
12
+ end
@@ -47,6 +47,47 @@ module NewRelic
47
47
  end
48
48
  end
49
49
 
50
+ def start(name, id, payload)
51
+ return unless state.is_execution_traced?
52
+
53
+ start_segment(name, id, payload)
54
+ rescue => e
55
+ log_notification_error(e, name, 'start')
56
+ end
57
+
58
+ def finish(name, id, payload)
59
+ return unless state.is_execution_traced?
60
+
61
+ finish_segment(id, payload)
62
+ rescue => e
63
+ log_notification_error(e, name, 'finish')
64
+ end
65
+
66
+ def start_segment(name, id, payload)
67
+ segment = Tracer.start_segment(name: metric_name(name, payload))
68
+ add_segment_params(segment, payload)
69
+ push_segment(id, segment)
70
+ end
71
+
72
+ def finish_segment(id, payload)
73
+ if segment = pop_segment(id)
74
+ if exception = exception_object(payload)
75
+ segment.notice_error(exception)
76
+ end
77
+ segment.finish
78
+ end
79
+ end
80
+
81
+ # for subclasses
82
+ def add_segment_params(segment, payload)
83
+ # no op
84
+ end
85
+
86
+ # for subclasses
87
+ def metric_name(name, payload)
88
+ "Ruby/#{name}"
89
+ end
90
+
50
91
  def log_notification_error(error, name, event_type)
51
92
  # These are important enough failures that we want the backtraces
52
93
  # logged at error level, hence the explicit log_exception call.
@@ -9,9 +9,9 @@ DependencyDetection.defer do
9
9
  @name = :action_cable_notifications
10
10
 
11
11
  depends_on do
12
- defined?(Rails::VERSION::MAJOR) &&
13
- Rails::VERSION::MAJOR.to_i >= 5 &&
14
- defined?(ActionCable)
12
+ defined?(ActionCable::VERSION::MAJOR) &&
13
+ ActionCable::VERSION::MAJOR.to_i >= 5 &&
14
+ defined?(ActiveSupport)
15
15
  end
16
16
 
17
17
  depends_on do
@@ -25,7 +25,7 @@ DependencyDetection.defer do
25
25
 
26
26
  executes do
27
27
  # enumerate the specific events we want so that we do not get unexpected additions in the future
28
- ActiveSupport::Notifications.subscribe(/(perform_action|transmit)\.action_cable/,
28
+ ActiveSupport::Notifications.subscribe(/\A(?:perform_action|transmit|broadcast)\.action_cable\z/,
29
29
  NewRelic::Agent::Instrumentation::ActionCableSubscriber.new)
30
30
 
31
31
  ActiveSupport.on_load(:action_cable) do
@@ -3,6 +3,7 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  require 'new_relic/agent/instrumentation/action_controller_subscriber'
6
+ require 'new_relic/agent/instrumentation/action_controller_other_subscriber'
6
7
  require 'new_relic/agent/prepend_supportability'
7
8
 
8
9
  DependencyDetection.defer do
@@ -13,7 +14,8 @@ DependencyDetection.defer do
13
14
  end
14
15
 
15
16
  depends_on do
16
- defined?(ActionController) && (defined?(ActionController::Base) || defined?(ActionController::API))
17
+ !NewRelic::Agent.config[:disable_action_controller] &&
18
+ defined?(ActionController) && (defined?(ActionController::Base) || defined?(ActionController::API))
17
19
  end
18
20
 
19
21
  executes do
@@ -29,5 +31,15 @@ DependencyDetection.defer do
29
31
 
30
32
  NewRelic::Agent::Instrumentation::ActionControllerSubscriber \
31
33
  .subscribe(/^process_action.action_controller$/)
34
+
35
+ subs = %w[send_file
36
+ send_data
37
+ redirect_to
38
+ halted_callback
39
+ unpermitted_parameters]
40
+
41
+ # have to double escape period because its going from string -> regex
42
+ NewRelic::Agent::Instrumentation::ActionControllerOtherSubscriber \
43
+ .subscribe(Regexp.new("^(#{subs.join('|')})\\.action_controller$"))
32
44
  end
33
45
  end
@@ -6,7 +6,7 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 8
9
- MINOR = 15
9
+ MINOR = 16
10
10
  TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
data/newrelic.yml CHANGED
@@ -169,12 +169,21 @@ common: &default_settings
169
169
  # If true, disables Action Cable instrumentation.
170
170
  # disable_action_cable_instrumentation: false
171
171
 
172
- # If true, disables instrumentation for Active Record 4, 5, and 6.
172
+ # If true, disables Action Mailbox instrumentation.
173
+ # disable_action_mailbox: false
174
+
175
+ # If true, disables Action Mailer instrumentation.
176
+ # disable_action_mailer: false
177
+
178
+ # If true, disables instrumentation for Active Record 4+
173
179
  # disable_active_record_notifications: false
174
180
 
175
181
  # If true, disables Active Storage instrumentation.
176
182
  # disable_active_storage: false
177
183
 
184
+ # If true, disables Active Support instrumentation.
185
+ # disable_active_support: false
186
+
178
187
  # If true, disables Active Job instrumentation.
179
188
  # disable_activejob: false
180
189
 
data/newrelic_rpm.gemspec CHANGED
@@ -60,5 +60,6 @@ https://github.com/newrelic/newrelic-ruby-agent/
60
60
  s.add_development_dependency 'rubocop-rake' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
61
61
  s.add_development_dependency 'simplecov' if RUBY_VERSION >= '2.7.0'
62
62
  s.add_development_dependency 'thor' unless ENV['CI']
63
+ s.add_development_dependency 'warning' if RUBY_VERSION >= '2.4.0'
63
64
  s.add_development_dependency 'yard', "#{RUBY_VERSION < '2.3.0' ? '0.9.26' : '> 0.9.26'}"
64
65
  end
data/test/agent_helper.rb CHANGED
@@ -1021,6 +1021,6 @@ def defer_testing_to_min_supported_rails(test_file, min_rails_version, supports_
1021
1021
 
1022
1022
  yield
1023
1023
  else
1024
- puts "Skipping tests in #{test_file} because Rails >= #{min_rails_version} is unavailable"
1024
+ puts "Skipping tests in #{File.basename(test_file)} because Rails >= #{min_rails_version} is unavailable" if ENV["VERBOSE_TEST_OUTPUT"]
1025
1025
  end
1026
1026
  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: 8.15.0
4
+ version: 8.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanna McClure
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-01-09 00:00:00.000000000 Z
14
+ date: 2023-02-06 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -97,6 +97,20 @@ dependencies:
97
97
  - - ">="
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
+ - !ruby/object:Gem::Dependency
101
+ name: warning
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
100
114
  - !ruby/object:Gem::Dependency
101
115
  name: yard
102
116
  requirement: !ruby/object:Gem::Requirement
@@ -241,9 +255,17 @@ files:
241
255
  - lib/new_relic/agent/http_clients/uri_util.rb
242
256
  - lib/new_relic/agent/instrumentation.rb
243
257
  - lib/new_relic/agent/instrumentation/action_cable_subscriber.rb
258
+ - lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb
244
259
  - lib/new_relic/agent/instrumentation/action_controller_subscriber.rb
260
+ - lib/new_relic/agent/instrumentation/action_dispatch.rb
261
+ - lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb
262
+ - lib/new_relic/agent/instrumentation/action_mailbox.rb
263
+ - lib/new_relic/agent/instrumentation/action_mailbox_subscriber.rb
264
+ - lib/new_relic/agent/instrumentation/action_mailer.rb
265
+ - lib/new_relic/agent/instrumentation/action_mailer_subscriber.rb
245
266
  - lib/new_relic/agent/instrumentation/action_view_subscriber.rb
246
267
  - lib/new_relic/agent/instrumentation/active_job.rb
268
+ - lib/new_relic/agent/instrumentation/active_job_subscriber.rb
247
269
  - lib/new_relic/agent/instrumentation/active_merchant.rb
248
270
  - lib/new_relic/agent/instrumentation/active_record.rb
249
271
  - lib/new_relic/agent/instrumentation/active_record_helper.rb
@@ -257,6 +279,7 @@ files:
257
279
  - lib/new_relic/agent/instrumentation/active_support_logger/chain.rb
258
280
  - lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb
259
281
  - lib/new_relic/agent/instrumentation/active_support_logger/prepend.rb
282
+ - lib/new_relic/agent/instrumentation/active_support_subscriber.rb
260
283
  - lib/new_relic/agent/instrumentation/acts_as_solr.rb
261
284
  - lib/new_relic/agent/instrumentation/authlogic.rb
262
285
  - lib/new_relic/agent/instrumentation/bunny.rb
@@ -272,6 +295,7 @@ files:
272
295
  - lib/new_relic/agent/instrumentation/curb/chain.rb
273
296
  - lib/new_relic/agent/instrumentation/curb/instrumentation.rb
274
297
  - lib/new_relic/agent/instrumentation/curb/prepend.rb
298
+ - lib/new_relic/agent/instrumentation/custom_events.rb
275
299
  - lib/new_relic/agent/instrumentation/custom_events_subscriber.rb
276
300
  - lib/new_relic/agent/instrumentation/data_mapper.rb
277
301
  - lib/new_relic/agent/instrumentation/delayed_job/chain.rb