newrelic_rpm 9.8.0 → 9.10.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 +46 -2
- data/README.md +3 -0
- data/Rakefile +1 -1
- data/lib/bootstrap.rb +105 -0
- data/lib/new_relic/agent/agent.rb +4 -1
- data/lib/new_relic/agent/agent_helpers/connect.rb +10 -8
- data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +1 -1
- data/lib/new_relic/agent/agent_helpers/startup.rb +2 -1
- data/lib/new_relic/agent/agent_logger.rb +2 -1
- data/lib/new_relic/agent/aws.rb +56 -0
- data/lib/new_relic/agent/configuration/default_source.rb +65 -15
- data/lib/new_relic/agent/configuration/environment_source.rb +9 -1
- data/lib/new_relic/agent/configuration/manager.rb +22 -5
- data/lib/new_relic/agent/configuration/yaml_source.rb +2 -0
- data/lib/new_relic/agent/connect/request_builder.rb +1 -1
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_payload.rb +1 -5
- data/lib/new_relic/agent/error_collector.rb +23 -0
- data/lib/new_relic/agent/harvester.rb +1 -1
- data/lib/new_relic/agent/instrumentation/dynamodb/chain.rb +27 -0
- data/lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb +58 -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 +6 -1
- data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +0 -1
- data/lib/new_relic/agent/instrumentation/ruby_openai/instrumentation.rb +1 -2
- data/lib/new_relic/agent/log_event_aggregator.rb +1 -16
- data/lib/new_relic/agent/new_relic_service.rb +12 -2
- data/lib/new_relic/agent/serverless_handler.rb +171 -0
- 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/transaction_error_primitive.rb +23 -19
- data/lib/new_relic/agent.rb +12 -8
- data/lib/new_relic/constants.rb +2 -0
- data/lib/new_relic/control/instance_methods.rb +7 -0
- data/lib/new_relic/local_environment.rb +13 -6
- data/lib/new_relic/rack/browser_monitoring.rb +9 -1
- data/lib/new_relic/version.rb +1 -1
- data/lib/tasks/config.rake +5 -3
- data/lib/tasks/helpers/config.html.erb +3 -2
- data/lib/tasks/helpers/format.rb +1 -1
- data/newrelic.yml +15 -1
- data/test/agent_helper.rb +3 -1
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3793bb498826b000ad9e00e7d57de0e95988c4ba213e341a6a8c18f90df772e
|
4
|
+
data.tar.gz: 6cb26b15c2faace4a7e1fd6775a3f69f965beaad10f395e0fb618cb411dbacfe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acb8dd0c767f40796fa1afb9cc26c0a57a9bdd83a4cbf550589a094f5cf48da32caf1d4c0f10e154633b754086bd62aa17d393bffa37eee5a0128e72c3bd6160
|
7
|
+
data.tar.gz: 6ce06fe8f1506405b7696089bf366e1aa0ccd60ab0d5034b22db87ac3c4523bd9d8d4dc4a6b568515cd516cd5c64babf853cdfed4af1839fd45cbed0450994f5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,49 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes
|
2
2
|
|
3
|
+
## v9.10.0
|
4
|
+
|
5
|
+
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.
|
6
|
+
|
7
|
+
- **Feature: Add instrumentation for DynamoDB**
|
8
|
+
|
9
|
+
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)
|
10
|
+
|
11
|
+
- **Feature: Automatically apply nonces from the Rails content security policy**
|
12
|
+
|
13
|
+
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)
|
14
|
+
|
15
|
+
- **Bugfix: Expected errors related to HTTP status code, class, and message won't impact Apdex**
|
16
|
+
|
17
|
+
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)
|
18
|
+
|
19
|
+
- **Bugfix: Do not start the agent automatically when `rails runner` or `rails db` commands are ran**
|
20
|
+
|
21
|
+
[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)
|
22
|
+
|
23
|
+
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:
|
24
|
+
|
25
|
+
```yaml
|
26
|
+
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"
|
27
|
+
```
|
28
|
+
|
29
|
+
## v9.9.0
|
30
|
+
|
31
|
+
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.
|
32
|
+
|
33
|
+
- **Feature: Serverless Mode for AWS Lambda**
|
34
|
+
|
35
|
+
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.
|
36
|
+
|
37
|
+
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/).
|
38
|
+
|
39
|
+
- **Feature: Add support for Elasticsearch 8.13.0**
|
40
|
+
|
41
|
+
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.
|
42
|
+
|
43
|
+
- **Bugfix: Add 'request.temperature' to ruby-openai chat completion summaries**
|
44
|
+
|
45
|
+
Previously, the agent was not reporting the `request.temperature` attribute on `LlmChatCompletionSummary` events through ruby-openai instrumentation. We are now reporting this attribute.
|
46
|
+
|
3
47
|
## v9.8.0
|
4
48
|
|
5
49
|
Version 9.8.0 introduces instrumentation for ruby-openai, adds the option to store tracer state on the thread-level, hardens the browser agent insertion logic to better proactively anticipate errors, and prevents excpetions from being raised in the Active Support Broadcast logger instrumentation.
|
@@ -15,7 +59,7 @@ Version 9.8.0 introduces instrumentation for ruby-openai, adds the option to sto
|
|
15
59
|
This version introduces two new APIs that allow users to record additional information on LLM events:
|
16
60
|
* `NewRelic::Agent.record_llm_feedback_event` - Records user feedback events.
|
17
61
|
* `NewRelic::Agent.set_llm_token_count_callback` - Sets a callback proc for calculating `token_count` attributes for embedding and chat completion message events.
|
18
|
-
|
62
|
+
|
19
63
|
Visit [RubyDoc](https://rubydoc.info/github/newrelic/newrelic-ruby-agent/) for more information on each of these APIs.
|
20
64
|
|
21
65
|
- **Feature: Store tracer state on thread-level**
|
@@ -49,7 +93,7 @@ Version 9.7.0 introduces ViewComponent instrumentation, changes the endpoint use
|
|
49
93
|
|
50
94
|
- **Feature: ViewComponent instrumentation**
|
51
95
|
|
52
|
-
[ViewComponent](https://viewcomponent.org/) is a now an instrumented library. [PR#2367](https://github.com/newrelic/newrelic-ruby-agent/pull/2367)
|
96
|
+
[ViewComponent](https://viewcomponent.org/) is a now an instrumented library. [PR#2367](https://github.com/newrelic/newrelic-ruby-agent/pull/2367)
|
53
97
|
|
54
98
|
- **Feature: Use root path to access Elasticsearch cluster name**
|
55
99
|
|
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/bootstrap.rb
ADDED
@@ -0,0 +1,105 @@
|
|
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/bootstrap"
|
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.dirname(__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
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def self.check_for_require
|
73
|
+
warn_and_exit "#{__FILE__} is meant to be required, not invoked directly" if $PROGRAM_NAME == __FILE__
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.check_for_rubyopt
|
77
|
+
unless ENV[RUBYOPT].to_s.match?("-r #{__FILE__.rpartition('.').first}")
|
78
|
+
warn_and_exit "#{__FILE__} is meant to be required via the RUBYOPT env var"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.check_for_bundler
|
83
|
+
require_bundler
|
84
|
+
|
85
|
+
warn_and_exit 'Required Ruby Bundler class Bundler::Runtime not defined!' unless defined?(Bundler::Runtime)
|
86
|
+
|
87
|
+
unless Bundler::Runtime.method_defined?(:require)
|
88
|
+
warn_and_exit "The active Ruby Bundler instance doesn't offer Bundler::Runtime#require"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.require_bundler
|
93
|
+
require BUNDLER
|
94
|
+
rescue LoadError => e
|
95
|
+
warn_and_exit "Required Ruby library '#{BUNDLER}' could not be required - #{e}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.warn_and_exit(msg)
|
99
|
+
warn "New Relic entrypoint at #{__FILE__} encountered an issue:\n\t#{msg}"
|
100
|
+
|
101
|
+
exit 1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
NRBundlerPatcher.patch
|
@@ -34,6 +34,7 @@ require 'new_relic/agent/utilization_data'
|
|
34
34
|
require 'new_relic/environment_report'
|
35
35
|
require 'new_relic/agent/attribute_filter'
|
36
36
|
require 'new_relic/agent/adaptive_sampler'
|
37
|
+
require 'new_relic/agent/serverless_handler'
|
37
38
|
require 'new_relic/agent/connect/request_builder'
|
38
39
|
require 'new_relic/agent/connect/response_handler'
|
39
40
|
|
@@ -96,6 +97,7 @@ module NewRelic
|
|
96
97
|
@monotonic_gc_profiler = VM::MonotonicGCProfiler.new
|
97
98
|
@adaptive_sampler = AdaptiveSampler.new(Agent.config[:sampling_target],
|
98
99
|
Agent.config[:sampling_target_period_in_seconds])
|
100
|
+
@serverless_handler = ServerlessHandler.new
|
99
101
|
end
|
100
102
|
|
101
103
|
def init_event_handlers
|
@@ -172,6 +174,7 @@ module NewRelic
|
|
172
174
|
attr_reader :transaction_event_recorder
|
173
175
|
attr_reader :attribute_filter
|
174
176
|
attr_reader :adaptive_sampler
|
177
|
+
attr_reader :serverless_handler
|
175
178
|
|
176
179
|
def transaction_event_aggregator
|
177
180
|
@transaction_event_recorder.transaction_event_aggregator
|
@@ -307,7 +310,7 @@ module NewRelic
|
|
307
310
|
@stats_engine = StatsEngine.new
|
308
311
|
end
|
309
312
|
|
310
|
-
def flush_pipe_data
|
313
|
+
def flush_pipe_data # used only by resque
|
311
314
|
if connected? && @service.is_a?(PipeService)
|
312
315
|
transmit_data_types
|
313
316
|
end
|
@@ -27,9 +27,13 @@ module NewRelic
|
|
27
27
|
@connect_state == :disconnected
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def serverless?
|
31
|
+
Agent.config[:'serverless_mode.enabled']
|
32
|
+
end
|
33
|
+
|
34
|
+
# Don't connect if we're already connected, if we're in serverless mode,
|
35
|
+
# or if we tried to connect and were rejected with prejudice because of
|
36
|
+
# a license issue, unless we're forced to by force_reconnect.
|
33
37
|
def should_connect?(force = false)
|
34
38
|
force || (!connected? && !disconnected?)
|
35
39
|
end
|
@@ -62,10 +66,8 @@ module NewRelic
|
|
62
66
|
# no longer try to connect to the server, saving the
|
63
67
|
# application and the server load
|
64
68
|
def handle_license_error(error)
|
65
|
-
::NewRelic::Agent.logger.error(
|
66
|
-
|
67
|
-
'Visit NewRelic.com to obtain a valid license key, or to upgrade your account.'
|
68
|
-
)
|
69
|
+
::NewRelic::Agent.logger.error(error.message,
|
70
|
+
'Visit newrelic.com to obtain a valid license key, or to upgrade your account.')
|
69
71
|
disconnect
|
70
72
|
end
|
71
73
|
|
@@ -94,7 +96,7 @@ module NewRelic
|
|
94
96
|
# connects, then configures the agent using the response from
|
95
97
|
# the connect service
|
96
98
|
def connect_to_server
|
97
|
-
request_builder = ::NewRelic::Agent::Connect::RequestBuilder.new(
|
99
|
+
request_builder = ::NewRelic::Agent::Connect::RequestBuilder.new(
|
98
100
|
@service,
|
99
101
|
Agent.config,
|
100
102
|
event_harvest_config,
|
@@ -128,7 +128,7 @@ module NewRelic
|
|
128
128
|
catch_errors do
|
129
129
|
NewRelic::Agent.disable_all_tracing do
|
130
130
|
connect(connection_options)
|
131
|
-
if connected?
|
131
|
+
if NewRelic::Agent.instance.connected?
|
132
132
|
create_and_run_event_loop
|
133
133
|
# never reaches here unless there is a problem or
|
134
134
|
# the agent is exiting
|
@@ -124,6 +124,8 @@ module NewRelic
|
|
124
124
|
# Warn the user if they have configured their agent not to
|
125
125
|
# send data, that way we can see this clearly in the log file
|
126
126
|
def monitoring?
|
127
|
+
return false if Agent.config[:'serverless_mode.enabled']
|
128
|
+
|
127
129
|
if Agent.config[:monitor_mode]
|
128
130
|
true
|
129
131
|
else
|
@@ -146,7 +148,6 @@ module NewRelic
|
|
146
148
|
end
|
147
149
|
end
|
148
150
|
|
149
|
-
# A correct license key exists and is of the proper length
|
150
151
|
def has_correct_license_key?
|
151
152
|
has_license_key? && correct_license_length
|
152
153
|
end
|
@@ -132,7 +132,8 @@ module NewRelic
|
|
132
132
|
end
|
133
133
|
|
134
134
|
def wants_stdout?
|
135
|
-
::NewRelic::Agent.config[:log_file_path].casecmp(NewRelic::STANDARD_OUT) == 0
|
135
|
+
::NewRelic::Agent.config[:log_file_path].casecmp(NewRelic::STANDARD_OUT) == 0 ||
|
136
|
+
::NewRelic::Agent.config[:'serverless_mode.enabled']
|
136
137
|
end
|
137
138
|
|
138
139
|
def find_or_create_file_path(path_setting, root)
|
@@ -0,0 +1,56 @@
|
|
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, config)
|
12
|
+
region = config.region
|
13
|
+
account_id = NewRelic::Agent::Aws.convert_access_key_to_account_id(config.credentials.access_key_id)
|
14
|
+
|
15
|
+
"arn:aws:#{service}:#{region}:#{account_id}:#{resource}"
|
16
|
+
rescue => e
|
17
|
+
NewRelic::Agent.logger.warn("Failed to create ARN: #{e}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.convert_access_key_to_account_id(access_key)
|
21
|
+
decoded_key = Integer(decode_to_hex(access_key[4..-1]), 16)
|
22
|
+
mask = Integer(HEX_MASK, 16)
|
23
|
+
(decoded_key & mask) >> 7
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.decode_to_hex(access_key)
|
27
|
+
bytes = access_key.delete('=').each_char.map { |c| CHARACTERS.index(c) }
|
28
|
+
|
29
|
+
bytes.each_slice(8).map do |section|
|
30
|
+
convert_section(section)
|
31
|
+
end.flatten[0...6].join
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.convert_section(section)
|
35
|
+
buffer = 0
|
36
|
+
section.each do |chunk|
|
37
|
+
buffer = (buffer << 5) + chunk
|
38
|
+
end
|
39
|
+
|
40
|
+
chunk_count = (section.length * 5.0 / 8.0).floor
|
41
|
+
|
42
|
+
if section.length < 8
|
43
|
+
buffer >>= (5 - (chunk_count * 8)) % 5
|
44
|
+
end
|
45
|
+
|
46
|
+
decoded = []
|
47
|
+
chunk_count.times do |i|
|
48
|
+
shift = 8 * (chunk_count - 1 - i)
|
49
|
+
decoded << ((buffer >> shift) & 255).to_s(16)
|
50
|
+
end
|
51
|
+
|
52
|
+
decoded
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -52,9 +52,24 @@ module NewRelic
|
|
52
52
|
result
|
53
53
|
end
|
54
54
|
|
55
|
+
def self.default_settings(key)
|
56
|
+
::NewRelic::Agent::Configuration::DEFAULTS[key]
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.value_from_defaults(key, subkey)
|
60
|
+
default_settings(key)&.send(:[], subkey)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.allowlist_for(key)
|
64
|
+
value_from_defaults(key, :allowlist)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.default_for(key)
|
68
|
+
value_from_defaults(key, :default)
|
69
|
+
end
|
70
|
+
|
55
71
|
def self.transform_for(key)
|
56
|
-
|
57
|
-
default_settings[:transform] if default_settings
|
72
|
+
value_from_defaults(key, :transform)
|
58
73
|
end
|
59
74
|
|
60
75
|
def self.config_search_paths # rubocop:disable Metrics/AbcSize
|
@@ -375,9 +390,11 @@ module NewRelic
|
|
375
390
|
:description => <<~DESCRIPTION
|
376
391
|
If `false`, LLM instrumentation (OpenAI only for now) will not capture input and output content on specific LLM events.
|
377
392
|
|
378
|
-
|
379
|
-
|
380
|
-
|
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.
|
381
398
|
DESCRIPTION
|
382
399
|
},
|
383
400
|
# this is only set via server side config
|
@@ -462,12 +479,9 @@ module NewRelic
|
|
462
479
|
:public => true,
|
463
480
|
:type => Boolean,
|
464
481
|
:allowed_from_server => false,
|
465
|
-
:description =>
|
466
|
-
|
467
|
-
|
468
|
-
'and the agent is detecting the Sinatra app and skipping the `at_exit` handler as a result. Sinatra classically ' \
|
469
|
-
'runs the entire application in an `at_exit` block and would otherwise misbehave if the agent\'s `at_exit` handler ' \
|
470
|
-
'was also installed in those circumstances. Note: `send_data_on_exit` should also be set to `true` in tandem with this setting.'
|
482
|
+
:description => <<~DESC
|
483
|
+
Forces the exit handler that sends all cached data to collector before shutting down to be installed regardless of detecting scenarios where it generally should not be. Known use-case for this option is where Sinatra is running as an embedded service within another framework and the agent is detecting the Sinatra app and skipping the `at_exit` handler as a result. Sinatra classically runs the entire application in an `at_exit` block and would otherwise misbehave if the Agent's `at_exit` handler was also installed in those circumstances. Note: `send_data_on_exit` should also be set to `true` in tandem with this setting."
|
484
|
+
DESC
|
471
485
|
},
|
472
486
|
:high_security => {
|
473
487
|
:default => false,
|
@@ -765,6 +779,15 @@ module NewRelic
|
|
765
779
|
:allowed_from_server => true,
|
766
780
|
: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).'
|
767
781
|
},
|
782
|
+
# CSP nonce
|
783
|
+
:'browser_monitoring.content_security_policy_nonce' => {
|
784
|
+
:default => value_of(:'rum.enabled'),
|
785
|
+
:documentation_default => false,
|
786
|
+
:public => true,
|
787
|
+
:type => Boolean,
|
788
|
+
:allowed_from_server => false,
|
789
|
+
: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+.'
|
790
|
+
},
|
768
791
|
# Transaction events
|
769
792
|
:'transaction_events.enabled' => {
|
770
793
|
:default => true,
|
@@ -800,6 +823,7 @@ module NewRelic
|
|
800
823
|
:public => true,
|
801
824
|
:type => String,
|
802
825
|
:allowed_from_server => false,
|
826
|
+
:allowlist => %w[debug info warn error fatal unknown DEBUG INFO WARN ERROR FATAL UNKNOWN],
|
803
827
|
:description => <<~DESCRIPTION
|
804
828
|
Sets the minimum level a log event must have to be forwarded to New Relic.
|
805
829
|
|
@@ -1053,7 +1077,9 @@ module NewRelic
|
|
1053
1077
|
Rails::Command::GenerateCommand
|
1054
1078
|
Rails::Command::InitializersCommand
|
1055
1079
|
Rails::Command::NotesCommand
|
1080
|
+
Rails::Command::RakeCommand
|
1056
1081
|
Rails::Command::RoutesCommand
|
1082
|
+
Rails::Command::RunnerCommand
|
1057
1083
|
Rails::Command::SecretsCommand
|
1058
1084
|
Rails::Console
|
1059
1085
|
Rails::DBConsole].join(','),
|
@@ -1424,6 +1450,14 @@ module NewRelic
|
|
1424
1450
|
:allowed_from_server => false,
|
1425
1451
|
:description => 'Controls auto-instrumentation of bunny at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1426
1452
|
},
|
1453
|
+
:'instrumentation.dynamodb' => {
|
1454
|
+
:default => 'auto',
|
1455
|
+
:public => true,
|
1456
|
+
:type => String,
|
1457
|
+
:dynamic_name => true,
|
1458
|
+
:allowed_from_server => false,
|
1459
|
+
:description => 'Controls auto-instrumentation of the aws-sdk-dynamodb library at start-up. May be one of `auto`, `prepend`, `chain`, `disabled`.'
|
1460
|
+
},
|
1427
1461
|
:'instrumentation.fiber' => {
|
1428
1462
|
:default => 'auto',
|
1429
1463
|
:public => true,
|
@@ -1472,7 +1506,7 @@ module NewRelic
|
|
1472
1506
|
:type => String,
|
1473
1507
|
:dynamic_name => true,
|
1474
1508
|
:allowed_from_server => false,
|
1475
|
-
:description => 'Controls auto-instrumentation of ethon at start up. May be one of
|
1509
|
+
:description => 'Controls auto-instrumentation of ethon at start up. May be one of `auto`, `prepend`, `chain`, `disabled`'
|
1476
1510
|
},
|
1477
1511
|
:'instrumentation.excon' => {
|
1478
1512
|
:default => 'enabled',
|
@@ -1542,7 +1576,7 @@ module NewRelic
|
|
1542
1576
|
:type => String,
|
1543
1577
|
:dynamic_name => true,
|
1544
1578
|
:allowed_from_server => false,
|
1545
|
-
:description => 'Controls auto-instrumentation of httpx at start up. May be one of
|
1579
|
+
:description => 'Controls auto-instrumentation of httpx at start up. May be one of `auto`, `prepend`, `chain`, `disabled`'
|
1546
1580
|
},
|
1547
1581
|
:'instrumentation.logger' => {
|
1548
1582
|
:default => instrumentation_value_from_boolean(:'application_logging.enabled'),
|
@@ -1604,7 +1638,7 @@ module NewRelic
|
|
1604
1638
|
:type => String,
|
1605
1639
|
:dynamic_name => true,
|
1606
1640
|
:allowed_from_server => false,
|
1607
|
-
:description => 'Controls auto-instrumentation of the ruby-openai gem at start-up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
|
1641
|
+
: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.'
|
1608
1642
|
},
|
1609
1643
|
:'instrumentation.puma_rack' => {
|
1610
1644
|
:default => value_of(:'instrumentation.rack'),
|
@@ -1844,6 +1878,17 @@ module NewRelic
|
|
1844
1878
|
:transform => DefaultSource.method(:convert_to_regexp_list),
|
1845
1879
|
:description => 'Define transactions you want the agent to ignore, by specifying a list of patterns matching the URI you want to ignore. For more detail, see [the docs on ignoring specific transactions](/docs/agents/ruby-agent/api-guides/ignoring-specific-transactions/#config-ignoring).'
|
1846
1880
|
},
|
1881
|
+
# Serverless
|
1882
|
+
:'serverless_mode.enabled' => {
|
1883
|
+
:default => false,
|
1884
|
+
:public => true,
|
1885
|
+
:type => Boolean,
|
1886
|
+
:allowed_from_server => false,
|
1887
|
+
:transform => proc { |bool| NewRelic::Agent::ServerlessHandler.env_var_set? || bool },
|
1888
|
+
:description => 'If `true`, the agent will operate in a streamlined mode suitable for use with short-lived ' \
|
1889
|
+
'serverless functions. NOTE: Only AWS Lambda functions are supported currently and this ' \
|
1890
|
+
"option is not intended for use without [New Relic's Ruby Lambda layer](https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/get-started/monitoring-aws-lambda-serverless-monitoring/) offering."
|
1891
|
+
},
|
1847
1892
|
# Sidekiq
|
1848
1893
|
:'sidekiq.args.include' => {
|
1849
1894
|
default: NewRelic::EMPTY_ARRAY,
|
@@ -1936,7 +1981,11 @@ module NewRelic
|
|
1936
1981
|
:public => true,
|
1937
1982
|
:type => Integer,
|
1938
1983
|
:allowed_from_server => true,
|
1939
|
-
:description =>
|
1984
|
+
:description => <<~DESC
|
1985
|
+
* Defines the maximum number of span events reported from a single harvest. Any Integer between `1` and `10000` is valid.'
|
1986
|
+
* When configuring the agent for [AI monitoring](/docs/ai-monitoring/intro-to-ai-monitoring), set to max value `10000`.\
|
1987
|
+
This ensures that the agent captures the maximum amount of distributed traces.
|
1988
|
+
DESC
|
1940
1989
|
},
|
1941
1990
|
# Strip exception messages
|
1942
1991
|
:'strip_exception_messages.enabled' => {
|
@@ -2252,6 +2301,7 @@ module NewRelic
|
|
2252
2301
|
:public => true,
|
2253
2302
|
:type => Symbol,
|
2254
2303
|
:allowed_from_server => false,
|
2304
|
+
:allowlist => %i[none low medium high],
|
2255
2305
|
:external => :infinite_tracing,
|
2256
2306
|
:description => <<~DESC
|
2257
2307
|
Configure the compression level for data sent to the trace observer.
|
@@ -99,7 +99,7 @@ module NewRelic
|
|
99
99
|
elsif !value.nil?
|
100
100
|
self[config_key] = true
|
101
101
|
end
|
102
|
-
|
102
|
+
elsif !serverless?
|
103
103
|
::NewRelic::Agent.logger.info("#{environment_key} does not have a corresponding configuration setting (#{config_key} does not exist).")
|
104
104
|
::NewRelic::Agent.logger.info('Run `rake newrelic:config:docs` or visit https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration to see a list of available configuration settings.')
|
105
105
|
self[config_key] = value
|
@@ -114,6 +114,14 @@ module NewRelic
|
|
114
114
|
def collect_new_relic_environment_variable_keys
|
115
115
|
ENV.keys.select { |key| key.match(SUPPORTED_PREFIXES) }
|
116
116
|
end
|
117
|
+
|
118
|
+
# we can't rely on the :'serverless_mode.enabled' config parameter being
|
119
|
+
# set yet to signify serverless mode given that we're in the midst of
|
120
|
+
# building the config but we can always rely on the env var being set
|
121
|
+
# by the Lambda layer
|
122
|
+
def serverless?
|
123
|
+
NewRelic::Agent::ServerlessHandler.env_var_set?
|
124
|
+
end
|
117
125
|
end
|
118
126
|
end
|
119
127
|
end
|
@@ -138,7 +138,11 @@ module NewRelic
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def evaluate_and_apply_transformations(key, value)
|
141
|
-
|
141
|
+
evaluated = evaluate_procs(value)
|
142
|
+
default = enforce_allowlist(key, evaluated)
|
143
|
+
return default if default
|
144
|
+
|
145
|
+
apply_transformations(key, evaluated)
|
142
146
|
end
|
143
147
|
|
144
148
|
def apply_transformations(key, value)
|
@@ -146,7 +150,7 @@ module NewRelic
|
|
146
150
|
begin
|
147
151
|
transform.call(value)
|
148
152
|
rescue => e
|
149
|
-
|
153
|
+
NewRelic::Agent.logger.error("Error applying transformation for #{key}, pre-transform value was: #{value}.", e)
|
150
154
|
raise e
|
151
155
|
end
|
152
156
|
else
|
@@ -154,8 +158,21 @@ module NewRelic
|
|
154
158
|
end
|
155
159
|
end
|
156
160
|
|
161
|
+
def enforce_allowlist(key, value)
|
162
|
+
return unless allowlist = default_source.allowlist_for(key)
|
163
|
+
return if allowlist.include?(value)
|
164
|
+
|
165
|
+
default = default_source.default_for(key)
|
166
|
+
NewRelic::Agent.logger.warn "Invalid value '#{value}' for #{key}, applying default value of '#{default}'"
|
167
|
+
default
|
168
|
+
end
|
169
|
+
|
157
170
|
def transform_from_default(key)
|
158
|
-
|
171
|
+
default_source.transform_for(key)
|
172
|
+
end
|
173
|
+
|
174
|
+
def default_source
|
175
|
+
NewRelic::Agent::Configuration::DefaultSource
|
159
176
|
end
|
160
177
|
|
161
178
|
def register_callback(key, &proc)
|
@@ -214,7 +231,7 @@ module NewRelic
|
|
214
231
|
begin
|
215
232
|
thawed_layer[k] = instance_eval(&v) if v.respond_to?(:call)
|
216
233
|
rescue => e
|
217
|
-
|
234
|
+
NewRelic::Agent.logger.debug("#{e.class.name} : #{e.message} - when accessing config key #{k}")
|
218
235
|
thawed_layer[k] = nil
|
219
236
|
end
|
220
237
|
thawed_layer.delete(:config)
|
@@ -383,7 +400,7 @@ module NewRelic
|
|
383
400
|
# is expensive enough that we don't want to do it unless we're
|
384
401
|
# actually going to be logging the message based on our current log
|
385
402
|
# level, so use a `do` block.
|
386
|
-
|
403
|
+
NewRelic::Agent.logger.debug do
|
387
404
|
hash = flattened.delete_if { |k, _h| DEFAULTS.fetch(k, {}).fetch(:exclude_from_reported_settings, false) }
|
388
405
|
"Updating config (#{direction}) from #{source.class}. Results: #{hash.inspect}"
|
389
406
|
end
|
@@ -24,7 +24,7 @@ module NewRelic
|
|
24
24
|
:host => local_host,
|
25
25
|
:display_host => Agent.config[:'process_host.display_name'],
|
26
26
|
:app_name => Agent.config[:app_name],
|
27
|
-
:language =>
|
27
|
+
:language => LANGUAGE,
|
28
28
|
:labels => Agent.config.parsed_labels,
|
29
29
|
:agent_version => NewRelic::VERSION::STRING,
|
30
30
|
:environment => @environment_report,
|