newrelic_rpm 9.18.0 → 9.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/lib/new_relic/agent/agent.rb +2 -0
- data/lib/new_relic/agent/configuration/default_source.rb +27 -0
- data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +6 -2
- data/lib/new_relic/agent/opentelemetry/trace/span.rb +23 -0
- data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +38 -0
- data/lib/new_relic/agent/opentelemetry/trace/tracer_provider.rb +18 -0
- data/lib/new_relic/agent/opentelemetry/trace.rb +15 -0
- data/lib/new_relic/agent/opentelemetry_bridge.rb +26 -0
- data/lib/new_relic/agent/span_event_primitive.rb +3 -1
- data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -1
- data/lib/new_relic/agent/transaction/request_attributes.rb +1 -6
- data/lib/new_relic/agent/transaction/trace_context.rb +33 -4
- data/lib/new_relic/version.rb +1 -1
- data/newrelic.yml +11 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a2b588c4be509b5a02bb0516a47e9329cab3bcf79c97f614d4349291db0876f
|
4
|
+
data.tar.gz: 30f1dcd2997242e38836aa3325badb71656aaa3aa074857a2edad75f6e21972b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6915cfd19ea57029473609dd02b4e9bd110aaa3766f13af648705a0132d4608f33051ad0e44f6c03f72b037eb99c64f1992c92408d1caedd3381538e906c4b0d
|
7
|
+
data.tar.gz: 87c1d548bd4a78eb26706eae9f1932c9fb394c05f16e8d4603ce8b690e4df255fdd8748f7f2b09501a7e73770961ec20f6df07435255db293bb4e7395400094c
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes
|
2
2
|
|
3
|
+
## v9.19.0
|
4
|
+
|
5
|
+
- **Feature: Add Thread ID as attribute to all spans**
|
6
|
+
|
7
|
+
The agent will now record the Thread ID as an attribute on each span. [PR#3122](https://github.com/newrelic/newrelic-ruby-agent/pull/3122)
|
8
|
+
|
9
|
+
- **Feature: Add support for W3C TraceContext Trace Flag**
|
10
|
+
|
11
|
+
Previously, the agent would not use the trace flag field of the traceparent header for sampling decisions. This could lead to fragmented traces in the UI. While the default behavior remains unchanged, two new configuration options, `distributed_tracing.sampler.remote_parent_sampled` and `distributed_tracing.sampler.remote_parent_not_sampled`, have been introduced to allow more control over the way sampling decisions are made. [PR#3135](https://github.com/newrelic/newrelic-ruby-agent/pull/3135)
|
12
|
+
|
13
|
+
- **Bugfix: Include request.uri in Transaction events by default**
|
14
|
+
|
15
|
+
[The New Relic data dictionary expects Transaction events to have the `request.uri` attribute.](https://docs.newrelic.com/attribute-dictionary/?event=Transaction&attribute=request.uri) The Ruby agent now fulfills this expectation. If you would like to exclude `request.uri` from Transaction events, you can do so by setting `transaction_events.attributes.exclude` to `'request.uri'`. [PR#3103](https://github.com/newrelic/newrelic-ruby-agent/pull/3103)
|
16
|
+
|
17
|
+
- **Bugfix: Fix error in Active Job instrumentation when using perform_all_later**
|
18
|
+
|
19
|
+
Previously, when Active Job's `perform_all_later` method was called and the agent was running, a `NoMethodError` would be raised with the message `undefined method 'queue_name' for nil`. The error has been fixed and the name of the segment will reflect the first job in the queue. Our thanks goes to [@tan-linx](https://github.com/tan-linx) for bringing this to our attention and providing a fix. [PR#3110](https://github.com/newrelic/newrelic-ruby-agent/pull/3110)
|
20
|
+
|
3
21
|
## v9.18.0
|
4
22
|
|
5
23
|
- **Feature: Add elasticsearch.capture_cluster_name configuration option**
|
@@ -38,6 +38,7 @@ require 'new_relic/agent/adaptive_sampler'
|
|
38
38
|
require 'new_relic/agent/serverless_handler'
|
39
39
|
require 'new_relic/agent/connect/request_builder'
|
40
40
|
require 'new_relic/agent/connect/response_handler'
|
41
|
+
require 'new_relic/agent/opentelemetry_bridge'
|
41
42
|
|
42
43
|
require 'new_relic/agent/agent_helpers/connect'
|
43
44
|
require 'new_relic/agent/agent_helpers/harvest'
|
@@ -100,6 +101,7 @@ module NewRelic
|
|
100
101
|
@adaptive_sampler = AdaptiveSampler.new(Agent.config[:sampling_target],
|
101
102
|
Agent.config[:sampling_target_period_in_seconds])
|
102
103
|
@serverless_handler = ServerlessHandler.new
|
104
|
+
@opentelemetry_bridge = OpenTelemetryBridge.new
|
103
105
|
end
|
104
106
|
|
105
107
|
def init_event_handlers
|
@@ -762,7 +762,12 @@ module NewRelic
|
|
762
762
|
DESCRIPTION
|
763
763
|
},
|
764
764
|
:'error_collector.ignore_messages' => {
|
765
|
+
# we have to keep the hash rocket in the actual default so the
|
766
|
+
# class name key is treated like a string rather than a symbol.
|
767
|
+
# however, this isn't valid yaml, so document something that is
|
768
|
+
# valid yaml
|
765
769
|
:default => {'ThreadError' => ['queue empty']},
|
770
|
+
:documentation_default => {'ThreadError': ['queue empty']},
|
766
771
|
:public => true,
|
767
772
|
:type => Hash,
|
768
773
|
:allowed_from_server => true,
|
@@ -1458,6 +1463,20 @@ module NewRelic
|
|
1458
1463
|
:allowed_from_server => true,
|
1459
1464
|
:description => 'Distributed tracing lets you see the path that a request takes through your distributed system. Enabling distributed tracing changes the behavior of some New Relic features, so carefully consult the [transition guide](/docs/transition-guide-distributed-tracing) before you enable this feature.'
|
1460
1465
|
},
|
1466
|
+
:'distributed_tracing.sampler.remote_parent_sampled' => {
|
1467
|
+
:default => 'default',
|
1468
|
+
:public => true,
|
1469
|
+
:type => String,
|
1470
|
+
:allowed_from_server => true,
|
1471
|
+
:description => 'This setting controls the behavior of transaction sampling when a remote parent is sampled and the trace flag is set in the traceparent. Available values are `default`, `always_on`, and `always_off`.'
|
1472
|
+
},
|
1473
|
+
:'distributed_tracing.sampler.remote_parent_not_sampled' => {
|
1474
|
+
:default => 'default',
|
1475
|
+
:public => true,
|
1476
|
+
:type => String,
|
1477
|
+
:allowed_from_server => true,
|
1478
|
+
:description => 'This setting controls the behavior of transaction sampling when a remote parent is not sampled and the trace flag is not set in the traceparent. Available values are `default`, `always_on`, and `always_off`.'
|
1479
|
+
},
|
1461
1480
|
# Elasticsearch
|
1462
1481
|
:'elasticsearch.capture_cluster_name' => {
|
1463
1482
|
:default => true,
|
@@ -2490,6 +2509,14 @@ module NewRelic
|
|
2490
2509
|
:allowed_from_server => true,
|
2491
2510
|
:description => 'Number of seconds betwixt connections to the New Relic span event collection services.'
|
2492
2511
|
},
|
2512
|
+
# TODO: Sync with the other agents to see what the config should be named, how it should be enabled, how it should be described
|
2513
|
+
:'opentelemetry_bridge.enabled' => {
|
2514
|
+
:default => false,
|
2515
|
+
:public => false,
|
2516
|
+
:type => Boolean,
|
2517
|
+
:allowed_from_server => false,
|
2518
|
+
:description => 'Enables the creation of Transaction Trace segments and timeslice metrics from OpenTelemetry Spans. This will help drive New Relic UI experience for opentelemetry spans. **WARNING**: This is not feature complete and is not intended to be enabled yet.'
|
2519
|
+
},
|
2493
2520
|
:force_reconnect => {
|
2494
2521
|
:default => false,
|
2495
2522
|
:public => false,
|
@@ -8,7 +8,7 @@ module NewRelic
|
|
8
8
|
module Agent
|
9
9
|
module Instrumentation
|
10
10
|
class ActiveJobSubscriber < NotificationsSubscriber
|
11
|
-
PAYLOAD_KEYS = %i[adapter db_runtime error job wait]
|
11
|
+
PAYLOAD_KEYS = %i[adapter db_runtime error job wait jobs]
|
12
12
|
|
13
13
|
def add_segment_params(segment, payload)
|
14
14
|
PAYLOAD_KEYS.each do |key|
|
@@ -16,8 +16,12 @@ module NewRelic
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
# NOTE: For `enqueue_all.active_job`, only the first job is used to determine the queue.
|
20
|
+
# Therefore, this assumes all jobs given as arguments for perform_all_later share the same queue.
|
19
21
|
def metric_name(name, payload)
|
20
|
-
|
22
|
+
job = payload[:job] || payload[:jobs].first
|
23
|
+
|
24
|
+
queue = job.queue_name
|
21
25
|
method = method_from_name(name)
|
22
26
|
"Ruby/ActiveJob/#{queue}/#{method}"
|
23
27
|
end
|
@@ -0,0 +1,23 @@
|
|
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 OpenTelemetry
|
8
|
+
module Trace
|
9
|
+
class Span < ::OpenTelemetry::Trace::Span
|
10
|
+
attr_reader :context
|
11
|
+
|
12
|
+
def initialize(segment:, transaction:)
|
13
|
+
@context = ::OpenTelemetry::Trace::SpanContext.new(
|
14
|
+
trace_id: transaction.trace_id,
|
15
|
+
span_id: segment.guid,
|
16
|
+
trace_flags: 1
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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 OpenTelemetry
|
8
|
+
module Trace
|
9
|
+
class Tracer < ::OpenTelemetry::Trace::Tracer
|
10
|
+
def initialize(name = nil, version = nil)
|
11
|
+
@name = name || ''
|
12
|
+
@version = version || ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def in_span(name, attributes: nil, links: nil, start_timestamp: nil, kind: nil)
|
16
|
+
case kind
|
17
|
+
when :internal
|
18
|
+
begin
|
19
|
+
return yield unless NewRelic::Agent::Tracer.current_transaction
|
20
|
+
|
21
|
+
segment = NewRelic::Agent::Tracer.start_segment(name: name)
|
22
|
+
span = Span.new(segment: segment, transaction: segment.transaction)
|
23
|
+
|
24
|
+
::OpenTelemetry::Trace.with_span(span) do
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
ensure
|
28
|
+
segment&.finish
|
29
|
+
end
|
30
|
+
else
|
31
|
+
NewRelic::Agent.logger.debug("Span kind: #{kind} is not supported yet")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,18 @@
|
|
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 OpenTelemetry
|
8
|
+
module Trace
|
9
|
+
class TracerProvider < ::OpenTelemetry::Trace::TracerProvider
|
10
|
+
# TODO: Add a registration mechanism for tracers like exists in the SDK
|
11
|
+
def tracer(name = nil, version = nil)
|
12
|
+
@tracer ||= Tracer.new(name, version)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
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 OpenTelemetry
|
8
|
+
module Trace
|
9
|
+
require_relative 'trace/tracer_provider'
|
10
|
+
require_relative 'trace/tracer'
|
11
|
+
require_relative 'trace/span'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
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
|
+
class OpenTelemetryBridge
|
8
|
+
def initialize
|
9
|
+
# no-op without OpenTelemetry API & config
|
10
|
+
return unless defined?(OpenTelemetry) &&
|
11
|
+
NewRelic::Agent.config[:'opentelemetry_bridge.enabled']
|
12
|
+
|
13
|
+
OpenTelemetryBridge.install
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def self.install
|
19
|
+
require 'opentelemetry' # requires the opentelemetry-api gem
|
20
|
+
require_relative 'opentelemetry/trace'
|
21
|
+
|
22
|
+
::OpenTelemetry.tracer_provider = NewRelic::Agent::OpenTelemetry::Trace::TracerProvider.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -44,6 +44,7 @@ module NewRelic
|
|
44
44
|
TRUSTED_PARENT_KEY = 'trustedParentId'
|
45
45
|
TRACING_VENDORS_KEY = 'tracingVendors'
|
46
46
|
TRANSACTION_NAME_KEY = 'transaction.name'
|
47
|
+
THREAD_ID_KEY = 'thread.id'
|
47
48
|
|
48
49
|
# Strings for static values of the event structure
|
49
50
|
EVENT_TYPE = 'Span'
|
@@ -135,7 +136,8 @@ module NewRelic
|
|
135
136
|
PRIORITY_KEY => segment.transaction.priority,
|
136
137
|
TIMESTAMP_KEY => milliseconds_since_epoch(segment),
|
137
138
|
DURATION_KEY => segment.duration,
|
138
|
-
NAME_KEY => segment.name
|
139
|
+
NAME_KEY => segment.name,
|
140
|
+
THREAD_ID_KEY => segment.thread_id
|
139
141
|
}
|
140
142
|
|
141
143
|
# with infinite-tracing, transactions may or may not be sampled!
|
@@ -19,7 +19,7 @@ module NewRelic
|
|
19
19
|
# after its parent. We will use the optimized exclusive duration
|
20
20
|
# calculation in all other cases.
|
21
21
|
#
|
22
|
-
attr_reader :start_time, :end_time, :duration, :exclusive_duration, :guid, :starting_segment_key
|
22
|
+
attr_reader :start_time, :end_time, :duration, :exclusive_duration, :guid, :starting_segment_key, :thread_id
|
23
23
|
attr_accessor :name, :parent, :children_time, :transaction, :transaction_name, :llm_event
|
24
24
|
attr_writer :record_metrics, :record_scoped_metric, :record_on_finish
|
25
25
|
attr_reader :noticed_error
|
@@ -30,6 +30,7 @@ module NewRelic
|
|
30
30
|
def initialize(name = nil, start_time = nil)
|
31
31
|
@name = name
|
32
32
|
@starting_segment_key = NewRelic::Agent::Tracer.current_segment_key
|
33
|
+
@thread_id = Thread.current.object_id
|
33
34
|
@transaction_name = nil
|
34
35
|
@transaction = nil
|
35
36
|
@guid = NewRelic::Agent::GuidGenerator.generate_guid
|
@@ -43,12 +43,7 @@ module NewRelic
|
|
43
43
|
end
|
44
44
|
|
45
45
|
if request_path
|
46
|
-
|
47
|
-
default_destinations
|
48
|
-
else
|
49
|
-
AttributeFilter::DST_TRANSACTION_TRACER | AttributeFilter::DST_ERROR_COLLECTOR
|
50
|
-
end
|
51
|
-
txn.add_agent_attribute(:'request.uri', request_path, destinations)
|
46
|
+
txn.add_agent_attribute(:'request.uri', request_path, default_destinations)
|
52
47
|
end
|
53
48
|
|
54
49
|
if accept
|
@@ -136,10 +136,8 @@ module NewRelic
|
|
136
136
|
|
137
137
|
transaction.distributed_tracer.parent_transaction_id = payload.transaction_id
|
138
138
|
|
139
|
-
|
140
|
-
|
141
|
-
transaction.priority = payload.priority if payload.priority
|
142
|
-
end
|
139
|
+
determine_sampling_decision(payload, header_data)
|
140
|
+
|
143
141
|
NewRelic::Agent.increment_metric(ACCEPT_SUCCESS_METRIC)
|
144
142
|
true
|
145
143
|
rescue => e
|
@@ -148,6 +146,37 @@ module NewRelic
|
|
148
146
|
false
|
149
147
|
end
|
150
148
|
|
149
|
+
def determine_sampling_decision(payload, header_data)
|
150
|
+
if header_data.trace_parent['trace_flags'] == '01'
|
151
|
+
set_priority_and_sampled(NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled'], payload)
|
152
|
+
elsif header_data.trace_parent['trace_flags'] == '00'
|
153
|
+
set_priority_and_sampled(NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled'], payload)
|
154
|
+
else
|
155
|
+
use_nr_tracestate_sampled(payload)
|
156
|
+
end
|
157
|
+
rescue
|
158
|
+
use_nr_tracestate_sampled(payload)
|
159
|
+
end
|
160
|
+
|
161
|
+
def use_nr_tracestate_sampled(payload)
|
162
|
+
unless payload.sampled.nil?
|
163
|
+
transaction.sampled = payload.sampled
|
164
|
+
transaction.priority = payload.priority if payload.priority
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def set_priority_and_sampled(config, payload)
|
169
|
+
if config == 'always_on'
|
170
|
+
transaction.sampled = true
|
171
|
+
transaction.priority = 2.0
|
172
|
+
elsif config == 'always_off'
|
173
|
+
transaction.sampled = false
|
174
|
+
transaction.priority = 0
|
175
|
+
else # default
|
176
|
+
use_nr_tracestate_sampled(payload)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
151
180
|
def ignore_trace_context?
|
152
181
|
if trace_context_header_data
|
153
182
|
NewRelic::Agent.increment_metric(IGNORE_MULTIPLE_ACCEPT_METRIC)
|
data/lib/new_relic/version.rb
CHANGED
data/newrelic.yml
CHANGED
@@ -359,6 +359,16 @@ common: &default_settings
|
|
359
359
|
# enable this feature.
|
360
360
|
# distributed_tracing.enabled: true
|
361
361
|
|
362
|
+
# This setting controls the behavior of transaction sampling when a remote
|
363
|
+
# parent is not sampled and the trace flag is not set in the traceparent.
|
364
|
+
# Available values are default, always_on, and always_off.
|
365
|
+
# distributed_tracing.sampler.remote_parent_not_sampled: default
|
366
|
+
|
367
|
+
# This setting controls the behavior of transaction sampling when a remote
|
368
|
+
# parent is sampled and the trace flag is set in the traceparent. Available
|
369
|
+
# values are default, always_on, and always_off.
|
370
|
+
# distributed_tracing.sampler.remote_parent_sampled: default
|
371
|
+
|
362
372
|
# If true, the agent captures the Elasticsearch cluster name in transaction
|
363
373
|
# traces.
|
364
374
|
# elasticsearch.capture_cluster_name: true
|
@@ -409,7 +419,7 @@ common: &default_settings
|
|
409
419
|
# classes specified here occurs, if its error message contains one of the
|
410
420
|
# strings corresponding to it here, that error will be ignored.
|
411
421
|
# This option can't be set via environment variable.
|
412
|
-
# error_collector.ignore_messages: {
|
422
|
+
# error_collector.ignore_messages: {ThreadError: ["queue empty"]}
|
413
423
|
|
414
424
|
# A comma separated list of status codes, possibly including ranges. Errors
|
415
425
|
# associated with these status codes, where applicable, will be ignored.
|
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.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tanna McClure
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
- Hannah Ramadan
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2025-04-
|
13
|
+
date: 2025-04-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -614,6 +614,11 @@ files:
|
|
614
614
|
- lib/new_relic/agent/noticeable_error.rb
|
615
615
|
- lib/new_relic/agent/null_logger.rb
|
616
616
|
- lib/new_relic/agent/obfuscator.rb
|
617
|
+
- lib/new_relic/agent/opentelemetry/trace.rb
|
618
|
+
- lib/new_relic/agent/opentelemetry/trace/span.rb
|
619
|
+
- lib/new_relic/agent/opentelemetry/trace/tracer.rb
|
620
|
+
- lib/new_relic/agent/opentelemetry/trace/tracer_provider.rb
|
621
|
+
- lib/new_relic/agent/opentelemetry_bridge.rb
|
617
622
|
- lib/new_relic/agent/parameter_filtering.rb
|
618
623
|
- lib/new_relic/agent/payload_metric_mapping.rb
|
619
624
|
- lib/new_relic/agent/pipe_channel_manager.rb
|