newrelic_rpm 9.10.1 → 9.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -1
- data/lib/new_relic/agent/aws.rb +10 -4
- data/lib/new_relic/agent/configuration/default_source.rb +22 -6
- data/lib/new_relic/agent/error_collector.rb +14 -10
- data/lib/new_relic/agent/instrumentation/aws_sqs/chain.rb +37 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs/instrumentation.rb +67 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs/prepend.rb +21 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs.rb +25 -0
- data/lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb +8 -2
- data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +22 -1
- data/lib/new_relic/version.rb +2 -2
- data/lib/tasks/gha.rake +31 -0
- data/lib/tasks/instrumentation_generator/instrumentation.thor +29 -21
- data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +4 -4
- data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +1 -1
- data/newrelic.yml +17 -11
- data/newrelic_rpm.gemspec +2 -0
- metadata +36 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc36449c6f2ea3322f353181809c05d3e84e28f85fb15544c82e088946384046
|
4
|
+
data.tar.gz: f8fa907597f05f47c5dbe9c38a005cb1d09f971183aa7075664e6ade029186fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 622cdf275eb70aa1f57e027f2e73559855c17c4351741c80ec0db8ae45b773f2d7aa2831ae562e228b24a71a0532ae93dced167be3ecfdd3561886224d212070
|
7
|
+
data.tar.gz: a68a148e494bfc0e5f9da3c369eb56f7170664e78ffd12cc178e77b7361da39edefbc967b5c71c2905b993b5d4075b2189abc3ec7692081d6b4dd422149902f3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,39 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes
|
2
2
|
|
3
|
+
## v9.11.0
|
4
|
+
|
5
|
+
Version 9.11.0 introduces instrumentation for the aws-sdk-sqs gem, fixes a bug related to expected errors not bearing a "true" value for the "expected" attribute if expected as a result of an HTTP status code match and changes the way Stripe instrumentation metrics are named to prevent high-cardinality issues.
|
6
|
+
|
7
|
+
- **Feature: Add instrumentation for SQS**
|
8
|
+
|
9
|
+
The agent has added instrumentation for the [aws-sdk-sqs gem](https://rubygems.org/gems/aws-sdk-sqs). The agent will now record message broker spans for SQS client calls made with the aws-sdk-sqs gem. [PR#2679](https://github.com/newrelic/newrelic-ruby-agent/pull/2679)
|
10
|
+
|
11
|
+
- **Bugfix: HTTP status code based expected errors will now have an "expected" value of "true"**
|
12
|
+
|
13
|
+
Previously when an error was treated as expected by the agent as a result of a matching HTTP status code being found in the :'error_collector.expected_status_codes' configuration setting, the error would not appear with an "expected" attribute value of "true" in the errors in the errors inbox. [PR#2710](https://github.com/newrelic/newrelic-ruby-agent/pull/2710)
|
14
|
+
|
15
|
+
- **Bugfix: Stripe metric names will no longer include full request paths to limit the unique name count**
|
16
|
+
|
17
|
+
The Stripe instrumentation introduced in agent version v9.5.0 produced instrumentation metric names that used the full Stripe request path. For any significant Stripe usage, this could quickly lead to very large number of distinct metric names. Now only the API version and the category part of the request path are included in the metric name which still includes the "Stripe" opener and method (ex: "get") closer. Thanks to [@jdelStrother](https://github.com/jdelStrother) and [@jsneedles](https://github.com/jsneedles) for bringing this issue to our attention and providing terrific information explaining the problem and potential paths to resolution. [PR#2716](https://github.com/newrelic/newrelic-ruby-agent/pull/2716)
|
18
|
+
|
19
|
+
## v9.10.2
|
20
|
+
|
21
|
+
Version 9.10.2 fixes a bug related to the new DynamoDB instrumentation and removes `Rails::Command::RakeCommand` from the default list of denylisted constants.
|
22
|
+
|
23
|
+
- **Bugfix: DynamoDB instrumentation logging errors when trying to get account_id**
|
24
|
+
|
25
|
+
When trying to access data needed to add the `account_id` to the DynamoDB span, the agent encountered an error when certain credentials classes were used. This has been fixed. Thanks to [@kichik](https://github.com/kichik) for bringing this to our attention. [PR#2684](https://github.com/newrelic/newrelic-ruby-agent/pull/2684)
|
26
|
+
|
27
|
+
- **Bugfix: Remove Rails::Command::RakeCommand from the default list of autostart.denylisted_constants**
|
28
|
+
|
29
|
+
The default value for the `autostart.denylisted_constants` configuration was changed in 9.10.0 to include `Rails::Command::RunnerCommand` and `Rails::Command::RakeCommand`. The inclusion of `Rails::Command::RakeCommand` prevented the agent from starting automatically when Solid Queue was started using `bin/rails solid_queue:start`. We recognize there are many commands nested within `Rails::Command::RakeCommand` and have decided to remove it from the default list. We encourage users who do not want the agent to run on `Rails::Command::RakeCommand` to add the constant to their configuration. This can be accomplished by adding the following to your `newrelic.yml` file:
|
30
|
+
|
31
|
+
```yaml
|
32
|
+
autostart.denylisted_constants: "Rails::Command::ConsoleCommand,Rails::Command::CredentialsCommand,Rails::Command::Db::System::ChangeCommand,Rails::Command::DbConsoleCommand,Rails::Command::DestroyCommand,Rails::Command::DevCommand,Rails::Command::EncryptedCommand,Rails::Command::GenerateCommand,Rails::Command::InitializersCommand,Rails::Command::NotesCommand,Rails::Command::RakeCommand,Rails::Command::RoutesCommand,Rails::Command::RunnerCommand,Rails::Command::SecretsCommand,Rails::Console,Rails::DBConsole"
|
33
|
+
```
|
34
|
+
|
35
|
+
Thank you, [@edariedl](https://github.com/edariedl), for reporting this issue. [Issue#2677](https://github.com/newrelic/newrelic-ruby-agent/issues/2677) [PR#2694](https://github.com/newrelic/newrelic-ruby-agent/pull/2694)
|
36
|
+
|
3
37
|
## v9.10.1
|
4
38
|
|
5
39
|
- **Bugfix: Incompatibility with Bootstrap**
|
@@ -11,7 +45,7 @@ Version 9.10.1 fixes an incompatibility between the agent and the [Bootstrap](ht
|
|
11
45
|
Version 9.10.0 introduces instrumentation for DynamoDB, adds a new feature to automatically apply nonces from the Rails content security policy, fixes a bug that would cause an expected error to negatively impact a transaction's Apdex, and fixes the agent's autostart logic so that by default `rails runner` and `rails db` commands will not cause the agent to start.
|
12
46
|
|
13
47
|
- **Feature: Add instrumentation for DynamoDB**
|
14
|
-
|
48
|
+
|
15
49
|
The agent has added instrumentation for the aws-sdk-dynamodb gem. The agent will now record datastore spans for DynamoDB client calls made with the aws-sdk-dynamodb gem. [PR#2642](https://github.com/newrelic/newrelic-ruby-agent/pull/2642)
|
16
50
|
|
17
51
|
- **Feature: Automatically apply nonces from the Rails content security policy**
|
data/lib/new_relic/agent/aws.rb
CHANGED
@@ -8,15 +8,21 @@ module NewRelic
|
|
8
8
|
CHARACTERS = %w[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 2 3 4 5 6 7].freeze
|
9
9
|
HEX_MASK = '7fffffffff80'
|
10
10
|
|
11
|
-
def self.create_arn(service, resource,
|
12
|
-
region = config.region
|
13
|
-
account_id = NewRelic::Agent::Aws.convert_access_key_to_account_id(config.credentials.access_key_id)
|
14
|
-
|
11
|
+
def self.create_arn(service, resource, region, account_id)
|
15
12
|
"arn:aws:#{service}:#{region}:#{account_id}:#{resource}"
|
16
13
|
rescue => e
|
17
14
|
NewRelic::Agent.logger.warn("Failed to create ARN: #{e}")
|
18
15
|
end
|
19
16
|
|
17
|
+
def self.get_account_id(config)
|
18
|
+
access_key_id = config.credentials.credentials.access_key_id if config&.credentials&.credentials&.respond_to?(:access_key_id)
|
19
|
+
return unless access_key_id
|
20
|
+
|
21
|
+
NewRelic::Agent::Aws.convert_access_key_to_account_id(access_key_id)
|
22
|
+
rescue => e
|
23
|
+
NewRelic::Agent.logger.debug("Failed to create account id: #{e}")
|
24
|
+
end
|
25
|
+
|
20
26
|
def self.convert_access_key_to_account_id(access_key)
|
21
27
|
decoded_key = Integer(decode_to_hex(access_key[4..-1]), 16)
|
22
28
|
mask = Integer(HEX_MASK, 16)
|
@@ -480,7 +480,12 @@ module NewRelic
|
|
480
480
|
:type => Boolean,
|
481
481
|
:allowed_from_server => false,
|
482
482
|
:description => <<~DESC
|
483
|
-
|
483
|
+
The exit handler that sends all cached data to the collector before shutting down is forcibly installed. \
|
484
|
+
This is true even when it detects scenarios where it generally should not be. The known use case for this \
|
485
|
+
option is when Sinatra runs as an embedded service within another framework. The agent detects the Sinatra \
|
486
|
+
app and skips the `at_exit` handler as a result. Sinatra classically runs the entire application in an \
|
487
|
+
`at_exit` block and would otherwise misbehave if the agent's `at_exit` handler was also installed in those \
|
488
|
+
circumstances. Note: `send_data_on_exit` should also be set to `true` in tandem with this setting.
|
484
489
|
DESC
|
485
490
|
},
|
486
491
|
:high_security => {
|
@@ -1077,7 +1082,6 @@ module NewRelic
|
|
1077
1082
|
Rails::Command::GenerateCommand
|
1078
1083
|
Rails::Command::InitializersCommand
|
1079
1084
|
Rails::Command::NotesCommand
|
1080
|
-
Rails::Command::RakeCommand
|
1081
1085
|
Rails::Command::RoutesCommand
|
1082
1086
|
Rails::Command::RunnerCommand
|
1083
1087
|
Rails::Command::SecretsCommand
|
@@ -1144,8 +1148,12 @@ module NewRelic
|
|
1144
1148
|
:public => true,
|
1145
1149
|
:type => Integer,
|
1146
1150
|
:allowed_from_server => true,
|
1147
|
-
:
|
1148
|
-
:
|
1151
|
+
:dynamic_name => true,
|
1152
|
+
:description => <<~DESC
|
1153
|
+
* Specify a maximum number of custom events to buffer in memory at a time.'
|
1154
|
+
* When configuring the agent for [AI monitoring](/docs/ai-monitoring/intro-to-ai-monitoring), \
|
1155
|
+
set to max value `100000`. This ensures the agent captures the maximum amount of LLM events.
|
1156
|
+
DESC
|
1149
1157
|
},
|
1150
1158
|
# Datastore tracer
|
1151
1159
|
:'datastore_tracer.database_name_reporting.enabled' => {
|
@@ -1450,6 +1458,14 @@ module NewRelic
|
|
1450
1458
|
:allowed_from_server => false,
|
1451
1459
|
:description => 'Controls auto-instrumentation of bunny at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1452
1460
|
},
|
1461
|
+
:'instrumentation.aws_sqs' => {
|
1462
|
+
:default => 'auto',
|
1463
|
+
:public => true,
|
1464
|
+
:type => String,
|
1465
|
+
:dynamic_name => true,
|
1466
|
+
:allowed_from_server => false,
|
1467
|
+
:description => 'Controls auto-instrumentation of the aws-sdk-sqs library at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1468
|
+
},
|
1453
1469
|
:'instrumentation.dynamodb' => {
|
1454
1470
|
:default => 'auto',
|
1455
1471
|
:public => true,
|
@@ -1983,8 +1999,8 @@ module NewRelic
|
|
1983
1999
|
:allowed_from_server => true,
|
1984
2000
|
:description => <<~DESC
|
1985
2001
|
* Defines the maximum number of span events reported from a single harvest. Any Integer between `1` and `10000` is valid.'
|
1986
|
-
|
1987
|
-
|
2002
|
+
* When configuring the agent for [AI monitoring](/docs/ai-monitoring/intro-to-ai-monitoring), set to max value `10000`.\
|
2003
|
+
This ensures the agent captures the maximum amount of distributed traces.
|
1988
2004
|
DESC
|
1989
2005
|
},
|
1990
2006
|
# Strip exception messages
|
@@ -237,7 +237,8 @@ module NewRelic
|
|
237
237
|
end
|
238
238
|
|
239
239
|
def notice_segment_error(segment, exception, options = {})
|
240
|
-
|
240
|
+
status_code = process_http_status_code(exception, options)
|
241
|
+
return if skip_notice_error?(exception, status_code)
|
241
242
|
|
242
243
|
options.merge!(segment.llm_event.error_attributes(exception)) if segment.llm_event
|
243
244
|
|
@@ -250,15 +251,13 @@ module NewRelic
|
|
250
251
|
|
251
252
|
# See NewRelic::Agent.notice_error for options and commentary
|
252
253
|
def notice_error(exception, options = {}, span_id = nil)
|
253
|
-
|
254
|
-
transaction = state.current_transaction
|
255
|
-
status_code = transaction&.http_response_code
|
256
|
-
|
254
|
+
status_code = process_http_status_code(exception, options)
|
257
255
|
return if skip_notice_error?(exception, status_code)
|
258
256
|
|
259
257
|
tag_exception(exception)
|
260
258
|
|
261
|
-
|
259
|
+
state = ::NewRelic::Agent::Tracer.state
|
260
|
+
if options[:expected]
|
262
261
|
increment_expected_error_count!(state, exception)
|
263
262
|
else
|
264
263
|
increment_error_count!(state, exception, options)
|
@@ -266,10 +265,8 @@ module NewRelic
|
|
266
265
|
|
267
266
|
noticed_error = create_noticed_error(exception, options)
|
268
267
|
error_trace_aggregator.add_to_error_queue(noticed_error)
|
269
|
-
|
270
|
-
|
271
|
-
span_id ||= transaction&.current_segment ? transaction.current_segment.guid : nil
|
272
|
-
error_event_aggregator.record(noticed_error, payload, span_id)
|
268
|
+
span_id ||= state.current_transaction&.current_segment&.guid
|
269
|
+
error_event_aggregator.record(noticed_error, state.current_transaction&.payload, span_id)
|
273
270
|
exception
|
274
271
|
rescue => e
|
275
272
|
::NewRelic::Agent.logger.warn("Failure when capturing error '#{exception}':", e)
|
@@ -359,6 +356,13 @@ module NewRelic
|
|
359
356
|
def error_group_callback
|
360
357
|
NewRelic::Agent.error_group_callback
|
361
358
|
end
|
359
|
+
|
360
|
+
def process_http_status_code(exception, options)
|
361
|
+
status_code = ::NewRelic::Agent::Tracer.state.current_transaction&.http_response_code
|
362
|
+
options[:expected] = true if !options[:expected] && @error_filter.expected?(exception, status_code)
|
363
|
+
|
364
|
+
status_code
|
365
|
+
end
|
362
366
|
end
|
363
367
|
end
|
364
368
|
end
|
@@ -0,0 +1,37 @@
|
|
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 AwsSqs::Chain
|
7
|
+
def self.instrument!
|
8
|
+
::Aws::SQS::Client.class_eval do
|
9
|
+
include NewRelic::Agent::Instrumentation::AwsSqs
|
10
|
+
|
11
|
+
alias_method(:send_message_without_new_relic, :send_message)
|
12
|
+
|
13
|
+
def send_message(*args)
|
14
|
+
send_message_with_new_relic(*args) do
|
15
|
+
send_message_without_new_relic(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method(:send_message_batch_without_new_relic, :send_message_batch)
|
20
|
+
|
21
|
+
def send_message_batch(*args)
|
22
|
+
send_message_batch_with_new_relic(*args) do
|
23
|
+
send_message_batch_without_new_relic(*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method(:receive_message_without_new_relic, :receive_message)
|
28
|
+
|
29
|
+
def receive_message(*args)
|
30
|
+
receive_message_with_new_relic(*args) do
|
31
|
+
receive_message_without_new_relic(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,67 @@
|
|
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 AwsSqs
|
7
|
+
MESSAGING_LIBRARY = 'SQS'
|
8
|
+
|
9
|
+
def send_message_with_new_relic(*args)
|
10
|
+
with_tracing(:produce, args) do
|
11
|
+
yield
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def send_message_batch_with_new_relic(*args)
|
16
|
+
with_tracing(:produce, args) do
|
17
|
+
yield
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def receive_message_with_new_relic(*args)
|
22
|
+
with_tracing(:consume, args) do
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_tracing(action, params)
|
28
|
+
segment = nil
|
29
|
+
begin
|
30
|
+
info = get_url_info(params[0])
|
31
|
+
segment = NewRelic::Agent::Tracer.start_message_broker_segment(
|
32
|
+
action: action,
|
33
|
+
library: MESSAGING_LIBRARY,
|
34
|
+
destination_type: :queue,
|
35
|
+
destination_name: info[:queue_name]
|
36
|
+
)
|
37
|
+
add_aws_attributes(segment, info)
|
38
|
+
rescue => e
|
39
|
+
NewRelic::Agent.logger.error('Error starting message broker segment in Aws::SQS::Client', e)
|
40
|
+
end
|
41
|
+
NewRelic::Agent::Tracer.capture_segment_error(segment) do
|
42
|
+
yield
|
43
|
+
end
|
44
|
+
ensure
|
45
|
+
segment&.finish
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def add_aws_attributes(segment, info)
|
51
|
+
return unless segment
|
52
|
+
|
53
|
+
segment.add_agent_attribute('messaging.system', 'aws_sqs')
|
54
|
+
segment.add_agent_attribute('cloud.region', config&.region)
|
55
|
+
segment.add_agent_attribute('cloud.account.id', info[:account_id])
|
56
|
+
segment.add_agent_attribute('messaging.destination.name', info[:queue_name])
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_url_info(params)
|
60
|
+
split = params[:queue_url].split('/')
|
61
|
+
{
|
62
|
+
queue_name: split.last,
|
63
|
+
account_id: split[-2]
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,21 @@
|
|
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 AwsSqs::Prepend
|
7
|
+
include NewRelic::Agent::Instrumentation::AwsSqs
|
8
|
+
|
9
|
+
def send_message(*args)
|
10
|
+
send_message_with_new_relic(*args) { super }
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_message_batch(*args)
|
14
|
+
send_message_batch_with_new_relic(*args) { super }
|
15
|
+
end
|
16
|
+
|
17
|
+
def receive_message(*args)
|
18
|
+
receive_message_with_new_relic(*args) { super }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
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 'aws_sqs/instrumentation'
|
6
|
+
require_relative 'aws_sqs/chain'
|
7
|
+
require_relative 'aws_sqs/prepend'
|
8
|
+
|
9
|
+
DependencyDetection.defer do
|
10
|
+
named :aws_sqs
|
11
|
+
|
12
|
+
depends_on do
|
13
|
+
defined?(Aws::SQS::Client)
|
14
|
+
end
|
15
|
+
|
16
|
+
executes do
|
17
|
+
NewRelic::Agent.logger.info('Installing aws-sdk-sqs instrumentation')
|
18
|
+
|
19
|
+
if use_prepend?
|
20
|
+
prepend_instrument Aws::SQS::Client, NewRelic::Agent::Instrumentation::AwsSqs::Prepend
|
21
|
+
else
|
22
|
+
chain_instrument NewRelic::Agent::Instrumentation::AwsSqs::Chain
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -49,10 +49,16 @@ module NewRelic::Agent::Instrumentation
|
|
49
49
|
@nr_captured_request = yield
|
50
50
|
end
|
51
51
|
|
52
|
+
def nr_account_id
|
53
|
+
return @nr_account_id if defined?(@nr_account_id)
|
54
|
+
|
55
|
+
@nr_account_id = NewRelic::Agent::Aws.get_account_id(config)
|
56
|
+
end
|
57
|
+
|
52
58
|
def get_arn(params)
|
53
|
-
return unless params[:table_name]
|
59
|
+
return unless params[:table_name] && nr_account_id
|
54
60
|
|
55
|
-
NewRelic::Agent::Aws.create_arn(PRODUCT.downcase, "table/#{params[:table_name]}", config)
|
61
|
+
NewRelic::Agent::Aws.create_arn(PRODUCT.downcase, "table/#{params[:table_name]}", config&.region, nr_account_id)
|
56
62
|
end
|
57
63
|
end
|
58
64
|
end
|
@@ -10,6 +10,7 @@ module NewRelic
|
|
10
10
|
EVENT_ATTRIBUTES = %i[http_status method num_retries path request_id].freeze
|
11
11
|
ATTRIBUTE_NAMESPACE = 'stripe.user_data'
|
12
12
|
ATTRIBUTE_FILTER_TYPES = %i[include exclude].freeze
|
13
|
+
PATH_PORTION_PATTERN = %r{^/([^/]+/[^/]+)(?:/|\z)}.freeze
|
13
14
|
|
14
15
|
def start_segment(event)
|
15
16
|
return unless is_execution_traced?
|
@@ -39,7 +40,27 @@ module NewRelic
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def metric_name(event)
|
42
|
-
|
43
|
+
# Grab only the first 2 items from the slash (/) delimited event path.
|
44
|
+
# These items are the API version string and the category. Grabbing
|
45
|
+
# any more of the path will result in unique method names that will
|
46
|
+
# easily grow to be too numerous to sort through in the UI and
|
47
|
+
# possibly even violate default New Relic metric count thresholds.
|
48
|
+
# See newrelic/newrelic-ruby-agent#2654 and
|
49
|
+
# newrelic/newrelic-ruby-agent#2709 for more details.
|
50
|
+
#
|
51
|
+
# In Ruby v3.4 benchmarks, using regex to get at the first two path
|
52
|
+
# elements was seen as more performant than using String#split.
|
53
|
+
#
|
54
|
+
# Regex legend:
|
55
|
+
#
|
56
|
+
# ^ = starts with
|
57
|
+
# / = a literal '/'
|
58
|
+
# () = capture
|
59
|
+
# (?:) = don't capture
|
60
|
+
# [^/]+ = 1 or more characters that are not '/'
|
61
|
+
# /|\z = a literal '/' OR the end of the string
|
62
|
+
path_portion = event.path =~ PATH_PORTION_PATTERN ? Regexp.last_match(1) : NewRelic::UNKNOWN
|
63
|
+
"Stripe/#{path_portion}/#{event.method}"
|
43
64
|
end
|
44
65
|
|
45
66
|
def add_stripe_attributes(segment, event)
|
data/lib/new_relic/version.rb
CHANGED
data/lib/tasks/gha.rake
ADDED
@@ -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 'yaml'
|
6
|
+
require_relative 'helpers/version_bump'
|
7
|
+
|
8
|
+
# gha = GitHub Actions
|
9
|
+
namespace :gha do
|
10
|
+
# See .github/versions.yml
|
11
|
+
desc 'Update 3rd party action versions across all workflows'
|
12
|
+
task :update_versions do
|
13
|
+
gh_dir = File.expand_path('../../../.github', __FILE__)
|
14
|
+
info = YAML.load_file(File.join(gh_dir, 'versions.yml'))
|
15
|
+
workflows = Dir.glob(File.join(gh_dir, 'workflows', '*.yml'))
|
16
|
+
workflows.each do |workflow|
|
17
|
+
original = File.read(workflow)
|
18
|
+
modified = original.dup
|
19
|
+
info.each do |action, settings|
|
20
|
+
modified.gsub!(/uses: #{action}.*$/, "uses: #{action}@#{settings[:sha]} # tag #{settings[:tag]}")
|
21
|
+
end
|
22
|
+
|
23
|
+
if original != modified
|
24
|
+
File.open(workflow, 'w') { |f| f.puts modified }
|
25
|
+
puts "Updated #{workflow} with changes"
|
26
|
+
else
|
27
|
+
puts "#{workflow} remains unchanged"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -31,15 +31,16 @@ class Instrumentation < Thor
|
|
31
31
|
|
32
32
|
def scaffold(name)
|
33
33
|
@name = name
|
34
|
+
@snake_name = snake_name(@name)
|
34
35
|
@method = options[:method] if options[:method]
|
35
36
|
@args = options[:args] if options[:args]
|
36
37
|
@class_name = ::NewRelic::LanguageSupport.camelize(name)
|
37
|
-
base_path = "#{INSTRUMENTATION_ROOT}#{
|
38
|
+
base_path = "#{INSTRUMENTATION_ROOT}#{@snake_name}"
|
38
39
|
|
39
40
|
empty_directory(base_path)
|
40
41
|
create_instrumentation_files(base_path)
|
41
|
-
append_to_default_source(name)
|
42
|
-
append_to_newrelic_yml(name)
|
42
|
+
append_to_default_source(@name, @snake_name)
|
43
|
+
# append_to_newrelic_yml(@name, @snake_name) # This is now done on release, we don't need it anymore, but leaving it to be sure.
|
43
44
|
create_tests(name)
|
44
45
|
end
|
45
46
|
|
@@ -69,53 +70,60 @@ class Instrumentation < Thor
|
|
69
70
|
def create_tests(name)
|
70
71
|
@name = name
|
71
72
|
@instrumentation_method_global_erb_snippet = '<%= $instrumentation_method %>'
|
72
|
-
|
73
|
+
@snake_name = snake_name(@name)
|
74
|
+
base_path = "#{MULTIVERSE_SUITE_ROOT}#{@snake_name}"
|
73
75
|
empty_directory(base_path)
|
74
76
|
template('templates/Envfile.tt', "#{base_path}/Envfile")
|
75
|
-
template('templates/test.tt', "#{base_path}/#{@
|
77
|
+
template('templates/test.tt', "#{base_path}/#{@snake_name}_instrumentation_test.rb")
|
76
78
|
|
77
79
|
empty_directory("#{base_path}/config")
|
78
80
|
template('templates/newrelic.yml.tt', "#{base_path}/config/newrelic.yml")
|
79
81
|
end
|
80
82
|
|
81
|
-
def append_to_default_source(name)
|
83
|
+
def append_to_default_source(name, snake_name)
|
82
84
|
insert_into_file(
|
83
85
|
DEFAULT_SOURCE_LOCATION,
|
84
|
-
config_block(name
|
86
|
+
config_block(name, snake_name),
|
85
87
|
after: ":description => 'Controls auto-instrumentation of bunny at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
86
88
|
},\n"
|
87
89
|
)
|
88
90
|
end
|
89
91
|
|
90
|
-
def append_to_newrelic_yml(name)
|
92
|
+
def append_to_newrelic_yml(name, snake_name)
|
91
93
|
insert_into_file(
|
92
94
|
NEWRELIC_YML_LOCATION,
|
93
|
-
yaml_block(name),
|
95
|
+
yaml_block(name, snake_name),
|
94
96
|
after: "# instrumentation.bunny: auto\n"
|
95
97
|
)
|
96
98
|
end
|
97
99
|
|
98
|
-
def config_block(name)
|
99
|
-
<<~
|
100
|
-
|
101
|
-
|
102
|
-
:
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
100
|
+
def config_block(name, snake_name)
|
101
|
+
# Don't change to <<~
|
102
|
+
# We want to preserve the whitespace so the config is correctly indented
|
103
|
+
<<-CONFIG
|
104
|
+
:'instrumentation.#{snake_name}' => {
|
105
|
+
:default => 'auto',
|
106
|
+
:public => true,
|
107
|
+
:type => String,
|
108
|
+
:dynamic_name => true,
|
109
|
+
:allowed_from_server => false,
|
110
|
+
:description => 'Controls auto-instrumentation of the #{name} library at start-up. May be one of `auto`, `prepend`, `chain`, `disabled`.'
|
111
|
+
},
|
108
112
|
CONFIG
|
109
113
|
end
|
110
114
|
|
111
|
-
def yaml_block(name)
|
115
|
+
def yaml_block(name, snake_name)
|
112
116
|
<<~HEREDOC
|
113
117
|
|
114
118
|
# Controls auto-instrumentation of #{name} at start-up.
|
115
119
|
# May be one of [auto|prepend|chain|disabled]
|
116
|
-
# instrumentation.#{
|
120
|
+
# instrumentation.#{snake_name}: auto
|
117
121
|
HEREDOC
|
118
122
|
end
|
123
|
+
|
124
|
+
def snake_name(name)
|
125
|
+
name.downcase.tr('-', '_')
|
126
|
+
end
|
119
127
|
end
|
120
128
|
|
121
129
|
Instrumentation.start(ARGV)
|
@@ -2,12 +2,12 @@
|
|
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
|
-
require_relative '<%= @
|
6
|
-
require_relative '<%= @
|
7
|
-
require_relative '<%= @
|
5
|
+
require_relative '<%= @snake_name.downcase %>/instrumentation'
|
6
|
+
require_relative '<%= @snake_name.downcase %>/chain'
|
7
|
+
require_relative '<%= @snake_name.downcase %>/prepend'
|
8
8
|
|
9
9
|
DependencyDetection.defer do
|
10
|
-
named :<%= @name.match?(/\-|\_/) ? "'#{@
|
10
|
+
named :<%= @name.match?(/\-|\_/) ? "'#{@snake_name}'" : @name.downcase %>
|
11
11
|
|
12
12
|
depends_on do
|
13
13
|
# The class that needs to be defined to prepend/chain onto. This can be used
|
@@ -6,7 +6,7 @@ development:
|
|
6
6
|
monitor_mode: true
|
7
7
|
license_key: bootstrap_newrelic_admin_license_key_000
|
8
8
|
instrumentation:
|
9
|
-
<%= @
|
9
|
+
<%= @snake_name %>: <%= @instrumentation_method_global_erb_snippet %>
|
10
10
|
app_name: test
|
11
11
|
log_level: debug
|
12
12
|
host: 127.0.0.1
|
data/newrelic.yml
CHANGED
@@ -116,7 +116,7 @@ common: &default_settings
|
|
116
116
|
# Specify a list of constants that should prevent the agent from starting
|
117
117
|
# automatically. Separate individual constants with a comma ,. For example,
|
118
118
|
# "Rails::Console,UninstrumentedBackgroundJob".
|
119
|
-
# autostart.denylisted_constants: Rails::Command::ConsoleCommand,Rails::Command::CredentialsCommand,Rails::Command::Db::System::ChangeCommand,Rails::Command::DbConsoleCommand,Rails::Command::DestroyCommand,Rails::Command::DevCommand,Rails::Command::EncryptedCommand,Rails::Command::GenerateCommand,Rails::Command::InitializersCommand,Rails::Command::NotesCommand,Rails::Command::
|
119
|
+
# autostart.denylisted_constants: Rails::Command::ConsoleCommand,Rails::Command::CredentialsCommand,Rails::Command::Db::System::ChangeCommand,Rails::Command::DbConsoleCommand,Rails::Command::DestroyCommand,Rails::Command::DevCommand,Rails::Command::EncryptedCommand,Rails::Command::GenerateCommand,Rails::Command::InitializersCommand,Rails::Command::NotesCommand,Rails::Command::RoutesCommand,Rails::Command::RunnerCommand,Rails::Command::SecretsCommand,Rails::Console,Rails::DBConsole
|
120
120
|
|
121
121
|
# Defines a comma-delimited list of executables that the agent should not
|
122
122
|
# instrument. For example, "rake,my_ruby_script.rb".
|
@@ -188,7 +188,9 @@ common: &default_settings
|
|
188
188
|
# If true, the agent captures custom events.
|
189
189
|
# custom_insights_events.enabled: true
|
190
190
|
|
191
|
-
# Specify a maximum number of custom events to buffer in memory at a time.
|
191
|
+
# * Specify a maximum number of custom events to buffer in memory at a time.'
|
192
|
+
# * When configuring the agent for AI monitoring, set to max value 100000. This
|
193
|
+
# ensures the agent captures the maximum amount of LLM events.
|
192
194
|
# custom_insights_events.max_samples_stored: 3000
|
193
195
|
|
194
196
|
# If false, the agent will not add database_name parameter to transaction or slow
|
@@ -354,14 +356,14 @@ common: &default_settings
|
|
354
356
|
# requests.
|
355
357
|
# exclude_newrelic_header: false
|
356
358
|
|
357
|
-
#
|
358
|
-
# down
|
359
|
-
# not be.
|
360
|
-
# embedded service within another framework
|
361
|
-
# app and
|
359
|
+
# The exit handler that sends all cached data to the collector before shutting
|
360
|
+
# down is forcibly installed. This is true even when it detects scenarios where it
|
361
|
+
# generally should not be. The known use case for this option is when Sinatra runs
|
362
|
+
# as an embedded service within another framework. The agent detects the Sinatra
|
363
|
+
# app and skips the at_exit handler as a result. Sinatra classically runs the
|
362
364
|
# entire application in an at_exit block and would otherwise misbehave if the
|
363
|
-
#
|
364
|
-
# send_data_on_exit should also be set to true in
|
365
|
+
# agent's at_exit handler was also installed in those circumstances. Note:
|
366
|
+
# send_data_on_exit should also be set to true in tandem with this setting.
|
365
367
|
# force_install_exit_handler: false
|
366
368
|
|
367
369
|
# Ordinarily the agent reports dyno names with a trailing dot and process ID (for
|
@@ -405,6 +407,10 @@ common: &default_settings
|
|
405
407
|
# prepend, chain, disabled.
|
406
408
|
# instrumentation.async_http: auto
|
407
409
|
|
410
|
+
# Controls auto-instrumentation of the aws-sdk-sqs library at start-up. May be one
|
411
|
+
# of: auto, prepend, chain, disabled.
|
412
|
+
# instrumentation.aws_sqs: auto
|
413
|
+
|
408
414
|
# Controls auto-instrumentation of bunny at start-up. May be one of: auto,
|
409
415
|
# prepend, chain, disabled.
|
410
416
|
# instrumentation.bunny: auto
|
@@ -699,8 +705,8 @@ common: &default_settings
|
|
699
705
|
|
700
706
|
# * Defines the maximum number of span events reported from a single harvest. Any
|
701
707
|
# Integer between 1 and 10000 is valid.'
|
702
|
-
# * When configuring the agent for AI monitoring, set to max value 10000.
|
703
|
-
# ensures
|
708
|
+
# * When configuring the agent for AI monitoring, set to max value 10000.This
|
709
|
+
# ensures the agent captures the maximum amount of distributed traces.
|
704
710
|
# span_events.max_samples_stored: 2000
|
705
711
|
|
706
712
|
# Sets the maximum number of span events to buffer when streaming to the trace
|
data/newrelic_rpm.gemspec
CHANGED
@@ -56,6 +56,8 @@ Gem::Specification.new do |s|
|
|
56
56
|
s.add_development_dependency 'minitest', "#{RUBY_VERSION >= '2.7.0' ? '5.3.3' : '4.7.5'}"
|
57
57
|
s.add_development_dependency 'minitest-stub-const', '0.6'
|
58
58
|
s.add_development_dependency 'mocha', '~> 1.16'
|
59
|
+
s.add_development_dependency 'mutex_m' # used by Minitest, not included in Rubies above v3.3
|
60
|
+
s.add_development_dependency 'ostruct' # used by Rack, not included in Rubies above v3.4
|
59
61
|
s.add_development_dependency 'pry' if ENV['ENABLE_PRY']
|
60
62
|
s.add_development_dependency 'rack'
|
61
63
|
s.add_development_dependency 'rake', '12.3.3'
|
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: 9.
|
4
|
+
version: 9.11.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: 2024-06-
|
14
|
+
date: 2024-06-20 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -69,6 +69,34 @@ dependencies:
|
|
69
69
|
- - "~>"
|
70
70
|
- !ruby/object:Gem::Version
|
71
71
|
version: '1.16'
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: mutex_m
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: ostruct
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
72
100
|
- !ruby/object:Gem::Dependency
|
73
101
|
name: rack
|
74
102
|
requirement: !ruby/object:Gem::Requirement
|
@@ -364,6 +392,10 @@ files:
|
|
364
392
|
- lib/new_relic/agent/instrumentation/async_http/chain.rb
|
365
393
|
- lib/new_relic/agent/instrumentation/async_http/instrumentation.rb
|
366
394
|
- lib/new_relic/agent/instrumentation/async_http/prepend.rb
|
395
|
+
- lib/new_relic/agent/instrumentation/aws_sqs.rb
|
396
|
+
- lib/new_relic/agent/instrumentation/aws_sqs/chain.rb
|
397
|
+
- lib/new_relic/agent/instrumentation/aws_sqs/instrumentation.rb
|
398
|
+
- lib/new_relic/agent/instrumentation/aws_sqs/prepend.rb
|
367
399
|
- lib/new_relic/agent/instrumentation/bunny.rb
|
368
400
|
- lib/new_relic/agent/instrumentation/bunny/chain.rb
|
369
401
|
- lib/new_relic/agent/instrumentation/bunny/instrumentation.rb
|
@@ -671,6 +703,7 @@ files:
|
|
671
703
|
- lib/tasks/bump_version.rake
|
672
704
|
- lib/tasks/config.rake
|
673
705
|
- lib/tasks/coverage_report.rake
|
706
|
+
- lib/tasks/gha.rake
|
674
707
|
- lib/tasks/helpers/config.html.erb
|
675
708
|
- lib/tasks/helpers/config.text.erb
|
676
709
|
- lib/tasks/helpers/format.rb
|
@@ -723,7 +756,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
723
756
|
- !ruby/object:Gem::Version
|
724
757
|
version: 1.3.1
|
725
758
|
requirements: []
|
726
|
-
rubygems_version: 3.5.
|
759
|
+
rubygems_version: 3.5.11
|
727
760
|
signing_key:
|
728
761
|
specification_version: 4
|
729
762
|
summary: New Relic Ruby Agent
|