newrelic_rpm 9.14.0 → 9.18.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/.build_ignore +1 -0
- data/CHANGELOG.md +139 -5
- data/CONTRIBUTING.md +2 -2
- data/lib/boot/strap.rb +4 -3
- data/lib/new_relic/agent/agent.rb +4 -0
- data/lib/new_relic/agent/agent_helpers/connect.rb +3 -0
- data/lib/new_relic/agent/agent_helpers/harvest.rb +3 -0
- data/lib/new_relic/agent/agent_helpers/shutdown.rb +3 -0
- data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +1 -0
- data/lib/new_relic/agent/agent_helpers/startup.rb +7 -0
- data/lib/new_relic/agent/aws.rb +6 -0
- data/lib/new_relic/agent/configuration/default_source.rb +336 -115
- data/lib/new_relic/agent/configuration/manager.rb +1 -1
- data/lib/new_relic/agent/configuration/yaml_source.rb +6 -1
- data/lib/new_relic/agent/database.rb +41 -1
- data/lib/new_relic/agent/distributed_tracing.rb +2 -2
- data/lib/new_relic/agent/health_check.rb +136 -0
- data/lib/new_relic/agent/http_clients/uri_util.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_record.rb +1 -8
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +5 -1
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +9 -16
- data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger.rb +0 -2
- data/lib/new_relic/agent/instrumentation/active_support_logger.rb +0 -2
- data/lib/new_relic/agent/instrumentation/async_http.rb +1 -2
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/instrumentation.rb +66 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_firehose.rb +22 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/instrumentation.rb +91 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis.rb +22 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/chain.rb +33 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/instrumentation.rb +93 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/prepend.rb +23 -0
- data/lib/new_relic/agent/instrumentation/aws_sdk_lambda.rb +23 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs.rb +0 -2
- data/lib/new_relic/agent/instrumentation/bunny.rb +3 -4
- data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +0 -2
- data/lib/new_relic/agent/instrumentation/curb.rb +3 -4
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +0 -4
- data/lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb +3 -4
- data/lib/new_relic/agent/instrumentation/dynamodb.rb +0 -2
- data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +1 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch.rb +0 -2
- data/lib/new_relic/agent/instrumentation/ethon.rb +0 -4
- data/lib/new_relic/agent/instrumentation/fiber.rb +0 -2
- data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +0 -3
- data/lib/new_relic/agent/instrumentation/grape.rb +1 -3
- data/lib/new_relic/agent/instrumentation/httpclient.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httpx.rb +0 -4
- data/lib/new_relic/agent/instrumentation/logger.rb +1 -3
- data/lib/new_relic/agent/instrumentation/logstasher.rb +0 -2
- data/lib/new_relic/agent/instrumentation/memcache.rb +0 -1
- data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +3 -3
- data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +0 -2
- data/lib/new_relic/agent/instrumentation/opensearch.rb +0 -2
- data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
- data/lib/new_relic/agent/instrumentation/rake.rb +0 -1
- data/lib/new_relic/agent/instrumentation/rdkafka/chain.rb +2 -1
- data/lib/new_relic/agent/instrumentation/rdkafka/prepend.rb +2 -1
- data/lib/new_relic/agent/instrumentation/rdkafka.rb +0 -2
- data/lib/new_relic/agent/instrumentation/redis.rb +0 -1
- data/lib/new_relic/agent/instrumentation/resque.rb +7 -5
- data/lib/new_relic/agent/instrumentation/roda.rb +4 -4
- data/lib/new_relic/agent/instrumentation/ruby_kafka/prepend.rb +14 -4
- data/lib/new_relic/agent/instrumentation/ruby_kafka.rb +0 -2
- data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delay_extensions.rb +24 -0
- data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +9 -1
- data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -6
- data/lib/new_relic/agent/instrumentation/thread.rb +0 -2
- data/lib/new_relic/agent/instrumentation/tilt.rb +0 -4
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
- data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +11 -8
- data/lib/new_relic/agent/instrumentation/view_component.rb +0 -2
- data/lib/new_relic/agent/local_log_decorator.rb +12 -2
- data/lib/new_relic/agent/log_event_aggregator.rb +28 -2
- data/lib/new_relic/agent/new_relic_service.rb +8 -2
- data/lib/new_relic/agent/span_event_primitive.rb +4 -2
- data/lib/new_relic/agent/threading/backtrace_node.rb +10 -1
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +3 -0
- data/lib/new_relic/agent/transaction/tracing.rb +4 -5
- data/lib/new_relic/agent/transaction.rb +2 -1
- data/lib/new_relic/agent/utilization_data.rb +15 -5
- data/lib/new_relic/agent.rb +2 -2
- data/lib/new_relic/control/frameworks/rails4.rb +1 -5
- data/lib/new_relic/control/instance_methods.rb +5 -0
- data/lib/new_relic/dependency_detection.rb +11 -13
- data/lib/new_relic/environment_report.rb +1 -5
- data/lib/new_relic/helper.rb +15 -0
- data/lib/new_relic/language_support.rb +1 -5
- data/lib/new_relic/version.rb +1 -1
- data/lib/sequel/extensions/new_relic_instrumentation.rb +1 -1
- data/lib/tasks/helpers/newrelicyml.rb +4 -2
- data/newrelic.yml +174 -66
- data/test/agent_helper.rb +8 -1
- metadata +17 -19
- data/lib/tasks/instrumentation_generator/README.md +0 -63
- data/lib/tasks/instrumentation_generator/TODO.md +0 -33
- data/lib/tasks/instrumentation_generator/instrumentation.thor +0 -130
- data/lib/tasks/instrumentation_generator/templates/Envfile.tt +0 -9
- data/lib/tasks/instrumentation_generator/templates/chain.tt +0 -21
- data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -7
- data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +0 -29
- data/lib/tasks/instrumentation_generator/templates/instrumentation.tt +0 -13
- data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +0 -3
- data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +0 -19
- data/lib/tasks/instrumentation_generator/templates/prepend.tt +0 -13
- data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +0 -3
- data/lib/tasks/instrumentation_generator/templates/test.tt +0 -15
@@ -5,6 +5,7 @@
|
|
5
5
|
require_relative 'sidekiq/client'
|
6
6
|
require_relative 'sidekiq/server'
|
7
7
|
require_relative 'sidekiq/extensions/delayed_class'
|
8
|
+
require_relative 'sidekiq/extensions/delay_extensions'
|
8
9
|
|
9
10
|
DependencyDetection.defer do
|
10
11
|
@name = :sidekiq
|
@@ -29,7 +30,14 @@ DependencyDetection.defer do
|
|
29
30
|
chain.add(NewRelic::Agent::Instrumentation::Sidekiq::Client)
|
30
31
|
end
|
31
32
|
config.server_middleware do |chain|
|
32
|
-
|
33
|
+
# We started prepending v chaining NR middleware in 9.18.0 in response to:
|
34
|
+
# https://github.com/newrelic/newrelic-ruby-agent/issues/3037
|
35
|
+
# This way, exceptions resolved by Sidekiq's own middleware are not reported in the agent
|
36
|
+
if chain.respond_to?(:prepend)
|
37
|
+
chain.prepend(NewRelic::Agent::Instrumentation::Sidekiq::Server)
|
38
|
+
else
|
39
|
+
chain.add(NewRelic::Agent::Instrumentation::Sidekiq::Server)
|
40
|
+
end
|
33
41
|
end
|
34
42
|
|
35
43
|
if config.respond_to?(:error_handlers)
|
@@ -16,10 +16,6 @@ DependencyDetection.defer do
|
|
16
16
|
depends_on { Sinatra::Base.private_method_defined?(:process_route) }
|
17
17
|
depends_on { Sinatra::Base.private_method_defined?(:route_eval) }
|
18
18
|
|
19
|
-
executes do
|
20
|
-
NewRelic::Agent.logger.info('Installing Sinatra instrumentation')
|
21
|
-
end
|
22
|
-
|
23
19
|
executes do
|
24
20
|
if use_prepend?
|
25
21
|
prepend_instrument Sinatra::Base, NewRelic::Agent::Instrumentation::Sinatra::Prepend
|
@@ -32,14 +28,15 @@ DependencyDetection.defer do
|
|
32
28
|
end
|
33
29
|
|
34
30
|
executes do
|
31
|
+
supportability_name = NewRelic::Agent::Instrumentation::Sinatra::Tracer::INSTRUMENTATION_NAME
|
35
32
|
# These requires are inside an executes block because they require rack, and
|
36
33
|
# we can't be sure that rack is available when this file is first required.
|
37
34
|
require 'new_relic/rack/agent_hooks'
|
38
35
|
require 'new_relic/rack/browser_monitoring'
|
39
36
|
if use_prepend?
|
40
|
-
prepend_instrument Sinatra::Base.singleton_class, NewRelic::Agent::Instrumentation::Sinatra::Build::Prepend
|
37
|
+
prepend_instrument Sinatra::Base.singleton_class, NewRelic::Agent::Instrumentation::Sinatra::Build::Prepend, supportability_name
|
41
38
|
else
|
42
|
-
chain_instrument NewRelic::Agent::Instrumentation::Sinatra::Build::Chain
|
39
|
+
chain_instrument NewRelic::Agent::Instrumentation::Sinatra::Build::Chain, supportability_name
|
43
40
|
end
|
44
41
|
end
|
45
42
|
end
|
@@ -11,10 +11,6 @@ DependencyDetection.defer do
|
|
11
11
|
|
12
12
|
depends_on { defined?(Tilt) }
|
13
13
|
|
14
|
-
executes do
|
15
|
-
NewRelic::Agent.logger.info('Installing Tilt instrumentation')
|
16
|
-
end
|
17
|
-
|
18
14
|
executes do
|
19
15
|
if use_prepend?
|
20
16
|
prepend_instrument Tilt::Template, NewRelic::Agent::Instrumentation::Tilt::Prepend
|
@@ -10,12 +10,7 @@ module NewRelic::Agent::Instrumentation
|
|
10
10
|
NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
|
11
11
|
|
12
12
|
begin
|
13
|
-
segment = NewRelic::Agent::Tracer.start_segment(
|
14
|
-
name: metric_name(
|
15
|
-
self.class.respond_to?(:identifier) ? self.class.identifier : nil,
|
16
|
-
self.class.name
|
17
|
-
)
|
18
|
-
)
|
13
|
+
segment = NewRelic::Agent::Tracer.start_segment(name: metric_name)
|
19
14
|
yield
|
20
15
|
rescue => e
|
21
16
|
NewRelic::Agent.notice_error(e)
|
@@ -25,8 +20,16 @@ module NewRelic::Agent::Instrumentation
|
|
25
20
|
end
|
26
21
|
end
|
27
22
|
|
28
|
-
def metric_name
|
29
|
-
|
23
|
+
def metric_name
|
24
|
+
# ViewComponent determines a component's identifier differently depending on the version
|
25
|
+
# https://github.com/ViewComponent/view_component/pull/2153
|
26
|
+
component_identifier = defined?(self.class.source_location) ? self.class.source_location : self.class.identifier
|
27
|
+
|
28
|
+
"View/#{metric_path(component_identifier)}/#{self.class.name}"
|
29
|
+
rescue => e
|
30
|
+
NewRelic::Agent.logger.error('Error identifying View Component metric name', e)
|
31
|
+
|
32
|
+
'View/component'
|
30
33
|
end
|
31
34
|
|
32
35
|
def metric_path(identifier)
|
@@ -9,7 +9,7 @@ module NewRelic
|
|
9
9
|
extend self
|
10
10
|
|
11
11
|
def decorate(message)
|
12
|
-
return message
|
12
|
+
return message if !decorating_enabled? || message.nil?
|
13
13
|
|
14
14
|
metadata = NewRelic::Agent.linking_metadata
|
15
15
|
|
@@ -37,7 +37,17 @@ module NewRelic
|
|
37
37
|
def escape_entity_name(entity_name)
|
38
38
|
return unless entity_name
|
39
39
|
|
40
|
-
|
40
|
+
# TODO: OLD RUBIES 3.3
|
41
|
+
# URI version 1.0 marked URI::RFC3986_PARSER.escape as obsolete,
|
42
|
+
# which URI::DEFAULT_PARSER is an alias for.
|
43
|
+
# URI version 1.0+ will ship with Ruby 3.4
|
44
|
+
# Once we drop support for Rubies below 3.4, we can use the
|
45
|
+
# URI::RFC2396 parser exclusively.
|
46
|
+
if Gem::Version.new(URI::VERSION) >= Gem::Version.new('1.0')
|
47
|
+
URI::RFC2396_PARSER.escape(entity_name)
|
48
|
+
else
|
49
|
+
URI::DEFAULT_PARSER.escape(entity_name)
|
50
|
+
end
|
41
51
|
end
|
42
52
|
end
|
43
53
|
end
|
@@ -25,6 +25,7 @@ module NewRelic
|
|
25
25
|
METRICS_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Metrics/Ruby/%s'.freeze
|
26
26
|
FORWARDING_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Forwarding/Ruby/%s'.freeze
|
27
27
|
DECORATING_SUPPORTABILITY_FORMAT = 'Supportability/Logging/LocalDecorating/Ruby/%s'.freeze
|
28
|
+
LABELS_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Labels/Ruby/%s'.freeze
|
28
29
|
MAX_BYTES = 32768 # 32 * 1024 bytes (32 kibibytes)
|
29
30
|
|
30
31
|
named :LogEventAggregator
|
@@ -38,6 +39,7 @@ module NewRelic
|
|
38
39
|
METRICS_ENABLED_KEY = :'application_logging.metrics.enabled'
|
39
40
|
FORWARDING_ENABLED_KEY = :'application_logging.forwarding.enabled'
|
40
41
|
DECORATING_ENABLED_KEY = :'application_logging.local_decorating.enabled'
|
42
|
+
LABELS_ENABLED_KEY = :'application_logging.forwarding.labels.enabled'
|
41
43
|
LOG_LEVEL_KEY = :'application_logging.forwarding.log_level'
|
42
44
|
CUSTOM_ATTRIBUTES_KEY = :'application_logging.forwarding.custom_attributes'
|
43
45
|
|
@@ -51,6 +53,7 @@ module NewRelic
|
|
51
53
|
@high_security = NewRelic::Agent.config[:high_security]
|
52
54
|
@instrumentation_logger_enabled = NewRelic::Agent::Instrumentation::Logger.enabled?
|
53
55
|
@attributes = NewRelic::Agent::LogEventAttributes.new
|
56
|
+
|
54
57
|
register_for_done_configuring(events)
|
55
58
|
end
|
56
59
|
|
@@ -186,6 +189,10 @@ module NewRelic
|
|
186
189
|
attributes.add_custom_attributes(custom_attributes)
|
187
190
|
end
|
188
191
|
|
192
|
+
def labels
|
193
|
+
@labels ||= create_labels
|
194
|
+
end
|
195
|
+
|
189
196
|
# Because our transmission format (MELT) is different than historical
|
190
197
|
# agent payloads, extract the munging here to keep the service focused
|
191
198
|
# on the general harvest + transmit instead of the format.
|
@@ -201,8 +208,9 @@ module NewRelic
|
|
201
208
|
# To save on unnecessary data transmission, trim the entity.type
|
202
209
|
# sent by classic logs-in-context
|
203
210
|
common_attributes.delete(ENTITY_TYPE_KEY)
|
204
|
-
|
205
|
-
common_attributes.merge!(
|
211
|
+
aggregator = NewRelic::Agent.agent.log_event_aggregator
|
212
|
+
common_attributes.merge!(aggregator.attributes.custom_attributes)
|
213
|
+
common_attributes.merge!(aggregator.labels)
|
206
214
|
|
207
215
|
_, items = data
|
208
216
|
payload = [{
|
@@ -247,6 +255,7 @@ module NewRelic
|
|
247
255
|
record_configuration_metric(METRICS_SUPPORTABILITY_FORMAT, METRICS_ENABLED_KEY)
|
248
256
|
record_configuration_metric(FORWARDING_SUPPORTABILITY_FORMAT, FORWARDING_ENABLED_KEY)
|
249
257
|
record_configuration_metric(DECORATING_SUPPORTABILITY_FORMAT, DECORATING_ENABLED_KEY)
|
258
|
+
record_configuration_metric(LABELS_SUPPORTABILITY_FORMAT, LABELS_ENABLED_KEY)
|
250
259
|
|
251
260
|
add_custom_attributes(NewRelic::Agent.config[CUSTOM_ATTRIBUTES_KEY])
|
252
261
|
end
|
@@ -327,6 +336,23 @@ module NewRelic
|
|
327
336
|
|
328
337
|
Logger::Severity.const_get(severity_constant) < Logger::Severity.const_get(configured_log_level_constant)
|
329
338
|
end
|
339
|
+
|
340
|
+
def create_labels
|
341
|
+
return NewRelic::EMPTY_HASH unless NewRelic::Agent.config[LABELS_ENABLED_KEY]
|
342
|
+
|
343
|
+
downcased_exclusions = NewRelic::Agent.config[:'application_logging.forwarding.labels.exclude'].map(&:downcase)
|
344
|
+
log_labels = {}
|
345
|
+
|
346
|
+
NewRelic::Agent.config.parsed_labels.each do |parsed_label|
|
347
|
+
next if downcased_exclusions.include?(parsed_label['label_type'].downcase)
|
348
|
+
|
349
|
+
# labels are referred to as tags in the UI, so prefix the
|
350
|
+
# label-related attributes with 'tags.*'
|
351
|
+
log_labels["tags.#{parsed_label['label_type']}"] = parsed_label['label_value']
|
352
|
+
end
|
353
|
+
|
354
|
+
log_labels
|
355
|
+
end
|
330
356
|
end
|
331
357
|
end
|
332
358
|
end
|
@@ -455,6 +455,8 @@ module NewRelic
|
|
455
455
|
end
|
456
456
|
|
457
457
|
def handle_error_response(response, endpoint)
|
458
|
+
NewRelic::Agent.agent&.health_check&.update_status(NewRelic::Agent::HealthCheck::HTTP_ERROR, [response.code, endpoint])
|
459
|
+
|
458
460
|
case response
|
459
461
|
when Net::HTTPRequestTimeOut,
|
460
462
|
Net::HTTPTooManyRequests,
|
@@ -637,9 +639,13 @@ module NewRelic
|
|
637
639
|
def send_request(opts)
|
638
640
|
request = prep_request(opts)
|
639
641
|
response = relay_request(request, opts)
|
640
|
-
return response if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPAccepted)
|
641
642
|
|
642
|
-
|
643
|
+
if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPAccepted)
|
644
|
+
NewRelic::Agent.agent&.health_check&.update_status(NewRelic::Agent::HealthCheck::HEALTHY)
|
645
|
+
response
|
646
|
+
else
|
647
|
+
handle_error_response(response, opts[:endpoint])
|
648
|
+
end
|
643
649
|
end
|
644
650
|
|
645
651
|
def log_response(response)
|
@@ -52,6 +52,8 @@ module NewRelic
|
|
52
52
|
DATASTORE_CATEGORY = 'datastore'
|
53
53
|
CLIENT = 'client'
|
54
54
|
|
55
|
+
DB_STATEMENT_MAX_BYTES = 4096
|
56
|
+
|
55
57
|
# Builds a Hash of error attributes as well as the Span ID when
|
56
58
|
# an error is present. Otherwise, returns nil when no error present.
|
57
59
|
def error_attributes(segment)
|
@@ -114,9 +116,9 @@ module NewRelic
|
|
114
116
|
agent_attributes[DB_SYSTEM_KEY] = segment.product if allowed?(DB_SYSTEM_KEY)
|
115
117
|
|
116
118
|
if segment.sql_statement && allowed?(DB_STATEMENT_KEY)
|
117
|
-
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.sql_statement.safe_sql,
|
119
|
+
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.sql_statement.safe_sql, DB_STATEMENT_MAX_BYTES)
|
118
120
|
elsif segment.nosql_statement && allowed?(DB_STATEMENT_KEY)
|
119
|
-
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.nosql_statement,
|
121
|
+
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.nosql_statement, DB_STATEMENT_MAX_BYTES)
|
120
122
|
end
|
121
123
|
|
122
124
|
[intrinsics, custom_attributes(segment), agent_attributes.merge(agent_attributes(segment))]
|
@@ -125,7 +125,16 @@ module NewRelic
|
|
125
125
|
|
126
126
|
# Returns [filename, method, line number]
|
127
127
|
def parse_backtrace_frame(frame)
|
128
|
-
|
128
|
+
# TODO: OLD RUBIES - Ruby 3.3
|
129
|
+
# The (?:`|') non-capturing group can be removed when the agent
|
130
|
+
# drops support for Ruby 3.3
|
131
|
+
# This group is used to capture the pre-Ruby 3.4.0 backtrace syntax.
|
132
|
+
# Example frame:
|
133
|
+
# Ruby 3.3.0 and below
|
134
|
+
# "irb.rb:69:in `catch'"
|
135
|
+
# Ruby 3.4.0+
|
136
|
+
# "irb.rb:69:in 'Kernel#catch'"
|
137
|
+
frame =~ /([^:]*)(\:(\d+))?\:in (?:`|')(.*)'/
|
129
138
|
[$1, $4, $3] # sic
|
130
139
|
end
|
131
140
|
end
|
@@ -15,6 +15,7 @@ module NewRelic
|
|
15
15
|
PRODUCE = 'Produce'.freeze
|
16
16
|
QUEUE = 'Queue'.freeze
|
17
17
|
PURGE = 'Purge'.freeze
|
18
|
+
STREAM = 'Stream'.freeze
|
18
19
|
TEMP = 'Temp'.freeze
|
19
20
|
TOPIC = 'Topic'.freeze
|
20
21
|
UNKNOWN = 'Unknown'.freeze
|
@@ -22,6 +23,7 @@ module NewRelic
|
|
22
23
|
DESTINATION_TYPES = [
|
23
24
|
:exchange,
|
24
25
|
:queue,
|
26
|
+
:stream,
|
25
27
|
:topic,
|
26
28
|
:temporary_queue,
|
27
29
|
:temporary_topic,
|
@@ -37,6 +39,7 @@ module NewRelic
|
|
37
39
|
TYPES = {
|
38
40
|
exchange: EXCHANGE,
|
39
41
|
temporary_queue: QUEUE,
|
42
|
+
stream: STREAM,
|
40
43
|
queue: QUEUE,
|
41
44
|
temporary_topic: TOPIC,
|
42
45
|
topic: TOPIC,
|
@@ -25,7 +25,7 @@ module NewRelic
|
|
25
25
|
segment.parent = parent || thread_starting_span || current_segment
|
26
26
|
set_current_segment(segment)
|
27
27
|
if @segments.length < segment_limit
|
28
|
-
@segments << segment
|
28
|
+
@segment_lock.synchronize { @segments << segment }
|
29
29
|
else
|
30
30
|
segment.record_on_finish = true
|
31
31
|
::NewRelic::Agent.logger.debug("Segment limit of #{segment_limit} reached, ceasing collection.")
|
@@ -42,8 +42,7 @@ module NewRelic
|
|
42
42
|
def thread_starting_span
|
43
43
|
# if the previous current segment was in another thread, use the thread local parent
|
44
44
|
if ThreadLocalStorage[:newrelic_thread_span_parent] &&
|
45
|
-
current_segment
|
46
|
-
current_segment.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
|
45
|
+
current_segment&.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
|
47
46
|
|
48
47
|
ThreadLocalStorage[:newrelic_thread_span_parent]
|
49
48
|
end
|
@@ -51,7 +50,7 @@ module NewRelic
|
|
51
50
|
|
52
51
|
def segment_complete(segment)
|
53
52
|
# if parent was in another thread, remove the current_segment entry for this thread
|
54
|
-
if segment.parent
|
53
|
+
if segment.parent&.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
|
55
54
|
remove_current_segment_by_thread_id(NewRelic::Agent::Tracer.current_segment_key)
|
56
55
|
else
|
57
56
|
set_current_segment(segment.parent)
|
@@ -65,7 +64,7 @@ module NewRelic
|
|
65
64
|
private
|
66
65
|
|
67
66
|
def finalize_segments
|
68
|
-
segments.each { |s| s
|
67
|
+
@segment_lock.synchronize { segments.each { |s| s&.finalize } }
|
69
68
|
end
|
70
69
|
|
71
70
|
WEB_TRANSACTION_TOTAL_TIME = 'WebTransactionTotalTime'.freeze
|
@@ -215,6 +215,7 @@ module NewRelic
|
|
215
215
|
@nesting_max_depth = 0
|
216
216
|
@current_segment_by_thread = {}
|
217
217
|
@current_segment_lock = Mutex.new
|
218
|
+
@segment_lock = Mutex.new
|
218
219
|
@segments = []
|
219
220
|
|
220
221
|
self.default_name = options[:transaction_name]
|
@@ -437,7 +438,7 @@ module NewRelic
|
|
437
438
|
end
|
438
439
|
|
439
440
|
def initial_segment
|
440
|
-
segments
|
441
|
+
segments&.first
|
441
442
|
end
|
442
443
|
|
443
444
|
def finished?
|
@@ -85,17 +85,27 @@ module NewRelic
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def append_vendor_info(collector_hash)
|
88
|
+
threads = []
|
89
|
+
complete = false
|
90
|
+
|
88
91
|
VENDORS.each_pair do |klass, config_option|
|
89
92
|
next unless Agent.config[config_option]
|
90
93
|
|
91
|
-
|
94
|
+
threads << Thread.new do
|
95
|
+
vendor = klass.new
|
96
|
+
|
97
|
+
if vendor.detect
|
98
|
+
collector_hash[:vendors] ||= {}
|
99
|
+
collector_hash[:vendors][vendor.vendor_name.to_sym] = vendor.metadata
|
92
100
|
|
93
|
-
|
94
|
-
|
95
|
-
collector_hash[:vendors][vendor.vendor_name.to_sym] = vendor.metadata
|
96
|
-
break
|
101
|
+
complete = true
|
102
|
+
end
|
97
103
|
end
|
98
104
|
end
|
105
|
+
|
106
|
+
while complete == false && threads.any?(&:alive?)
|
107
|
+
sleep 0.01
|
108
|
+
end
|
99
109
|
end
|
100
110
|
|
101
111
|
def append_docker_info(collector_hash)
|
data/lib/new_relic/agent.rb
CHANGED
@@ -132,8 +132,8 @@ module NewRelic
|
|
132
132
|
def agent # :nodoc:
|
133
133
|
return @agent if @agent
|
134
134
|
|
135
|
-
NewRelic::Agent.logger.
|
136
|
-
NewRelic::Agent.logger.
|
135
|
+
NewRelic::Agent.logger.debug("Agent unavailable as it hasn't been started.")
|
136
|
+
NewRelic::Agent.logger.debug(caller.join("\n"))
|
137
137
|
nil
|
138
138
|
end
|
139
139
|
|
@@ -9,11 +9,7 @@ module NewRelic
|
|
9
9
|
module Frameworks
|
10
10
|
class Rails4 < NewRelic::Control::Frameworks::Rails3
|
11
11
|
def rails_gem_list
|
12
|
-
|
13
|
-
Bundler.rubygems.installed_specs.map { |gem| "#{gem.name} (#{gem.version})" }
|
14
|
-
else
|
15
|
-
Bundler.rubygems.all_specs.map { |gem| "#{gem.name} (#{gem.version})" }
|
16
|
-
end
|
12
|
+
NewRelic::Helper.rubygems_specs.map { |gem| "#{gem.name} (#{gem.version})" }
|
17
13
|
end
|
18
14
|
|
19
15
|
def append_plugin_list
|
@@ -74,6 +74,7 @@ module NewRelic
|
|
74
74
|
NewRelic::Agent.agent = NewRelic::Agent::Agent.instance
|
75
75
|
init_instrumentation
|
76
76
|
init_security_agent
|
77
|
+
report_agent_version_metric
|
77
78
|
end
|
78
79
|
|
79
80
|
def determine_env(options)
|
@@ -171,6 +172,10 @@ module NewRelic
|
|
171
172
|
def stdout
|
172
173
|
STDOUT
|
173
174
|
end
|
175
|
+
|
176
|
+
def report_agent_version_metric
|
177
|
+
NewRelic::Agent.record_metric_once("Supportability/AgentVersion/newrelic_rpm/#{NewRelic::VERSION::STRING}")
|
178
|
+
end
|
174
179
|
end
|
175
180
|
include InstanceMethods
|
176
181
|
end
|
@@ -25,11 +25,9 @@ module DependencyDetection
|
|
25
25
|
|
26
26
|
def detect!
|
27
27
|
@items.each do |item|
|
28
|
-
if item.
|
29
|
-
|
30
|
-
|
31
|
-
item.configure_as_unsatisfied unless item.disabled_configured?
|
32
|
-
end
|
28
|
+
next if item.executed || item.disabled_configured?
|
29
|
+
|
30
|
+
item.dependencies_satisfied? ? item.execute : item.configure_as_unsatisfied
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -65,6 +63,13 @@ module DependencyDetection
|
|
65
63
|
end
|
66
64
|
|
67
65
|
def configure_as_unsatisfied
|
66
|
+
# TODO: currently using :unsatisfied for Padrino will clobber the value
|
67
|
+
# already set for Sinatra, so skip Padrino and circle back with a
|
68
|
+
# new Padrino specific solution in the future.
|
69
|
+
#
|
70
|
+
# https://github.com/newrelic/newrelic-ruby-agent/issues/2912
|
71
|
+
return if name == :padrino
|
72
|
+
|
68
73
|
NewRelic::Agent.config.instance_variable_get(:@cache)[config_key] = :unsatisfied
|
69
74
|
end
|
70
75
|
|
@@ -139,8 +144,6 @@ module DependencyDetection
|
|
139
144
|
!(disabled_configured? || deprecated_disabled_configured?)
|
140
145
|
end
|
141
146
|
|
142
|
-
# TODO: MAJOR VERSION
|
143
|
-
# will only return true if a disabled key is found and is truthy
|
144
147
|
def deprecated_disabled_configured?
|
145
148
|
return false if self.name.nil?
|
146
149
|
|
@@ -148,12 +151,7 @@ module DependencyDetection
|
|
148
151
|
return false unless ::NewRelic::Agent.config[key] == true
|
149
152
|
|
150
153
|
::NewRelic::Agent.logger.debug("Not installing #{self.name} instrumentation because of configuration #{key}")
|
151
|
-
|
152
|
-
"[DEPRECATED] configuration #{key} for #{self.name} will be removed in the next major release. " \
|
153
|
-
"Use `#{config_key}` with one of `#{VALID_CONFIG_VALUES.map(&:to_s).inspect}`"
|
154
|
-
)
|
155
|
-
|
156
|
-
return true
|
154
|
+
true
|
157
155
|
end
|
158
156
|
|
159
157
|
def config_key
|
@@ -44,11 +44,7 @@ module NewRelic
|
|
44
44
|
####################################
|
45
45
|
report_on('Gems') do
|
46
46
|
begin
|
47
|
-
|
48
|
-
Bundler.rubygems.installed_specs.map { |gem| "#{gem.name}(#{gem.version})" }
|
49
|
-
else
|
50
|
-
Bundler.rubygems.all_specs.map { |gem| "#{gem.name}(#{gem.version})" }
|
51
|
-
end
|
47
|
+
NewRelic::Helper.rubygems_specs.map { |gem| "#{gem.name}(#{gem.version})" }
|
52
48
|
rescue
|
53
49
|
# There are certain rubygem, bundler, rails combinations (e.g. gem
|
54
50
|
# 1.6.2, rails 2.3, bundler 1.2.3) where the code above throws an error
|
data/lib/new_relic/helper.rb
CHANGED
@@ -82,5 +82,20 @@ module NewRelic
|
|
82
82
|
File.exist?(executable_path) && File.file?(executable_path) && File.executable?(executable_path)
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
# Bundler version 2.5.12 deprecated all_specs and added installed_specs.
|
87
|
+
# To support newer Bundler versions, try to use installed_specs first,
|
88
|
+
# then fall back to all_specs.
|
89
|
+
# All callers expect this to be an array, so return an array if Bundler isn't defined
|
90
|
+
# @api private
|
91
|
+
def rubygems_specs
|
92
|
+
return [] unless defined?(Bundler)
|
93
|
+
|
94
|
+
if Bundler.rubygems.respond_to?(:installed_specs)
|
95
|
+
Bundler.rubygems.installed_specs
|
96
|
+
else
|
97
|
+
Bundler.rubygems.all_specs
|
98
|
+
end
|
99
|
+
end
|
85
100
|
end
|
86
101
|
end
|
@@ -90,11 +90,7 @@ module NewRelic
|
|
90
90
|
def bundled_gem?(gem_name)
|
91
91
|
return false unless defined?(Bundler)
|
92
92
|
|
93
|
-
|
94
|
-
Bundler.rubygems.installed_specs.map(&:name).include?(gem_name)
|
95
|
-
else
|
96
|
-
Bundler.rubygems.all_specs.map(&:name).include?(gem_name)
|
97
|
-
end
|
93
|
+
NewRelic::Helper.rubygems_specs.map(&:name).include?(gem_name)
|
98
94
|
rescue => e
|
99
95
|
::NewRelic::Agent.logger.info("Could not determine if third party #{gem_name} gem is installed", e)
|
100
96
|
false
|
data/lib/new_relic/version.rb
CHANGED
@@ -79,7 +79,7 @@ module Sequel
|
|
79
79
|
|
80
80
|
THREAD_SAFE_CONNECTION_POOL_CLASSES = [
|
81
81
|
(defined?(::Sequel::ThreadedConnectionPool) && ::Sequel::ThreadedConnectionPool),
|
82
|
-
(defined?(::Sequel::TimedQueueConnectionPool) && RUBY_VERSION >= '3.
|
82
|
+
(defined?(::Sequel::TimedQueueConnectionPool) && RUBY_VERSION >= '3.2' && ::Sequel::TimedQueueConnectionPool)
|
83
83
|
].compact.freeze
|
84
84
|
|
85
85
|
def explainer_for(sql)
|
@@ -141,6 +141,8 @@ module NewRelicYML
|
|
141
141
|
description.gsub!(/<InlinePopover type="(.*)" \/>/, '\1')
|
142
142
|
# remove hyperlinks
|
143
143
|
description.gsub!(/\[([^\]]+)\]\([^\)]+\)/, '\1')
|
144
|
+
# delete lines with code fences including the language
|
145
|
+
description.gsub!(/```[a-zA-Z0-9_]*\n(.*?)```/m, '\1')
|
144
146
|
# remove single pairs of backticks
|
145
147
|
description.gsub!(/`([^`]+)`/, '\1')
|
146
148
|
# removed href links
|
@@ -153,8 +155,8 @@ module NewRelicYML
|
|
153
155
|
# remove leading and trailing whitespace
|
154
156
|
description.strip!
|
155
157
|
# wrap text after 80 characters, assuming we're at one tabstop's (two
|
156
|
-
# spaces') level of indentation already
|
157
|
-
description.gsub!(/(.{1,78})(\s
|
158
|
+
# spaces') level of indentation already, keep leading whitespace
|
159
|
+
description.gsub!(/(.{1,78})(\s|\Z)/, "\\1\n")
|
158
160
|
# add hashtags to lines
|
159
161
|
description = description.split("\n").map { |line| " # #{line}" }.join("\n")
|
160
162
|
|