newrelic_rpm 9.9.0 → 9.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -0
- data/README.md +3 -0
- data/Rakefile +1 -1
- data/lib/boot/strap.rb +101 -0
- data/lib/new_relic/agent/aws.rb +62 -0
- data/lib/new_relic/agent/configuration/default_source.rb +45 -15
- data/lib/new_relic/agent/error_collector.rb +23 -0
- data/lib/new_relic/agent/instrumentation/dynamodb/chain.rb +27 -0
- data/lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb +64 -0
- data/lib/new_relic/agent/instrumentation/dynamodb/prepend.rb +19 -0
- data/lib/new_relic/agent/instrumentation/dynamodb.rb +25 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +51 -6
- data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +0 -1
- data/lib/new_relic/agent/span_event_primitive.rb +4 -8
- data/lib/new_relic/agent/transaction/external_request_segment.rb +0 -10
- data/lib/new_relic/agent/transaction.rb +2 -6
- data/lib/new_relic/agent.rb +1 -0
- data/lib/new_relic/rack/browser_monitoring.rb +9 -1
- data/lib/new_relic/version.rb +2 -2
- data/lib/sequel/extensions/new_relic_instrumentation.rb +3 -2
- data/lib/tasks/config.rake +3 -2
- data/lib/tasks/helpers/config.html.erb +3 -2
- data/lib/tasks/helpers/format.rb +1 -1
- 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 +29 -15
- data/test/agent_helper.rb +7 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cef71bbfaac5e07f6d5b0862fccb3bf35e4c99251ce5fec00143036c89c964f8
|
4
|
+
data.tar.gz: e5521d0958408d97494625b155f2dcb97736d02994f7b7dfdc58143dabc73dee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28a45e748a241b3bfb2c93bb19500cda6bc433c9c428e56f4cbcc92ff5c12d8f6d0198ab87d3a910f11539695fc8d0a4935c65ea5869d6bf36b66ae2b012c3a7
|
7
|
+
data.tar.gz: 35426f77a90e9f10b2be825538482a5bda1d074cc4d3c22acd1df007774f21a190b10696ad962fe34e30db0dd57d0a5bcadb3db6d5bc97edad0dcfba88db9a19
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,55 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes
|
2
2
|
|
3
|
+
## v9.10.2
|
4
|
+
|
5
|
+
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.
|
6
|
+
|
7
|
+
- **Bugfix: DynamoDB instrumentation logging errors when trying to get account_id**
|
8
|
+
|
9
|
+
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#2864](https://github.com/newrelic/newrelic-ruby-agent/pull/2684)
|
10
|
+
|
11
|
+
- **Bugfix: Remove Rails::Command::RakeCommand from the default list of autostart.denylisted_constants**
|
12
|
+
|
13
|
+
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:
|
14
|
+
|
15
|
+
```yaml
|
16
|
+
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"
|
17
|
+
```
|
18
|
+
|
19
|
+
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)
|
20
|
+
|
21
|
+
## v9.10.1
|
22
|
+
|
23
|
+
- **Bugfix: Incompatibility with Bootstrap**
|
24
|
+
|
25
|
+
Version 9.10.1 fixes an incompatibility between the agent and the [Bootstrap](https://github.com/twbs/bootstrap-rubygem) gem caused by agent v9.10.0's introduction of a `lib/bootstrap.rb` file. Thank you to [@dorner](https://github.com/dorner) for reporting the bug and identifying the 'bootstrap' name collision as the root cause. [BUG#2675](https://github.com/newrelic/newrelic-ruby-agent/issues/2675) [PR#2676](https://github.com/newrelic/newrelic-ruby-agent/pull/2676)
|
26
|
+
|
27
|
+
## v9.10.0
|
28
|
+
|
29
|
+
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.
|
30
|
+
|
31
|
+
- **Feature: Add instrumentation for DynamoDB**
|
32
|
+
|
33
|
+
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)
|
34
|
+
|
35
|
+
- **Feature: Automatically apply nonces from the Rails content security policy**
|
36
|
+
|
37
|
+
To auto-inject browser monitoring with the New Relic Ruby agent, you either need to set your content security policy to 'unsafe-inline' or provide a nonce. Previously, the only way to provide a nonce was by using the [`NewRelic::Agent.browser_timing_header`](https://rubydoc.info/gems/newrelic_rpm/NewRelic/Agent#browser_timing_header-instance_method) API. Now, when a Rails application uses [the content security policy configuration to add a nonce](https://guides.rubyonrails.org/security.html#adding-a-nonce), the nonce will be automatically applied to the browser agent. A new configuration option, [`browser_monitoring.content_security_policy_nonce`](https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration/#browser_monitoring-content_security_policy_nonce), toggles this feature. It is on by default. Thank you [@baldarn](https://github.com/baldarn) for submitting this feature! [PR#2544](https://github.com/newrelic/newrelic-ruby-agent/pull/2544)
|
38
|
+
|
39
|
+
- **Bugfix: Expected errors related to HTTP status code, class, and message won't impact Apdex**
|
40
|
+
|
41
|
+
The agent is supposed to prevent observed application errors from negatively impacting Apdex if the errors are either ignored or expected. There are two ways for the agent to expect an error: via the `notice_error` API receiving an `expected: true` argument or via matches made against user-configured lists for expected HTTP status codes (`:'error_collector.expected_status_codes'`), expected error classes (`:'error_collector.expected_classes'`), or expected error messages (`:'error_collector.expected_messages'`). Previously, only errors expected via the `notice_error` API were correctly prevented from impacting Apdex. Expected errors set by configuration incorrectly impacted Apdex. This behavior has been fixed and now both types of expected errors will correctly not impact Apdex. Thanks very much to [@florianpilz](https://github.com/florianpilz) for bringing this issue to our attention. [PR#2619](https://github.com/newrelic/newrelic-ruby-agent/pull/2619)
|
42
|
+
|
43
|
+
- **Bugfix: Do not start the agent automatically when `rails runner` or `rails db` commands are ran**
|
44
|
+
|
45
|
+
[PR#2239](https://github.com/newrelic/newrelic-ruby-agent/pull/2239) taught the agent how to recognize `bin/rails` based contexts that it should not automatically start up in. But `bin/rails runner` and `bin/rails db` commands would still see the agent start automatically. Those 2 contexts will now no longer see the agent start automatically. Thank you to [@jdelStrother](https://github.com/jdelStrother) for both bringing the `bin/rails` context to our attention and for letting us know about the `bin/rails runner` and `bin/rails db` outliers that still needed fixing. [PR#2623](https://github.com/newrelic/newrelic-ruby-agent/pull/2623)
|
46
|
+
|
47
|
+
Older agent versions that are still supported by New Relic can update to the new list of denylisted constants by having the following line added to the `newrelic.yml` configuration file:
|
48
|
+
|
49
|
+
```yaml
|
50
|
+
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"
|
51
|
+
```
|
52
|
+
|
3
53
|
## v9.9.0
|
4
54
|
|
5
55
|
Version 9.9.0 introduces support for AWS Lambda serverless function observability, adds support for Elasticsearch 8.13.0, and adds the 'request.temperature' attribute to chat completion summaries in ruby-openai instrumentation.
|
@@ -8,6 +58,8 @@ Version 9.9.0 introduces support for AWS Lambda serverless function observabilit
|
|
8
58
|
|
9
59
|
The Ruby agent is now capable of operating in a quick and light serverless mode suitable for observing AWS Lambda function invocations. For serverless use, the agent is delivered by a New Relic Lambda [layer](https://github.com/newrelic/newrelic-lambda-layers) that can be associated with a Lambda function. All reported data will appear in New Relic's dedicated serverless UI views. Only AWS based Lambda functions are supported for now, though support for other cloud hosted serverless offerings may be added in future depending on Ruby customer demand. The serverless functionality is only intended for use with the official New Relic Ruby layers for Lambda. Any existing workflows that involve the manual use of the Ruby agent in an AWS Lambda context without a New Relic layer should not be impacted.
|
10
60
|
|
61
|
+
For more details, see our [getting started guide](https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/get-started/monitoring-aws-lambda-serverless-monitoring/).
|
62
|
+
|
11
63
|
- **Feature: Add support for Elasticsearch 8.13.0**
|
12
64
|
|
13
65
|
Elasticsearch 8.13.0 increased the number of arguments used in the method the agent instruments, `Elastic::Transport::Client#perform_request`. Now, the agent supports a variable number of arguments for the instrumented method to prevent future `ArgumentError`s.
|
data/README.md
CHANGED
@@ -23,6 +23,9 @@ can be found on [our docs site](http://docs.newrelic.com/docs/ruby/supported-fra
|
|
23
23
|
You can also monitor non-web applications. Refer to the "Other
|
24
24
|
Environments" section below.
|
25
25
|
|
26
|
+
We offer an AWS Lambda layer for instrumenting your serverless Ruby functions.
|
27
|
+
Details can be found on our [getting started guide](https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/get-started/monitoring-aws-lambda-serverless-monitoring/).
|
28
|
+
|
26
29
|
## Installing and Using
|
27
30
|
|
28
31
|
The latest released gem for the Ruby agent can be found at [RubyGems.org](https://rubygems.org/gems/newrelic_rpm)
|
data/Rakefile
CHANGED
data/lib/boot/strap.rb
ADDED
@@ -0,0 +1,101 @@
|
|
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 file is designed to bootstrap a `Bundler.require`-based Ruby app (such as
|
6
|
+
# a Ruby on Rails app) so the app can be instrumented and observed by the
|
7
|
+
# New Relic Ruby agent without the agent being added to the app as a dependency.
|
8
|
+
# NOTE: introducing the agent into your application via bootstrap is in beta.
|
9
|
+
# Use at your own risk.
|
10
|
+
#
|
11
|
+
# Given a production-ready Ruby app that optionally has a pre-packaged "frozen"
|
12
|
+
# or "deployment"–gem bundle, the New Relic Ruby agent can be introduced
|
13
|
+
# to the app without modifying the app and keeping all of the app's content
|
14
|
+
# read-only.
|
15
|
+
#
|
16
|
+
# Prerequisites:
|
17
|
+
# - Ruby (tested v2.4+)
|
18
|
+
# - Bundler (included with Ruby, tested v1.17+)
|
19
|
+
#
|
20
|
+
# Instructions:
|
21
|
+
# - First, make sure the New Relic Ruby agent exists on disk. For these
|
22
|
+
# instructions, we'll assume the agent exists at `/newrelic`.
|
23
|
+
# - The agent can be downloaded as the "newrelic_rpm" gem from RubyGems.org
|
24
|
+
# and unpacked with "gem unpack"
|
25
|
+
# - The agent can be cloned from the New Relic public GitHub repo:
|
26
|
+
# https://github.com/newrelic/newrelic-ruby-agent
|
27
|
+
# - Next, use the "RUBYOPT" environment variable to require ("-r") this
|
28
|
+
# file (note that the ".rb" extension is dropped):
|
29
|
+
# ```
|
30
|
+
# export RUBYOPT="-r /newrelic/lib/boot/strap"
|
31
|
+
# ```
|
32
|
+
# - Add your New Relic license key as an environment variable.
|
33
|
+
# ```
|
34
|
+
# export NEW_RELIC_LICENSE_KEY=1a2b3c4d5e67f8g9h0i
|
35
|
+
# ```
|
36
|
+
# - Launch an existing Ruby app as usual. For a Ruby on Rails app, this might
|
37
|
+
# involve running `bin/rails server`.
|
38
|
+
# - In the Ruby app's directory, look for and inspect
|
39
|
+
# `log/newrelic_agent.log`. If this file exists and there are no "WARN" or
|
40
|
+
# "ERROR" entries within it, then the agent was successfully introduced to
|
41
|
+
# the Ruby application.
|
42
|
+
|
43
|
+
module NRBundlerPatch
|
44
|
+
NR_AGENT_GEM = 'newrelic_rpm'
|
45
|
+
|
46
|
+
def require(*_groups)
|
47
|
+
super
|
48
|
+
|
49
|
+
require_newrelic
|
50
|
+
end
|
51
|
+
|
52
|
+
def require_newrelic
|
53
|
+
lib = File.expand_path('../..', __FILE__)
|
54
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
55
|
+
Kernel.require NR_AGENT_GEM
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class NRBundlerPatcher
|
60
|
+
BUNDLER = 'bundler'
|
61
|
+
RUBYOPT = 'RUBYOPT'
|
62
|
+
|
63
|
+
def self.patch
|
64
|
+
check_for_require
|
65
|
+
check_for_rubyopt
|
66
|
+
check_for_bundler
|
67
|
+
Bundler::Runtime.prepend(NRBundlerPatch)
|
68
|
+
rescue StandardError => e
|
69
|
+
Kernel.warn "New Relic entrypoint at #{__FILE__} encountered an issue:\n #{e.message}"
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def self.check_for_require
|
75
|
+
raise "#{__FILE__} is meant to be required, not invoked directly" if $PROGRAM_NAME == __FILE__
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.check_for_rubyopt
|
79
|
+
unless ENV[RUBYOPT].to_s.match?("-r #{__FILE__.rpartition('.').first}")
|
80
|
+
raise "#{__FILE__} is meant to be required via the RUBYOPT env var"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.check_for_bundler
|
85
|
+
require_bundler
|
86
|
+
|
87
|
+
raise 'Required Ruby Bundler class Bundler::Runtime not defined!' unless defined?(Bundler::Runtime)
|
88
|
+
|
89
|
+
unless Bundler::Runtime.method_defined?(:require)
|
90
|
+
raise "The active Ruby Bundler instance doesn't offer Bundler::Runtime#require"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.require_bundler
|
95
|
+
require BUNDLER
|
96
|
+
rescue LoadError => e
|
97
|
+
raise "Required Ruby library '#{BUNDLER}' could not be required - #{e}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
NRBundlerPatcher.patch
|
@@ -0,0 +1,62 @@
|
|
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 Aws
|
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
|
+
HEX_MASK = '7fffffffff80'
|
10
|
+
|
11
|
+
def self.create_arn(service, resource, region, account_id)
|
12
|
+
"arn:aws:#{service}:#{region}:#{account_id}:#{resource}"
|
13
|
+
rescue => e
|
14
|
+
NewRelic::Agent.logger.warn("Failed to create ARN: #{e}")
|
15
|
+
end
|
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
|
+
|
26
|
+
def self.convert_access_key_to_account_id(access_key)
|
27
|
+
decoded_key = Integer(decode_to_hex(access_key[4..-1]), 16)
|
28
|
+
mask = Integer(HEX_MASK, 16)
|
29
|
+
(decoded_key & mask) >> 7
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.decode_to_hex(access_key)
|
33
|
+
bytes = access_key.delete('=').each_char.map { |c| CHARACTERS.index(c) }
|
34
|
+
|
35
|
+
bytes.each_slice(8).map do |section|
|
36
|
+
convert_section(section)
|
37
|
+
end.flatten[0...6].join
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.convert_section(section)
|
41
|
+
buffer = 0
|
42
|
+
section.each do |chunk|
|
43
|
+
buffer = (buffer << 5) + chunk
|
44
|
+
end
|
45
|
+
|
46
|
+
chunk_count = (section.length * 5.0 / 8.0).floor
|
47
|
+
|
48
|
+
if section.length < 8
|
49
|
+
buffer >>= (5 - (chunk_count * 8)) % 5
|
50
|
+
end
|
51
|
+
|
52
|
+
decoded = []
|
53
|
+
chunk_count.times do |i|
|
54
|
+
shift = 8 * (chunk_count - 1 - i)
|
55
|
+
decoded << ((buffer >> shift) & 255).to_s(16)
|
56
|
+
end
|
57
|
+
|
58
|
+
decoded
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -390,9 +390,11 @@ module NewRelic
|
|
390
390
|
:description => <<~DESCRIPTION
|
391
391
|
If `false`, LLM instrumentation (OpenAI only for now) will not capture input and output content on specific LLM events.
|
392
392
|
|
393
|
-
|
394
|
-
|
395
|
-
|
393
|
+
The excluded attributes include:
|
394
|
+
* `content` from LlmChatCompletionMessage events
|
395
|
+
* `input` from LlmEmbedding events
|
396
|
+
|
397
|
+
This is an optional security setting to prevent recording sensitive data sent to and received from your LLMs.
|
396
398
|
DESCRIPTION
|
397
399
|
},
|
398
400
|
# this is only set via server side config
|
@@ -477,12 +479,14 @@ module NewRelic
|
|
477
479
|
:public => true,
|
478
480
|
:type => Boolean,
|
479
481
|
:allowed_from_server => false,
|
480
|
-
:description =>
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
482
|
+
:description => <<~DESC
|
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.
|
489
|
+
DESC
|
486
490
|
},
|
487
491
|
:high_security => {
|
488
492
|
:default => false,
|
@@ -780,6 +784,15 @@ module NewRelic
|
|
780
784
|
:allowed_from_server => true,
|
781
785
|
:description => 'If `true`, enables [auto-injection](/docs/browser/new-relic-browser/installation-configuration/adding-apps-new-relic-browser#select-apm-app) of the JavaScript header for page load timing (sometimes referred to as real user monitoring or RUM).'
|
782
786
|
},
|
787
|
+
# CSP nonce
|
788
|
+
:'browser_monitoring.content_security_policy_nonce' => {
|
789
|
+
:default => value_of(:'rum.enabled'),
|
790
|
+
:documentation_default => true,
|
791
|
+
:public => true,
|
792
|
+
:type => Boolean,
|
793
|
+
:allowed_from_server => false,
|
794
|
+
:description => 'If `true`, enables auto-injection of [Content Security Policy Nonce](https://content-security-policy.com/nonce/) in browser monitoring scripts. For now, auto-injection only works with Rails 5.2+.'
|
795
|
+
},
|
783
796
|
# Transaction events
|
784
797
|
:'transaction_events.enabled' => {
|
785
798
|
:default => true,
|
@@ -1070,6 +1083,7 @@ module NewRelic
|
|
1070
1083
|
Rails::Command::InitializersCommand
|
1071
1084
|
Rails::Command::NotesCommand
|
1072
1085
|
Rails::Command::RoutesCommand
|
1086
|
+
Rails::Command::RunnerCommand
|
1073
1087
|
Rails::Command::SecretsCommand
|
1074
1088
|
Rails::Console
|
1075
1089
|
Rails::DBConsole].join(','),
|
@@ -1134,8 +1148,12 @@ module NewRelic
|
|
1134
1148
|
:public => true,
|
1135
1149
|
:type => Integer,
|
1136
1150
|
:allowed_from_server => true,
|
1137
|
-
:
|
1138
|
-
:
|
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
|
1139
1157
|
},
|
1140
1158
|
# Datastore tracer
|
1141
1159
|
:'datastore_tracer.database_name_reporting.enabled' => {
|
@@ -1440,6 +1458,14 @@ module NewRelic
|
|
1440
1458
|
:allowed_from_server => false,
|
1441
1459
|
:description => 'Controls auto-instrumentation of bunny at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1442
1460
|
},
|
1461
|
+
:'instrumentation.dynamodb' => {
|
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-dynamodb library at start-up. May be one of `auto`, `prepend`, `chain`, `disabled`.'
|
1468
|
+
},
|
1443
1469
|
:'instrumentation.fiber' => {
|
1444
1470
|
:default => 'auto',
|
1445
1471
|
:public => true,
|
@@ -1488,7 +1514,7 @@ module NewRelic
|
|
1488
1514
|
:type => String,
|
1489
1515
|
:dynamic_name => true,
|
1490
1516
|
:allowed_from_server => false,
|
1491
|
-
:description => 'Controls auto-instrumentation of ethon at start up. May be one of
|
1517
|
+
:description => 'Controls auto-instrumentation of ethon at start up. May be one of `auto`, `prepend`, `chain`, `disabled`'
|
1492
1518
|
},
|
1493
1519
|
:'instrumentation.excon' => {
|
1494
1520
|
:default => 'enabled',
|
@@ -1558,7 +1584,7 @@ module NewRelic
|
|
1558
1584
|
:type => String,
|
1559
1585
|
:dynamic_name => true,
|
1560
1586
|
:allowed_from_server => false,
|
1561
|
-
:description => 'Controls auto-instrumentation of httpx at start up. May be one of
|
1587
|
+
:description => 'Controls auto-instrumentation of httpx at start up. May be one of `auto`, `prepend`, `chain`, `disabled`'
|
1562
1588
|
},
|
1563
1589
|
:'instrumentation.logger' => {
|
1564
1590
|
:default => instrumentation_value_from_boolean(:'application_logging.enabled'),
|
@@ -1620,7 +1646,7 @@ module NewRelic
|
|
1620
1646
|
:type => String,
|
1621
1647
|
:dynamic_name => true,
|
1622
1648
|
:allowed_from_server => false,
|
1623
|
-
:description => 'Controls auto-instrumentation of the ruby-openai gem at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1649
|
+
:description => 'Controls auto-instrumentation of the ruby-openai gem at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`. Defaults to `disabled` in high security mode.'
|
1624
1650
|
},
|
1625
1651
|
:'instrumentation.puma_rack' => {
|
1626
1652
|
:default => value_of(:'instrumentation.rack'),
|
@@ -1963,7 +1989,11 @@ module NewRelic
|
|
1963
1989
|
:public => true,
|
1964
1990
|
:type => Integer,
|
1965
1991
|
:allowed_from_server => true,
|
1966
|
-
:description =>
|
1992
|
+
:description => <<~DESC
|
1993
|
+
* Defines the maximum number of span events reported from a single harvest. Any Integer between `1` and `10000` is valid.'
|
1994
|
+
* When configuring the agent for [AI monitoring](/docs/ai-monitoring/intro-to-ai-monitoring), set to max value `10000`.\
|
1995
|
+
This ensures the agent captures the maximum amount of distributed traces.
|
1996
|
+
DESC
|
1967
1997
|
},
|
1968
1998
|
# Strip exception messages
|
1969
1999
|
:'strip_exception_messages.enabled' => {
|
@@ -110,6 +110,29 @@ module NewRelic
|
|
110
110
|
false
|
111
111
|
end
|
112
112
|
|
113
|
+
# Neither ignored nor expected errors impact apdex.
|
114
|
+
#
|
115
|
+
# Ignored errors are checked via `#error_is_ignored?`
|
116
|
+
# Expected errors are checked in 2 separate ways:
|
117
|
+
# 1. The presence of an `expected: true` attribute key/value pair in the
|
118
|
+
# options hash, which will be set if that key/value pair was used in
|
119
|
+
# the `notice_error` public API.
|
120
|
+
# 2. By calling `#expected?` which in turn calls `ErrorFilter#expected?`
|
121
|
+
# which checks for 3 things:
|
122
|
+
# - A match for user-defined HTTP status codes to expect
|
123
|
+
# - A match for user-defined error classes to expect
|
124
|
+
# - A match for user-defined error messages to expect
|
125
|
+
def error_affects_apdex?(error, options)
|
126
|
+
return false if error_is_ignored?(error)
|
127
|
+
return false if options[:expected]
|
128
|
+
|
129
|
+
!expected?(error, ::NewRelic::Agent::Tracer.state.current_transaction&.http_response_code)
|
130
|
+
rescue => e
|
131
|
+
NewRelic::Agent.logger.error("Could not determine if error '#{error}' should impact Apdex - " \
|
132
|
+
"#{e.class}: #{e.message}. Defaulting to 'true' (it should impact Apdex).")
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
113
136
|
# Calling instance_variable_set on a wrapped Java object in JRuby will
|
114
137
|
# generate a warning unless that object's class has already been marked
|
115
138
|
# as persistent, so we skip tagging of exception objects that are actually
|
@@ -0,0 +1,27 @@
|
|
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 DynamoDB::Chain
|
7
|
+
def self.instrument!
|
8
|
+
::Aws::DynamoDB::Client.class_eval do
|
9
|
+
include NewRelic::Agent::Instrumentation::DynamoDB
|
10
|
+
|
11
|
+
NewRelic::Agent::Instrumentation::DynamoDB::INSTRUMENTED_METHODS.each do |method_name|
|
12
|
+
alias_method("#{method_name}_without_new_relic".to_sym, method_name.to_sym)
|
13
|
+
|
14
|
+
define_method(method_name) do |*args|
|
15
|
+
instrument_method_with_new_relic(method_name, *args) { send("#{method_name}_without_new_relic".to_sym, *args) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method(:build_request_without_new_relic, :build_request)
|
20
|
+
|
21
|
+
def build_request(*args)
|
22
|
+
build_request_with_new_relic(*args) { build_request_without_new_relic(*args) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
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
|
+
module NewRelic::Agent::Instrumentation
|
6
|
+
module DynamoDB
|
7
|
+
INSTRUMENTED_METHODS = %w[
|
8
|
+
create_table
|
9
|
+
delete_item
|
10
|
+
delete_table
|
11
|
+
get_item
|
12
|
+
put_item
|
13
|
+
query
|
14
|
+
scan
|
15
|
+
update_item
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
PRODUCT = 'DynamoDB'
|
19
|
+
DEFAULT_HOST = 'dynamodb.amazonaws.com'
|
20
|
+
|
21
|
+
def instrument_method_with_new_relic(method_name, *args)
|
22
|
+
return yield unless NewRelic::Agent::Tracer.tracing_enabled?
|
23
|
+
|
24
|
+
NewRelic::Agent.record_instrumentation_invocation(PRODUCT)
|
25
|
+
|
26
|
+
segment = NewRelic::Agent::Tracer.start_datastore_segment(
|
27
|
+
product: PRODUCT,
|
28
|
+
operation: method_name,
|
29
|
+
host: config&.endpoint&.host || DEFAULT_HOST,
|
30
|
+
port_path_or_id: config&.endpoint&.port,
|
31
|
+
collection: args[0][:table_name]
|
32
|
+
)
|
33
|
+
|
34
|
+
arn = get_arn(args[0])
|
35
|
+
segment&.add_agent_attribute('cloud.resource_id', arn) if arn
|
36
|
+
|
37
|
+
@nr_captured_request = nil # clear request just in case
|
38
|
+
begin
|
39
|
+
NewRelic::Agent::Tracer.capture_segment_error(segment) { yield }
|
40
|
+
ensure
|
41
|
+
segment&.add_agent_attribute('aws.operation', method_name)
|
42
|
+
segment&.add_agent_attribute('aws.requestId', @nr_captured_request&.context&.http_response&.headers&.[]('x-amzn-requestid'))
|
43
|
+
segment&.add_agent_attribute('aws.region', config&.region)
|
44
|
+
segment&.finish
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_request_with_new_relic(*args)
|
49
|
+
@nr_captured_request = yield
|
50
|
+
end
|
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
|
+
|
58
|
+
def get_arn(params)
|
59
|
+
return unless params[:table_name] && nr_account_id
|
60
|
+
|
61
|
+
NewRelic::Agent::Aws.create_arn(PRODUCT.downcase, "table/#{params[:table_name]}", config&.region, nr_account_id)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,19 @@
|
|
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 DynamoDB::Prepend
|
7
|
+
include NewRelic::Agent::Instrumentation::DynamoDB
|
8
|
+
|
9
|
+
INSTRUMENTED_METHODS.each do |method_name|
|
10
|
+
define_method(method_name) do |*args|
|
11
|
+
instrument_method_with_new_relic(method_name, *args) { super(*args) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_request(*args)
|
16
|
+
build_request_with_new_relic(*args) { super }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
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 'dynamodb/instrumentation'
|
6
|
+
require_relative 'dynamodb/chain'
|
7
|
+
require_relative 'dynamodb/prepend'
|
8
|
+
|
9
|
+
DependencyDetection.defer do
|
10
|
+
named :dynamodb
|
11
|
+
|
12
|
+
depends_on do
|
13
|
+
defined?(Aws::DynamoDB::Client)
|
14
|
+
end
|
15
|
+
|
16
|
+
executes do
|
17
|
+
NewRelic::Agent.logger.info('Installing DynamoDB instrumentation')
|
18
|
+
|
19
|
+
if use_prepend?
|
20
|
+
prepend_instrument Aws::DynamoDB::Client, NewRelic::Agent::Instrumentation::DynamoDB::Prepend
|
21
|
+
else
|
22
|
+
chain_instrument NewRelic::Agent::Instrumentation::DynamoDB::Chain
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -8,6 +8,54 @@ module NewRelic::Agent::Instrumentation
|
|
8
8
|
module Elasticsearch
|
9
9
|
PRODUCT_NAME = 'Elasticsearch'
|
10
10
|
OPERATION = 'perform_request'
|
11
|
+
|
12
|
+
# Pattern to use with client caller location strings. Look for a location
|
13
|
+
# that contains '/lib/elasticsearch/api/' and is NOT followed by the
|
14
|
+
# string held in the OPERATION constant
|
15
|
+
OPERATION_PATTERN = %r{/lib/elasticsearch/api/(?!.+#{OPERATION})}.freeze
|
16
|
+
|
17
|
+
# Use the OPERATION_PATTERN pattern to find the appropriate caller location
|
18
|
+
# that will contain the client instance method (example: 'search') and
|
19
|
+
# return that method name.
|
20
|
+
#
|
21
|
+
# A Ruby caller location matching the OPERATION_PATTERN will contain an
|
22
|
+
# elasticsearch client instance method name (such as "search"), and that
|
23
|
+
# method name will be used as the operation name.
|
24
|
+
#
|
25
|
+
# With Ruby < 3.4 the method name is listed as:
|
26
|
+
#
|
27
|
+
# `search'
|
28
|
+
#
|
29
|
+
# with an opening backtick and a closing single tick. And only the
|
30
|
+
# method name itself is listed.
|
31
|
+
#
|
32
|
+
# With Ruby 3.4+ the method name is listed as:
|
33
|
+
#
|
34
|
+
# 'Elasticsearch::API::Actions#search'
|
35
|
+
#
|
36
|
+
# with opening and closing single ticks and the class defining the
|
37
|
+
# instance method listed.
|
38
|
+
#
|
39
|
+
# (?:) = ?: prevents capturing
|
40
|
+
# (?:`|') = allow ` or '
|
41
|
+
# (?:.+#) = allow the class name and '#' prefix to exist but ignore it
|
42
|
+
# ([^']+)' = after the opening ` or ', capturing everything up to the
|
43
|
+
# closing '. [^']+ = one or more characters that are not '
|
44
|
+
#
|
45
|
+
# Example Ruby 3.3.1 input:
|
46
|
+
#
|
47
|
+
# /Users/fallwith/.rubies/ruby-3.3.1/lib/ruby/gems/3.3.0/gems/elasticsearch-api-7.17.10/lib/elasticsearch/api/actions/index.rb:74:in `index'
|
48
|
+
#
|
49
|
+
# Example Ruby 3.4.0-preview1 input:
|
50
|
+
#
|
51
|
+
# /Users/fallwith/.rubies/ruby-3.4.0-preview1/lib/ruby/gems/3.4.0+0/gems/elasticsearch-api-7.17.10/lib/elasticsearch/api/actions/index.rb:74:in 'Elasticsearch::API::Actions#index'
|
52
|
+
#
|
53
|
+
# Example output for both Rubies:
|
54
|
+
#
|
55
|
+
# index
|
56
|
+
|
57
|
+
INSTANCE_METHOD_PATTERN = /:in (?:`|')(?:.+#)?([^']+)'\z/.freeze
|
58
|
+
|
11
59
|
INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
|
12
60
|
|
13
61
|
# We need the positional arguments `params` and `body`
|
@@ -40,13 +88,10 @@ module NewRelic::Agent::Instrumentation
|
|
40
88
|
private
|
41
89
|
|
42
90
|
def nr_operation
|
43
|
-
|
44
|
-
|
45
|
-
string.include?('lib/elasticsearch/api') && !string.include?(OPERATION)
|
46
|
-
end
|
47
|
-
return nil unless operation_index
|
91
|
+
location = caller_locations.detect { |loc| loc.to_s.match?(OPERATION_PATTERN) }
|
92
|
+
return unless location && location.to_s =~ INSTANCE_METHOD_PATTERN
|
48
93
|
|
49
|
-
|
94
|
+
Regexp.last_match(1)
|
50
95
|
end
|
51
96
|
|
52
97
|
def nr_reported_query(query)
|
@@ -79,17 +79,13 @@ module NewRelic
|
|
79
79
|
intrinsics[SPAN_KIND_KEY] = CLIENT
|
80
80
|
intrinsics[SERVER_ADDRESS_KEY] = segment.uri.host
|
81
81
|
intrinsics[SERVER_PORT_KEY] = segment.uri.port
|
82
|
-
agent_attributes =
|
82
|
+
agent_attributes = {}
|
83
83
|
|
84
84
|
if allowed?(HTTP_URL_KEY)
|
85
85
|
agent_attributes[HTTP_URL_KEY] = truncate(segment.uri)
|
86
86
|
end
|
87
87
|
|
88
|
-
|
89
|
-
agent_attributes.merge!(agent_attributes(segment))
|
90
|
-
end
|
91
|
-
|
92
|
-
[intrinsics, custom_attributes(segment), agent_attributes]
|
88
|
+
[intrinsics, custom_attributes(segment), agent_attributes.merge(agent_attributes(segment))]
|
93
89
|
end
|
94
90
|
|
95
91
|
def for_datastore_segment(segment) # rubocop:disable Metrics/AbcSize
|
@@ -99,7 +95,7 @@ module NewRelic
|
|
99
95
|
intrinsics[SPAN_KIND_KEY] = CLIENT
|
100
96
|
intrinsics[CATEGORY_KEY] = DATASTORE_CATEGORY
|
101
97
|
|
102
|
-
agent_attributes =
|
98
|
+
agent_attributes = {}
|
103
99
|
|
104
100
|
if segment.database_name && allowed?(DB_INSTANCE_KEY)
|
105
101
|
agent_attributes[DB_INSTANCE_KEY] = truncate(segment.database_name)
|
@@ -123,7 +119,7 @@ module NewRelic
|
|
123
119
|
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.nosql_statement, 2000)
|
124
120
|
end
|
125
121
|
|
126
|
-
[intrinsics, custom_attributes(segment), agent_attributes]
|
122
|
+
[intrinsics, custom_attributes(segment), agent_attributes.merge(agent_attributes(segment))]
|
127
123
|
end
|
128
124
|
|
129
125
|
private
|
@@ -23,7 +23,6 @@ module NewRelic
|
|
23
23
|
MISSING_STATUS_CODE = 'MissingHTTPStatusCode'
|
24
24
|
|
25
25
|
attr_reader :library, :uri, :procedure, :http_status_code
|
26
|
-
attr_writer :record_agent_attributes
|
27
26
|
|
28
27
|
def initialize(library, uri, procedure, start_time = nil) # :nodoc:
|
29
28
|
@library = library
|
@@ -32,7 +31,6 @@ module NewRelic
|
|
32
31
|
@host_header = nil
|
33
32
|
@app_data = nil
|
34
33
|
@http_status_code = nil
|
35
|
-
@record_agent_attributes = false
|
36
34
|
super(nil, nil, start_time)
|
37
35
|
end
|
38
36
|
|
@@ -44,14 +42,6 @@ module NewRelic
|
|
44
42
|
@host_header || uri.host
|
45
43
|
end
|
46
44
|
|
47
|
-
# By default external request segments only have errors and the http
|
48
|
-
# url recorded as agent attributes. To have all the agent attributes
|
49
|
-
# recorded, use the attr_writer like so `segment.record_agent_attributes = true`
|
50
|
-
# See: SpanEventPrimitive#for_external_request_segment
|
51
|
-
def record_agent_attributes?
|
52
|
-
@record_agent_attributes
|
53
|
-
end
|
54
|
-
|
55
45
|
# This method adds New Relic request headers to a given request made to an
|
56
46
|
# external API and checks to see if a host header is used for the request.
|
57
47
|
# If a host header is used, it updates the segment name to match the host
|
@@ -816,13 +816,9 @@ module NewRelic
|
|
816
816
|
end
|
817
817
|
|
818
818
|
def had_error_affecting_apdex?
|
819
|
-
@exceptions.each do |exception, options|
|
820
|
-
|
821
|
-
expected = options[:expected]
|
822
|
-
|
823
|
-
return true unless ignored || expected
|
819
|
+
@exceptions.each.any? do |exception, options|
|
820
|
+
NewRelic::Agent.instance.error_collector.error_affects_apdex?(exception, options)
|
824
821
|
end
|
825
|
-
false
|
826
822
|
end
|
827
823
|
|
828
824
|
def apdex_bucket(duration, current_apdex_t)
|
data/lib/new_relic/agent.rb
CHANGED
@@ -38,7 +38,7 @@ module NewRelic
|
|
38
38
|
result = @app.call(env)
|
39
39
|
(status, headers, response) = result
|
40
40
|
|
41
|
-
js_to_inject = NewRelic::Agent.browser_timing_header
|
41
|
+
js_to_inject = NewRelic::Agent.browser_timing_header(nonce(env))
|
42
42
|
if (js_to_inject != NewRelic::EMPTY_STR) && should_instrument?(env, status, headers)
|
43
43
|
response_string = autoinstrument_source(response, js_to_inject)
|
44
44
|
if headers.key?(CONTENT_LENGTH)
|
@@ -58,6 +58,14 @@ module NewRelic
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
def nonce(env)
|
62
|
+
return unless NewRelic::Agent.config[:'browser_monitoring.content_security_policy_nonce']
|
63
|
+
return unless NewRelic::Agent.config[:framework] == :rails_notifications
|
64
|
+
return unless defined?(ActionDispatch::ContentSecurityPolicy::Request)
|
65
|
+
|
66
|
+
env[ActionDispatch::ContentSecurityPolicy::Request::NONCE]
|
67
|
+
end
|
68
|
+
|
61
69
|
def should_instrument?(env, status, headers)
|
62
70
|
NewRelic::Agent.config[:'browser_monitoring.auto_instrument'] &&
|
63
71
|
status == 200 &&
|
data/lib/new_relic/version.rb
CHANGED
@@ -78,8 +78,9 @@ module Sequel
|
|
78
78
|
end
|
79
79
|
|
80
80
|
THREAD_SAFE_CONNECTION_POOL_CLASSES = [
|
81
|
-
(defined?(::Sequel::ThreadedConnectionPool) && ::Sequel::ThreadedConnectionPool)
|
82
|
-
|
81
|
+
(defined?(::Sequel::ThreadedConnectionPool) && ::Sequel::ThreadedConnectionPool),
|
82
|
+
(defined?(::Sequel::TimedQueueConnectionPool) && RUBY_VERSION >= '3.4' && ::Sequel::TimedQueueConnectionPool)
|
83
|
+
].compact.freeze
|
83
84
|
|
84
85
|
def explainer_for(sql)
|
85
86
|
proc do |*|
|
data/lib/tasks/config.rake
CHANGED
@@ -20,7 +20,7 @@ namespace :newrelic do
|
|
20
20
|
ATTRIBUTES => '[Attributes](/docs/features/agent-attributes) are key-value pairs containing information that determines the properties of an event or transaction. These key-value pairs can be viewed within transaction traces in APM, traced errors in APM, transaction events in dashboards, and page views in dashboards. You can customize exactly which attributes will be sent to each of these destinations',
|
21
21
|
'transaction_tracer' => 'The [transaction traces](/docs/apm/traces/transaction-traces/transaction-traces) feature collects detailed information from a selection of transactions, including a summary of the calling sequence, a breakdown of time spent, and a list of SQL queries and their query plans (on mysql and postgresql). Available features depend on your New Relic subscription level.',
|
22
22
|
'error_collector' => "The agent collects and reports all uncaught exceptions by default. These configuration options allow you to customize the error collection.\n\nFor information on ignored and expected errors, [see this page on Error Analytics in APM](/docs/agents/manage-apm-agents/agent-data/manage-errors-apm-collect-ignore-or-mark-expected/). To set expected errors via the `NewRelic::Agent.notice_error` Ruby method, [consult the Ruby agent API](/docs/agents/ruby-agent/api-guides/sending-handled-errors-new-relic/).",
|
23
|
-
'browser_monitoring' => "The browser
|
23
|
+
'browser_monitoring' => "The <InlinePopover type='browser' /> [page load timing](/docs/browser/new-relic-browser/page-load-timing/page-load-timing-process) feature (sometimes referred to as real user monitoring or RUM) gives you insight into the performance real users are experiencing with your website. This is accomplished by measuring the time it takes for your users' browsers to download and render your web pages by injecting a small amount of JavaScript code into the header and footer of each page.",
|
24
24
|
'application_logging' => "The Ruby agent supports [APM logs in context](/docs/apm/new-relic-apm/getting-started/get-started-logs-context). For some tips on configuring logs for the Ruby agent, see [Configure Ruby logs in context](/docs/logs/logs-context/configure-logs-context-ruby).\n\nAvailable logging-related config options include:",
|
25
25
|
'analytics_events' => '[New Relic dashboards](/docs/query-your-data/explore-query-data/dashboards/introduction-new-relic-one-dashboards) is a resource to gather and visualize data about your software and what it says about your business. With it you can quickly and easily create real-time dashboards to get immediate answers about end-user experiences, clickstreams, mobile activities, and server transactions.',
|
26
26
|
'ai_monitoring' => "This section includes Ruby agent configurations for setting up AI monitoring.\n\n<Callout variant='important'>You need to enable distributed tracing to capture trace and feedback data. It is turned on by default in Ruby agents 8.0.0 and higher.</Callout>"
|
@@ -28,7 +28,8 @@ namespace :newrelic do
|
|
28
28
|
|
29
29
|
NAME_OVERRIDES = {
|
30
30
|
'slow_sql' => 'Slow SQL [#slow-sql]',
|
31
|
-
'custom_insights_events' => 'Custom Events [#custom-events]'
|
31
|
+
'custom_insights_events' => 'Custom Events [#custom-events]',
|
32
|
+
'ai_monitoring' => 'AI Monitoring [#ai-monitoring]'
|
32
33
|
}
|
33
34
|
|
34
35
|
desc 'Describe available New Relic configuration settings'
|
@@ -10,6 +10,7 @@ redirects:
|
|
10
10
|
- /docs/ruby/ruby-agent-configuration
|
11
11
|
- /docs/agents/ruby-agent/installation-and-configuration/ruby-agent-configuration
|
12
12
|
- /docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration
|
13
|
+
freshnessValidatedDate: never
|
13
14
|
---
|
14
15
|
|
15
16
|
<CONTRIBUTOR_NOTE>
|
@@ -70,12 +71,12 @@ The Ruby agent looks for the following environment variables, in this order, to
|
|
70
71
|
|
71
72
|
If the Ruby agent doesn't detect values for any of those environment variables, it will default the application environment to `development` and read from the `development` section of the `newrelic.yml` config file.
|
72
73
|
|
73
|
-
When running the Ruby agent in a Rails app, the agent first looks for the `NEW_RELIC_ENV` environment variable to
|
74
|
+
When running the Ruby agent in a Rails app, the agent first looks for the `NEW_RELIC_ENV` environment variable to find the application environment and which section of the `newrelic.yml` to use. If `NEW_RELIC_ENV` is not present, the agent uses the Rails environment (`RAILS_ENV`).
|
74
75
|
|
75
76
|
When you edit the config file, be sure to:
|
76
77
|
|
77
78
|
* Indent only with two spaces.
|
78
|
-
* Indent only where relevant, in
|
79
|
+
* Indent only where relevant, in sections such as <DoNotTranslate>**`error_collector`**</DoNotTranslate>.
|
79
80
|
|
80
81
|
If you do not indent correctly, the agent may throw an `Unable to parse configuration file` error on startup.
|
81
82
|
|
data/lib/tasks/helpers/format.rb
CHANGED
@@ -69,7 +69,7 @@ module Format
|
|
69
69
|
|
70
70
|
def format_description(value)
|
71
71
|
description = ''
|
72
|
-
description += '
|
72
|
+
description += '<DoNotTranslate>**DEPRECATED**</DoNotTranslate>' if value[:deprecated]
|
73
73
|
description += value[:description]
|
74
74
|
description
|
75
75
|
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
@@ -43,6 +43,8 @@ common: &default_settings
|
|
43
43
|
# The excluded attributes include:
|
44
44
|
# * content from LlmChatCompletionMessage events
|
45
45
|
# * input from LlmEmbedding events
|
46
|
+
# This is an optional security setting to prevent recording sensitive data sent to
|
47
|
+
# and received from your LLMs.
|
46
48
|
# ai_monitoring.record_content.enabled: true
|
47
49
|
|
48
50
|
# If true, enables capture of all HTTP request headers for all destinations.
|
@@ -114,7 +116,7 @@ common: &default_settings
|
|
114
116
|
# Specify a list of constants that should prevent the agent from starting
|
115
117
|
# automatically. Separate individual constants with a comma ,. For example,
|
116
118
|
# "Rails::Console,UninstrumentedBackgroundJob".
|
117
|
-
# 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::SecretsCommand,Rails::Console,Rails::DBConsole
|
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
|
118
120
|
|
119
121
|
# Defines a comma-delimited list of executables that the agent should not
|
120
122
|
# instrument. For example, "rake,my_ruby_script.rb".
|
@@ -144,6 +146,10 @@ common: &default_settings
|
|
144
146
|
# (sometimes referred to as real user monitoring or RUM).
|
145
147
|
# browser_monitoring.auto_instrument: true
|
146
148
|
|
149
|
+
# If true, enables auto-injection of Content Security Policy Nonce in browser
|
150
|
+
# monitoring scripts. For now, auto-injection only works with Rails 5.2+.
|
151
|
+
# browser_monitoring.content_security_policy_nonce: true
|
152
|
+
|
147
153
|
# Manual override for the path to your local CA bundle. This CA bundle will be
|
148
154
|
# used to validate the SSL certificate presented by New Relic's data collection
|
149
155
|
# service.
|
@@ -182,7 +188,9 @@ common: &default_settings
|
|
182
188
|
# If true, the agent captures custom events.
|
183
189
|
# custom_insights_events.enabled: true
|
184
190
|
|
185
|
-
# 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.
|
186
194
|
# custom_insights_events.max_samples_stored: 3000
|
187
195
|
|
188
196
|
# If false, the agent will not add database_name parameter to transaction or slow
|
@@ -348,14 +356,14 @@ common: &default_settings
|
|
348
356
|
# requests.
|
349
357
|
# exclude_newrelic_header: false
|
350
358
|
|
351
|
-
#
|
352
|
-
# down
|
353
|
-
# not be.
|
354
|
-
# embedded service within another framework
|
355
|
-
# 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
|
356
364
|
# entire application in an at_exit block and would otherwise misbehave if the
|
357
365
|
# agent's at_exit handler was also installed in those circumstances. Note:
|
358
|
-
# send_data_on_exit should also be set to true in
|
366
|
+
# send_data_on_exit should also be set to true in tandem with this setting.
|
359
367
|
# force_install_exit_handler: false
|
360
368
|
|
361
369
|
# Ordinarily the agent reports dyno names with a trailing dot and process ID (for
|
@@ -415,12 +423,16 @@ common: &default_settings
|
|
415
423
|
# prepend, chain, disabled.
|
416
424
|
# instrumentation.delayed_job: auto
|
417
425
|
|
426
|
+
# Controls auto-instrumentation of the aws-sdk-dynamodb library at start-up. May
|
427
|
+
# be one of auto, prepend, chain, disabled.
|
428
|
+
# instrumentation.dynamodb: auto
|
429
|
+
|
418
430
|
# Controls auto-instrumentation of the elasticsearch library at start-up. May be
|
419
431
|
# one of: auto, prepend, chain, disabled.
|
420
432
|
# instrumentation.elasticsearch: auto
|
421
433
|
|
422
|
-
# Controls auto-instrumentation of ethon at start up. May be one of
|
423
|
-
#
|
434
|
+
# Controls auto-instrumentation of ethon at start up. May be one of auto, prepend,
|
435
|
+
# chain, disabled
|
424
436
|
# instrumentation.ethon: auto
|
425
437
|
|
426
438
|
# Controls auto-instrumentation of Excon at start-up. May be one of: enabled,
|
@@ -460,8 +472,8 @@ common: &default_settings
|
|
460
472
|
# prepend, chain, disabled.
|
461
473
|
# instrumentation.httprb: auto
|
462
474
|
|
463
|
-
# Controls auto-instrumentation of httpx at start up. May be one of
|
464
|
-
#
|
475
|
+
# Controls auto-instrumentation of httpx at start up. May be one of auto, prepend,
|
476
|
+
# chain, disabled
|
465
477
|
# instrumentation.httpx: auto
|
466
478
|
|
467
479
|
# Controls auto-instrumentation of Ruby standard library Logger at start-up. May
|
@@ -523,7 +535,7 @@ common: &default_settings
|
|
523
535
|
# instrumentation.roda: auto
|
524
536
|
|
525
537
|
# Controls auto-instrumentation of the ruby-openai gem at start-up. May be one of:
|
526
|
-
# auto, prepend, chain, disabled.
|
538
|
+
# auto, prepend, chain, disabled. Defaults to disabled in high security mode.
|
527
539
|
# instrumentation.ruby_openai: auto
|
528
540
|
|
529
541
|
# Controls auto-instrumentation of Sinatra at start-up. May be one of: auto,
|
@@ -687,8 +699,10 @@ common: &default_settings
|
|
687
699
|
# If true, enables span event sampling.
|
688
700
|
# span_events.enabled: true
|
689
701
|
|
690
|
-
# Defines the maximum number of span events reported from a single harvest. Any
|
691
|
-
# Integer between 1 and 10000 is valid.
|
702
|
+
# * Defines the maximum number of span events reported from a single harvest. Any
|
703
|
+
# Integer between 1 and 10000 is valid.'
|
704
|
+
# * When configuring the agent for AI monitoring, set to max value 10000.This
|
705
|
+
# ensures the agent captures the maximum amount of distributed traces.
|
692
706
|
# span_events.max_samples_stored: 2000
|
693
707
|
|
694
708
|
# Sets the maximum number of span events to buffer when streaming to the trace
|
data/test/agent_helper.rb
CHANGED
@@ -228,7 +228,9 @@ def assert_metrics_recorded(expected)
|
|
228
228
|
expected.each do |specish, expected_attrs|
|
229
229
|
expected_spec = metric_spec_from_specish(specish)
|
230
230
|
actual_stats = NewRelic::Agent.instance.stats_engine.to_h[expected_spec]
|
231
|
-
if
|
231
|
+
if actual_stats
|
232
|
+
assert(actual_stats)
|
233
|
+
else
|
232
234
|
all_specs = NewRelic::Agent.instance.stats_engine.to_h.keys.sort
|
233
235
|
matches = all_specs.select { |spec| spec.name == expected_spec.name }
|
234
236
|
matches.map! { |m| " #{m.inspect}" }
|
@@ -1037,3 +1039,7 @@ def first_call_for(subject)
|
|
1037
1039
|
|
1038
1040
|
items.first
|
1039
1041
|
end
|
1042
|
+
|
1043
|
+
def ruby_version_float
|
1044
|
+
RUBY_VERSION.split('.')[0..1].join('.').to_f
|
1045
|
+
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: 9.
|
4
|
+
version: 9.10.2
|
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-
|
14
|
+
date: 2024-06-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -243,6 +243,7 @@ files:
|
|
243
243
|
- bin/nrdebug
|
244
244
|
- init.rb
|
245
245
|
- install.rb
|
246
|
+
- lib/boot/strap.rb
|
246
247
|
- lib/new_relic/agent.rb
|
247
248
|
- lib/new_relic/agent/adaptive_sampler.rb
|
248
249
|
- lib/new_relic/agent/agent.rb
|
@@ -260,6 +261,7 @@ files:
|
|
260
261
|
- lib/new_relic/agent/attributes.rb
|
261
262
|
- lib/new_relic/agent/audit_logger.rb
|
262
263
|
- lib/new_relic/agent/autostart.rb
|
264
|
+
- lib/new_relic/agent/aws.rb
|
263
265
|
- lib/new_relic/agent/chained_call.rb
|
264
266
|
- lib/new_relic/agent/commands/agent_command.rb
|
265
267
|
- lib/new_relic/agent/commands/agent_command_router.rb
|
@@ -381,6 +383,10 @@ files:
|
|
381
383
|
- lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb
|
382
384
|
- lib/new_relic/agent/instrumentation/delayed_job/prepend.rb
|
383
385
|
- lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb
|
386
|
+
- lib/new_relic/agent/instrumentation/dynamodb.rb
|
387
|
+
- lib/new_relic/agent/instrumentation/dynamodb/chain.rb
|
388
|
+
- lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb
|
389
|
+
- lib/new_relic/agent/instrumentation/dynamodb/prepend.rb
|
384
390
|
- lib/new_relic/agent/instrumentation/elasticsearch.rb
|
385
391
|
- lib/new_relic/agent/instrumentation/elasticsearch/chain.rb
|
386
392
|
- lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb
|
@@ -717,7 +723,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
717
723
|
- !ruby/object:Gem::Version
|
718
724
|
version: 1.3.1
|
719
725
|
requirements: []
|
720
|
-
rubygems_version: 3.
|
726
|
+
rubygems_version: 3.5.9
|
721
727
|
signing_key:
|
722
728
|
specification_version: 4
|
723
729
|
summary: New Relic Ruby Agent
|