newrelic_rpm 9.3.0 → 9.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.build_ignore +6 -1
- data/CHANGELOG.md +43 -0
- data/README.md +4 -0
- data/lib/new_relic/agent/configuration/default_source.rb +25 -2
- data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
- data/lib/new_relic/agent/distributed_tracing.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -2
- data/lib/new_relic/agent/instrumentation/memcache.rb +2 -2
- data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
- data/lib/new_relic/agent/instrumentation/roda/chain.rb +43 -0
- data/lib/new_relic/agent/instrumentation/roda/instrumentation.rb +52 -0
- data/lib/new_relic/agent/instrumentation/roda/prepend.rb +24 -0
- data/lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb +30 -0
- data/lib/new_relic/agent/instrumentation/roda.rb +33 -0
- data/lib/new_relic/agent/instrumentation/sequel.rb +1 -1
- data/lib/new_relic/agent/log_event_attributes.rb +1 -1
- data/lib/new_relic/agent/new_relic_service.rb +33 -17
- data/lib/new_relic/agent/pipe_service.rb +1 -1
- data/lib/new_relic/agent/tracer.rb +4 -3
- data/lib/new_relic/agent/transaction/request_attributes.rb +45 -7
- data/lib/new_relic/agent/transaction.rb +5 -4
- data/lib/new_relic/agent/utilization/vendor.rb +5 -7
- data/lib/new_relic/agent.rb +1 -1
- data/lib/new_relic/cli/command.rb +1 -0
- data/lib/new_relic/control/class_methods.rb +1 -7
- data/lib/new_relic/control/frameworks/roda.rb +20 -0
- data/lib/new_relic/language_support.rb +5 -0
- data/lib/new_relic/noticed_error.rb +5 -2
- data/lib/new_relic/rack/browser_monitoring.rb +1 -1
- data/lib/new_relic/version.rb +1 -1
- data/lib/tasks/bump_version.rake +1 -1
- data/lib/tasks/config.rake +3 -2
- data/lib/tasks/helpers/config.html.erb +93 -0
- data/lib/tasks/helpers/format.rb +11 -7
- data/lib/tasks/helpers/version_bump.rb +2 -2
- data/lib/tasks/newrelicyml.rake +1 -1
- data/newrelic.yml +11 -0
- data/newrelic_rpm.gemspec +8 -5
- data/test/agent_helper.rb +1027 -0
- metadata +26 -8
- data/lib/tasks/helpers/removers.rb +0 -33
- data/lib/tasks/multiverse.rake +0 -6
- data/lib/tasks/multiverse.rb +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8e0198f3fe3562d84248d3be65acdc8e7ae92e0ca27ecaa1023ca2303152464
|
4
|
+
data.tar.gz: 6d721589df2371d8d63b96eba38adddff1e534678e19b9adfdf028807233d109
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e72bfc0219779d6912631c687d64d896b5becf69be013b35f0a88729ebc444f592d72261b2620d7fdc419b7f3fe0557af56e7e3577a6a482c1cdd4fd19aea7a
|
7
|
+
data.tar.gz: 99a8dee22642c178cf8800e1eec28544262c9b09abcfeb9f856495121de33d5fe1e33483e233d41d746d37cb2e0a2377db00a446d80653816dc252967b64b3e1
|
data/.build_ignore
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
.github
|
1
|
+
.github/
|
2
2
|
.gitignore
|
3
3
|
.project
|
4
4
|
.rubocop.yml
|
@@ -19,3 +19,8 @@ lefthook.yml
|
|
19
19
|
log/
|
20
20
|
README.md
|
21
21
|
test/
|
22
|
+
lib/tasks/bump_version.rb
|
23
|
+
lib/tasks/coverage_report.rb
|
24
|
+
lib/tasks/multiverse.rake
|
25
|
+
lib/tasks/multiverse.rb
|
26
|
+
lib/tasks/tests.rb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,48 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes
|
2
2
|
|
3
|
+
## v9.4.0
|
4
|
+
|
5
|
+
Version 9.4.0 of the agent adds [Roda](https://roda.jeremyevans.net/) instrumentation, adds a new `allow_all_headers` configuration option to permit capturing all HTTP headers, introduces improved error tracking functionality by associating a transaction id with each error, and uses more reliable network timeout logic.
|
6
|
+
|
7
|
+
- **Feature: Add Roda instrumentation**
|
8
|
+
|
9
|
+
[Roda](https://roda.jeremyevans.net/) is a now an instrumented framework. The agent currently supports Roda versions 3.19.0+. [PR#2144](https://github.com/newrelic/newrelic-ruby-agent/pull/2144)
|
10
|
+
|
11
|
+
- **Feature: New allow_all_headers configuration option**
|
12
|
+
|
13
|
+
A new `allow_all_headers` configuration option brings parity with the [Node.js agent](https://docs.newrelic.com/docs/release-notes/agent-release-notes/nodejs-release-notes/node-agent-270/) to capture all HTTP request headers.
|
14
|
+
|
15
|
+
This configuration option:
|
16
|
+
* Defaults to `false`
|
17
|
+
* Is not compatible with high security mode
|
18
|
+
* Requires Rack version 2 or higher (as does Ruby on Rails version 5 and above)
|
19
|
+
* Respects all existing behavior for the `attributes.include` and `attributes.exclude` [configuration options](https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration/#attributes)
|
20
|
+
* Captures the additional headers as attributes prefixed with `request.headers.`
|
21
|
+
|
22
|
+
This work was done in response to a feature request submitted by community member [@jamesarosen](https://github.com/jamesarosen). Thank you very much, @jamesarosen! [Issue#1029](https://github.com/newrelic/newrelic-ruby-agent/issues/1029)
|
23
|
+
|
24
|
+
- **Feature: Improved error tracking transaction linking**
|
25
|
+
|
26
|
+
Errors tracked and sent to the New Relic errors inbox will now be associated with a transaction id to enable improved UI/UX associations between transactions and errors. [PR#2035](https://github.com/newrelic/newrelic-ruby-agent/pull/2035)
|
27
|
+
|
28
|
+
- **Feature: Use Net::HTTP native timeout logic**
|
29
|
+
|
30
|
+
In line with current Ruby best practices, make use of Net::HTTP's own timeout logic and avoid the use of `Timeout.timeout()` when possible. The agent's data transmissions and cloud provider detection routines have been updated accordingly. [PR#2147](https://github.com/newrelic/newrelic-ruby-agent/pull/2147)
|
31
|
+
|
32
|
+
## v9.3.1
|
33
|
+
|
34
|
+
Version 9.3.1 of the agent fixes `NewRelic::Agent.require_test_helper`.
|
35
|
+
|
36
|
+
- **Bugfix: Fix NewRelic::Agent.require_test_helper**
|
37
|
+
|
38
|
+
Version 9.3.0 of the agent made a change to the files distributed with the gem. This change unintentionally broke the `NewRelic::Agent.require_test_helper` API by removing the `test/agent_helper.rb` file. The file has been added back to the gem. This change also removes the `lib/new_relic/build.rb` file from the list because it is no longer created with our current release process.
|
39
|
+
|
40
|
+
Our thanks go to [@ajesler](https://github.com/ajesler) for reporting this issue and writing a test for the bug. [Issue#2113](https://github.com/newrelic/newrelic-ruby-agent/issues/2113), [PR#2115](https://github.com/newrelic/newrelic-ruby-agent/pull/2115), [Issue#2117](https://github.com/newrelic/newrelic-ruby-agent/issues/2117), [PR#2118](https://github.com/newrelic/newrelic-ruby-agent/pull/2118)
|
41
|
+
|
42
|
+
- **Source Documentation: update the Rack spec URL**
|
43
|
+
|
44
|
+
Community member [@olleolleolle](https://github.com/olleolleolle) noticed that our source code was referencing a now defunct URL for the Rack specification and submitted [PR#2121](https://github.com/newrelic/newrelic-ruby-agent/pull/2121) to update it. He also provided a terrific recommendation that we automate the checking of links to proactively catch defunct ones in future. Thanks, @olleolleolle!
|
45
|
+
|
3
46
|
## v9.3.0
|
4
47
|
|
5
48
|
Version 9.3.0 of the agent adds log-level filtering, adds custom attributes for log events, and updates instrumentation for Action Cable. It also provides fixes for how `Fiber` args are treated, Code-Level Metrics, unnecessary files being included in the gem, and `NewRelic::Agent::Logging::DecoratingFormatter#clear_tags!` being incorrectly private.
|
data/README.md
CHANGED
@@ -134,6 +134,10 @@ The New Relic Ruby agent may use source code from third-party libraries. When us
|
|
134
134
|
|
135
135
|
## Thank You
|
136
136
|
|
137
|
+
We always look forward to connecting with the community. We welcome [contributions](https://github.com/newrelic/newrelic-ruby-agent#contributing) to our source code and suggestions for improvements, and would love to hear about what you like and want to see in the future.
|
138
|
+
|
139
|
+
Visit our [project board](https://github.com/orgs/newrelic/projects/84/) to see what's upcoming in a future release, what we're currently working on, and what we're planning next.
|
140
|
+
|
137
141
|
Thank you,
|
138
142
|
|
139
143
|
New Relic Ruby agent team
|
@@ -24,7 +24,7 @@ module NewRelic
|
|
24
24
|
# Does not appear in logs.
|
25
25
|
def self.deprecated_description(new_setting, description)
|
26
26
|
link_ref = new_setting.to_s.tr('.', '-')
|
27
|
-
%{Please see: [#{new_setting}](
|
27
|
+
%{Please see: [#{new_setting}](##{link_ref}). \n\n#{description}}
|
28
28
|
end
|
29
29
|
|
30
30
|
class Boolean
|
@@ -115,6 +115,7 @@ module NewRelic
|
|
115
115
|
:rails_notifications
|
116
116
|
end
|
117
117
|
when defined?(::Sinatra) && defined?(::Sinatra::Base) then :sinatra
|
118
|
+
when defined?(::Roda) then :roda
|
118
119
|
when defined?(::NewRelic::IA) then :external
|
119
120
|
else :ruby
|
120
121
|
end
|
@@ -818,6 +819,13 @@ module NewRelic
|
|
818
819
|
:description => 'If `true`, the agent captures metrics related to logging for your application.'
|
819
820
|
},
|
820
821
|
# Attributes
|
822
|
+
:'allow_all_headers' => {
|
823
|
+
:default => false,
|
824
|
+
:public => true,
|
825
|
+
:type => Boolean,
|
826
|
+
:allowed_from_server => false,
|
827
|
+
:description => 'If `true`, enables capture of all HTTP request headers for all destinations.'
|
828
|
+
},
|
821
829
|
:'attributes.enabled' => {
|
822
830
|
:default => true,
|
823
831
|
:public => true,
|
@@ -1042,7 +1050,7 @@ module NewRelic
|
|
1042
1050
|
:allowed_from_server => true,
|
1043
1051
|
:deprecated => true,
|
1044
1052
|
:description => deprecated_description(
|
1045
|
-
:'distributed_tracing
|
1053
|
+
:'distributed_tracing.enabled',
|
1046
1054
|
'If `true`, enables [cross-application tracing](/docs/agents/ruby-agent/features/cross-application-tracing-ruby/) when `distributed_tracing.enabled` is set to `false`.'
|
1047
1055
|
)
|
1048
1056
|
},
|
@@ -1227,6 +1235,13 @@ module NewRelic
|
|
1227
1235
|
:allowed_from_server => false,
|
1228
1236
|
:description => 'If `true`, disables [Sidekiq instrumentation](/docs/agents/ruby-agent/background-jobs/sidekiq-instrumentation).'
|
1229
1237
|
},
|
1238
|
+
:disable_roda_auto_middleware => {
|
1239
|
+
:default => false,
|
1240
|
+
:public => true,
|
1241
|
+
:type => Boolean,
|
1242
|
+
:allowed_from_server => false,
|
1243
|
+
:description => 'If `true`, disables agent middleware for Roda. This middleware is responsible for advanced feature support such as [page load timing](/docs/browser/new-relic-browser/getting-started/new-relic-browser) and [error collection](/docs/apm/applications-menu/events/view-apm-error-analytics).'
|
1244
|
+
},
|
1230
1245
|
:disable_sinatra_auto_middleware => {
|
1231
1246
|
:default => false,
|
1232
1247
|
:public => true,
|
@@ -1564,6 +1579,14 @@ module NewRelic
|
|
1564
1579
|
:allowed_from_server => false,
|
1565
1580
|
:description => 'Controls auto-instrumentation of resque at start up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1566
1581
|
},
|
1582
|
+
:'instrumentation.roda' => {
|
1583
|
+
:default => 'auto',
|
1584
|
+
:public => true,
|
1585
|
+
:type => String,
|
1586
|
+
:dynamic_name => true,
|
1587
|
+
:allowed_from_server => false,
|
1588
|
+
:description => 'Controls auto-instrumentation of Roda at start up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1589
|
+
},
|
1567
1590
|
:'instrumentation.sinatra' => {
|
1568
1591
|
:default => 'auto',
|
1569
1592
|
:public => true,
|
@@ -101,7 +101,7 @@ module NewRelic
|
|
101
101
|
end
|
102
102
|
else
|
103
103
|
::NewRelic::Agent.logger.info("#{environment_key} does not have a corresponding configuration setting (#{config_key} does not exist).")
|
104
|
-
::NewRelic::Agent.logger.info('Run `rake newrelic:config:docs` or visit https://newrelic.com/docs/ruby/ruby-agent-configuration to see a list of available configuration settings.')
|
104
|
+
::NewRelic::Agent.logger.info('Run `rake newrelic:config:docs` or visit https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration to see a list of available configuration settings.')
|
105
105
|
self[config_key] = value
|
106
106
|
end
|
107
107
|
end
|
@@ -87,7 +87,7 @@ module NewRelic
|
|
87
87
|
# header-friendly string returned from
|
88
88
|
# {DistributedTracePayload#http_safe}
|
89
89
|
#
|
90
|
-
# @param
|
90
|
+
# @param transport_type [String] May be one of: +HTTP+, +HTTPS+, +Kafka+, +JMS+,
|
91
91
|
# +IronMQ+, +AMQP+, +Queue+, +Other+. Values are
|
92
92
|
# case sensitive. All other values result in +Unknown+
|
93
93
|
#
|
@@ -23,7 +23,7 @@ module NewRelic
|
|
23
23
|
|
24
24
|
def metric_name(name, payload)
|
25
25
|
controller_name = controller_name_for_metric(payload)
|
26
|
-
"Ruby/ActionController#{"/#{controller_name}" if controller_name}/#{name.gsub(
|
26
|
+
"Ruby/ActionController#{"/#{controller_name}" if controller_name}/#{name.gsub('.action_controller', '')}"
|
27
27
|
end
|
28
28
|
|
29
29
|
def controller_name_for_metric(payload)
|
@@ -41,8 +41,6 @@ module NewRelic
|
|
41
41
|
clazz.extend(ClassMethodsShim)
|
42
42
|
end
|
43
43
|
|
44
|
-
def new_relic_trace_controller_action(*args); yield; end
|
45
|
-
|
46
44
|
def perform_action_with_newrelic_trace(*args); yield; end
|
47
45
|
end
|
48
46
|
|
@@ -245,6 +243,7 @@ module NewRelic
|
|
245
243
|
when :background then ::NewRelic::Agent::Transaction::TASK_PREFIX
|
246
244
|
when :rack then ::NewRelic::Agent::Transaction::RACK_PREFIX
|
247
245
|
when :uri then ::NewRelic::Agent::Transaction::CONTROLLER_PREFIX
|
246
|
+
when :roda then ::NewRelic::Agent::Transaction::RODA_PREFIX
|
248
247
|
when :sinatra then ::NewRelic::Agent::Transaction::SINATRA_PREFIX
|
249
248
|
when :middleware then ::NewRelic::Agent::Transaction::MIDDLEWARE_PREFIX
|
250
249
|
when :grape then ::NewRelic::Agent::Transaction::GRAPE_PREFIX
|
@@ -5,8 +5,8 @@
|
|
5
5
|
# NOTE: there are multiple implementations of the Memcached client in Ruby,
|
6
6
|
# each with slightly different APIs and semantics.
|
7
7
|
# See:
|
8
|
-
#
|
9
|
-
#
|
8
|
+
# https://rubygems.org/gems/Ruby-MemCache (Gem: Ruby-MemCache)
|
9
|
+
# https://github.com/mperham/memcache-client (Gem: memcache-client)
|
10
10
|
# https://github.com/mperham/dalli (Gem: dalli)
|
11
11
|
|
12
12
|
require_relative 'memcache/helper'
|
@@ -5,7 +5,7 @@
|
|
5
5
|
module NewRelic
|
6
6
|
module Agent
|
7
7
|
module Instrumentation
|
8
|
-
# https://newrelic.com/docs/features/tracking-front-end-time
|
8
|
+
# https://docs.newrelic.com/docs/features/tracking-front-end-time
|
9
9
|
# Record queue time metrics based on any of three headers
|
10
10
|
# which can be set on the request.
|
11
11
|
module QueueTime
|
@@ -0,0 +1,43 @@
|
|
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
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module Roda
|
7
|
+
module Chain
|
8
|
+
def self.instrument!
|
9
|
+
::Roda.class_eval do
|
10
|
+
include ::NewRelic::Agent::Instrumentation::Roda::Tracer
|
11
|
+
|
12
|
+
alias_method(:_roda_handle_main_route_without_tracing, :_roda_handle_main_route)
|
13
|
+
|
14
|
+
def _roda_handle_main_route(*args)
|
15
|
+
_roda_handle_main_route_with_tracing(*args) do
|
16
|
+
_roda_handle_main_route_without_tracing(*args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Build
|
24
|
+
module Chain
|
25
|
+
def self.instrument!
|
26
|
+
::Roda.class_eval do
|
27
|
+
include ::NewRelic::Agent::Instrumentation::Roda::Tracer
|
28
|
+
|
29
|
+
class << self
|
30
|
+
alias_method(:build_rack_app_without_tracing, :build_rack_app)
|
31
|
+
|
32
|
+
def build_rack_app
|
33
|
+
build_rack_app_with_tracing do
|
34
|
+
build_rack_app_without_tracing
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,52 @@
|
|
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
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module Roda
|
7
|
+
module Tracer
|
8
|
+
include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
9
|
+
|
10
|
+
def self.included(clazz)
|
11
|
+
clazz.extend(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def newrelic_middlewares
|
15
|
+
middlewares = [NewRelic::Rack::BrowserMonitoring]
|
16
|
+
if NewRelic::Rack::AgentHooks.needed?
|
17
|
+
middlewares << NewRelic::Rack::AgentHooks
|
18
|
+
end
|
19
|
+
middlewares
|
20
|
+
end
|
21
|
+
|
22
|
+
def build_rack_app_with_tracing
|
23
|
+
unless NewRelic::Agent.config[:disable_roda_auto_middleware]
|
24
|
+
newrelic_middlewares.each do |middleware_class|
|
25
|
+
self.use middleware_class
|
26
|
+
end
|
27
|
+
end
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
|
31
|
+
# Roda makes use of Rack, so we can get params from the request object
|
32
|
+
def rack_request_params
|
33
|
+
begin
|
34
|
+
@_request.params
|
35
|
+
rescue => e
|
36
|
+
NewRelic::Agent.logger.debug('Failed to get params from Rack request.', e)
|
37
|
+
NewRelic::EMPTY_HASH
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def _roda_handle_main_route_with_tracing(*args)
|
42
|
+
perform_action_with_newrelic_trace(
|
43
|
+
category: :roda,
|
44
|
+
name: TransactionNamer.transaction_name(request),
|
45
|
+
params: ::NewRelic::Agent::ParameterFiltering::apply_filters(request.env, rack_request_params)
|
46
|
+
) do
|
47
|
+
yield
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module Roda
|
7
|
+
module Prepend
|
8
|
+
include ::NewRelic::Agent::Instrumentation::Roda::Tracer
|
9
|
+
|
10
|
+
def _roda_handle_main_route(*args)
|
11
|
+
_roda_handle_main_route_with_tracing(*args) { super }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Build
|
16
|
+
module Prepend
|
17
|
+
include ::NewRelic::Agent::Instrumentation::Roda::Tracer
|
18
|
+
def build_rack_app
|
19
|
+
build_rack_app_with_tracing { super }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
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
|
+
module NewRelic
|
6
|
+
module Agent
|
7
|
+
module Instrumentation
|
8
|
+
module Roda
|
9
|
+
module TransactionNamer
|
10
|
+
extend self
|
11
|
+
|
12
|
+
ROOT = '/'.freeze
|
13
|
+
REGEX_MULTIPLE_SLASHES = %r{^[/^\A]*(.*?)[/$?\z]*$}.freeze
|
14
|
+
|
15
|
+
def transaction_name(request)
|
16
|
+
path = request.path || ::NewRelic::Agent::UNKNOWN_METRIC
|
17
|
+
name = path.gsub(REGEX_MULTIPLE_SLASHES, '\1') # remove any rogue slashes
|
18
|
+
name = ROOT if name.empty?
|
19
|
+
name = "#{request.request_method} #{name}" if request.respond_to?(:request_method)
|
20
|
+
|
21
|
+
name
|
22
|
+
rescue => e
|
23
|
+
::NewRelic::Agent.logger.debug("#{e.class} : #{e.message} - Error encountered trying to identify Roda transaction name")
|
24
|
+
::NewRelic::Agent::UNKNOWN_METRIC
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
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_relative 'roda/instrumentation'
|
6
|
+
|
7
|
+
DependencyDetection.defer do
|
8
|
+
named :roda
|
9
|
+
|
10
|
+
depends_on do
|
11
|
+
defined?(Roda) &&
|
12
|
+
Gem::Version.new(Roda::RodaVersion) >= Gem::Version.new('3.19.0') &&
|
13
|
+
Roda::RodaPlugins::Base::ClassMethods.private_method_defined?(:build_rack_app) &&
|
14
|
+
Roda::RodaPlugins::Base::InstanceMethods.method_defined?(:_roda_handle_main_route)
|
15
|
+
end
|
16
|
+
|
17
|
+
executes do
|
18
|
+
require_relative '../../rack/agent_hooks'
|
19
|
+
require_relative '../../rack/browser_monitoring'
|
20
|
+
|
21
|
+
NewRelic::Agent.logger.info('Installing Roda instrumentation')
|
22
|
+
|
23
|
+
if use_prepend?
|
24
|
+
require_relative 'roda/prepend'
|
25
|
+
prepend_instrument Roda.singleton_class, NewRelic::Agent::Instrumentation::Roda::Build::Prepend
|
26
|
+
prepend_instrument Roda, NewRelic::Agent::Instrumentation::Roda::Prepend
|
27
|
+
else
|
28
|
+
require_relative 'roda/chain'
|
29
|
+
chain_instrument NewRelic::Agent::Instrumentation::Roda::Build::Chain
|
30
|
+
chain_instrument NewRelic::Agent::Instrumentation::Roda::Chain
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -30,7 +30,7 @@ DependencyDetection.defer do
|
|
30
30
|
else
|
31
31
|
NewRelic::Agent.logger.info('Detected Sequel version %s.' % [Sequel::VERSION])
|
32
32
|
NewRelic::Agent.logger.info('Please see additional documentation: ' +
|
33
|
-
'https://newrelic.com/docs/ruby/sequel-instrumentation')
|
33
|
+
'https://docs.newrelic.com/docs/apm/agents/ruby-agent/frameworks/sequel-instrumentation/')
|
34
34
|
end
|
35
35
|
|
36
36
|
Sequel.synchronize { Sequel::DATABASES.dup }.each do |db|
|
@@ -10,7 +10,7 @@ module NewRelic
|
|
10
10
|
ATTRIBUTE_VALUE_CHARACTER_LIMIT = 4094
|
11
11
|
|
12
12
|
def add_custom_attributes(attributes)
|
13
|
-
return if @custom_attribute_limit_reached
|
13
|
+
return if defined?(@custom_attribute_limit_reached) && @custom_attribute_limit_reached
|
14
14
|
|
15
15
|
attributes.each do |key, value|
|
16
16
|
next if absent?(key) || absent?(value)
|
@@ -3,7 +3,6 @@
|
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
require 'zlib'
|
6
|
-
require 'timeout'
|
7
6
|
require 'new_relic/agent/audit_logger'
|
8
7
|
require 'new_relic/agent/new_relic_service/encoders'
|
9
8
|
require 'new_relic/agent/new_relic_service/marshaller'
|
@@ -19,7 +18,13 @@ module NewRelic
|
|
19
18
|
|
20
19
|
# These include Errno connection errors, and all indicate that the
|
21
20
|
# underlying TCP connection may be in a bad state.
|
22
|
-
CONNECTION_ERRORS = [
|
21
|
+
CONNECTION_ERRORS = [Net::OpenTimeout, Net::ReadTimeout, EOFError, SystemCallError, SocketError]
|
22
|
+
# TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until Ruby 2.6.
|
23
|
+
# Once support for Ruby 2.5 is dropped, we should simply include
|
24
|
+
# Net::WriteTimeout in the connection errors array directly instead
|
25
|
+
# of with a conditional
|
26
|
+
CONNECTION_ERRORS << Net::WriteTimeout if defined?(Net::WriteTimeout)
|
27
|
+
CONNECTION_ERRORS.freeze
|
23
28
|
|
24
29
|
# The maximum number of times to attempt an HTTP request
|
25
30
|
MAX_ATTEMPTS = 2
|
@@ -319,13 +324,15 @@ module NewRelic
|
|
319
324
|
|
320
325
|
def start_connection(conn)
|
321
326
|
NewRelic::Agent.logger.debug("Opening TCP connection to #{conn.address}:#{conn.port}")
|
322
|
-
|
323
|
-
conn
|
327
|
+
conn.start
|
324
328
|
end
|
325
329
|
|
326
330
|
def setup_connection_timeouts(conn)
|
327
|
-
|
328
|
-
conn.read_timeout =
|
331
|
+
conn.open_timeout = @request_timeout
|
332
|
+
conn.read_timeout = @request_timeout
|
333
|
+
# TODO: MAJOR VERSION - #write_timeout= requires Ruby 2.6+, so remove
|
334
|
+
# the conditional check once support for Ruby 2.5 is dropped
|
335
|
+
conn.write_timeout = @request_timeout if conn.respond_to?(:write_timeout=)
|
329
336
|
|
330
337
|
if conn.respond_to?(:keep_alive_timeout) && NewRelic::Agent.config[:aggressive_keepalive]
|
331
338
|
conn.keep_alive_timeout = NewRelic::Agent.config[:keep_alive_timeout]
|
@@ -362,8 +369,8 @@ module NewRelic
|
|
362
369
|
conn = create_http_connection
|
363
370
|
start_connection(conn)
|
364
371
|
conn
|
365
|
-
rescue
|
366
|
-
::NewRelic::Agent.logger.info('
|
372
|
+
rescue Net::OpenTimeout
|
373
|
+
::NewRelic::Agent.logger.info('Timed out while attempting to connect. For SSL issues, you may need to install system-level CA Certificates to be used by Net::HTTP.')
|
367
374
|
raise
|
368
375
|
end
|
369
376
|
|
@@ -436,13 +443,9 @@ module NewRelic
|
|
436
443
|
end
|
437
444
|
|
438
445
|
def attempt_request(request, opts)
|
439
|
-
response = nil
|
440
446
|
conn = http_connection
|
441
447
|
::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}")
|
442
|
-
|
443
|
-
response = conn.request(request)
|
444
|
-
end
|
445
|
-
response
|
448
|
+
conn.request(request)
|
446
449
|
end
|
447
450
|
|
448
451
|
def handle_error_response(response, endpoint)
|
@@ -450,7 +453,9 @@ module NewRelic
|
|
450
453
|
when Net::HTTPRequestTimeOut,
|
451
454
|
Net::HTTPTooManyRequests,
|
452
455
|
Net::HTTPInternalServerError,
|
453
|
-
Net::HTTPServiceUnavailable
|
456
|
+
Net::HTTPServiceUnavailable,
|
457
|
+
Net::OpenTimeout,
|
458
|
+
Net::ReadTimeout
|
454
459
|
handle_server_connection_exception(response, endpoint)
|
455
460
|
when Net::HTTPBadRequest,
|
456
461
|
Net::HTTPForbidden,
|
@@ -471,9 +476,20 @@ module NewRelic
|
|
471
476
|
when Net::HTTPGone
|
472
477
|
handle_gone_response(response, endpoint)
|
473
478
|
else
|
474
|
-
|
475
|
-
|
476
|
-
|
479
|
+
# TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until
|
480
|
+
# Ruby 2.6, so it can't be included in the case statement
|
481
|
+
# as a constant and instead needs to be found here. Once
|
482
|
+
# support for Ruby 2.5 is dropped, we should have
|
483
|
+
# Net::WriteTimeout sit in the 'when' clause above alongside
|
484
|
+
# Net::OpenTimeout and Net::ReadTimeout and this entire if/else
|
485
|
+
# conditional can be removed.
|
486
|
+
if response.respond_to?(:name) && response.name == 'Net::WriteTimeout'
|
487
|
+
handle_server_connection_exception(response, endpoint)
|
488
|
+
else
|
489
|
+
record_endpoint_attempts_supportability_metrics(endpoint)
|
490
|
+
record_error_response_supportability_metrics(response.code)
|
491
|
+
raise UnrecoverableServerException, "#{response.code}: #{response.message}"
|
492
|
+
end
|
477
493
|
end
|
478
494
|
response
|
479
495
|
end
|
@@ -15,7 +15,7 @@ module NewRelic
|
|
15
15
|
if @pipe && @pipe.parent_pid != $$
|
16
16
|
@pipe.after_fork_in_child
|
17
17
|
else
|
18
|
-
NewRelic::Agent.logger.error('No communication channel to parent process, please see https://newrelic.com/docs/ruby/resque-instrumentation for more information.')
|
18
|
+
NewRelic::Agent.logger.error('No communication channel to parent process, please see https://docs.newrelic.com/docs/apm/agents/ruby-agent/background-jobs/resque-instrumentation/ for more information.')
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -66,9 +66,10 @@ module NewRelic
|
|
66
66
|
#
|
67
67
|
# @api public
|
68
68
|
def transaction_sampled?
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
txn = current_transaction
|
70
|
+
return false unless txn
|
71
|
+
|
72
|
+
txn.sampled?
|
72
73
|
end
|
73
74
|
alias_method :sampled?, :transaction_sampled?
|
74
75
|
|
@@ -8,11 +8,17 @@ module NewRelic
|
|
8
8
|
module Agent
|
9
9
|
class Transaction
|
10
10
|
class RequestAttributes
|
11
|
-
|
12
|
-
|
11
|
+
# the HTTP standard has "referrer" mispelled as "referer"
|
12
|
+
attr_reader :accept, :content_length, :content_type, :host, :other_headers, :port, :referer, :request_method,
|
13
|
+
:request_path, :user_agent
|
13
14
|
|
14
15
|
HTTP_ACCEPT_HEADER_KEY = 'HTTP_ACCEPT'.freeze
|
15
16
|
|
17
|
+
BASE_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE HTTP_ACCEPT HTTP_REFERER HTTP_USER_AGENT PATH_INFO REMOTE_HOST
|
18
|
+
REQUEST_METHOD REQUEST_URI SERVER_PORT].freeze
|
19
|
+
|
20
|
+
ATTRIBUTE_PREFIX = 'request.headers.'
|
21
|
+
|
16
22
|
def initialize(request)
|
17
23
|
@request_path = path_from_request(request)
|
18
24
|
@referer = referer_from_request(request)
|
@@ -23,6 +29,7 @@ module NewRelic
|
|
23
29
|
@port = port_from_request(request)
|
24
30
|
@user_agent = attribute_from_request(request, :user_agent)
|
25
31
|
@request_method = attribute_from_request(request, :request_method)
|
32
|
+
@other_headers = other_headers_from_request(request)
|
26
33
|
end
|
27
34
|
|
28
35
|
def assign_agent_attributes(txn)
|
@@ -31,14 +38,17 @@ module NewRelic
|
|
31
38
|
AttributeFilter::DST_ERROR_COLLECTOR
|
32
39
|
|
33
40
|
if referer
|
34
|
-
|
41
|
+
destinations = allow_other_headers? ? default_destinations : AttributeFilter::DST_ERROR_COLLECTOR
|
42
|
+
txn.add_agent_attribute(:'request.headers.referer', referer, destinations)
|
35
43
|
end
|
36
44
|
|
37
45
|
if request_path
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
46
|
+
destinations = if allow_other_headers?
|
47
|
+
default_destinations
|
48
|
+
else
|
49
|
+
AttributeFilter::DST_TRANSACTION_TRACER | AttributeFilter::DST_ERROR_COLLECTOR
|
50
|
+
end
|
51
|
+
txn.add_agent_attribute(:'request.uri', request_path, destinations)
|
42
52
|
end
|
43
53
|
|
44
54
|
if accept
|
@@ -64,6 +74,14 @@ module NewRelic
|
|
64
74
|
if request_method
|
65
75
|
txn.add_agent_attribute(:'request.method', request_method, default_destinations)
|
66
76
|
end
|
77
|
+
|
78
|
+
if port && allow_other_headers?
|
79
|
+
txn.add_agent_attribute(:'request.headers.port', port, default_destinations)
|
80
|
+
end
|
81
|
+
|
82
|
+
other_headers.each do |header, value|
|
83
|
+
txn.add_agent_attribute(header, value, default_destinations)
|
84
|
+
end
|
67
85
|
end
|
68
86
|
|
69
87
|
private
|
@@ -116,6 +134,26 @@ module NewRelic
|
|
116
134
|
env[key]
|
117
135
|
end
|
118
136
|
end
|
137
|
+
|
138
|
+
def allow_other_headers?
|
139
|
+
NewRelic::Agent.config[:allow_all_headers] && !NewRelic::Agent.config[:high_security]
|
140
|
+
end
|
141
|
+
|
142
|
+
def other_headers_from_request(request)
|
143
|
+
# confirm that `request` is an instance of `Rack::Request` by checking
|
144
|
+
# for #each_header
|
145
|
+
return NewRelic::EMPTY_HASH unless allow_other_headers? && request.respond_to?(:each_header)
|
146
|
+
|
147
|
+
request.each_header.with_object({}) do |(header, value), hash|
|
148
|
+
next if BASE_HEADERS.include?(header)
|
149
|
+
|
150
|
+
hash[formatted_header(header)] = value
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def formatted_header(raw_name)
|
155
|
+
"#{ATTRIBUTE_PREFIX}#{NewRelic::LanguageSupport.camelize_with_first_letter_downcased(raw_name)}".to_sym
|
156
|
+
end
|
119
157
|
end
|
120
158
|
end
|
121
159
|
end
|