newrelic_rpm 9.9.0 → 9.21.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 +463 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +16 -17
- data/Rakefile +1 -1
- data/lib/boot/strap.rb +102 -0
- data/lib/new_relic/agent/agent.rb +6 -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/agent_logger.rb +1 -0
- data/lib/new_relic/agent/aws.rb +68 -0
- data/lib/new_relic/agent/configuration/default_source.rb +603 -105
- data/lib/new_relic/agent/configuration/environment_source.rb +5 -1
- data/lib/new_relic/agent/configuration/manager.rb +28 -2
- data/lib/new_relic/agent/configuration/yaml_source.rb +7 -2
- data/lib/new_relic/agent/database/obfuscation_helpers.rb +11 -11
- data/lib/new_relic/agent/database/obfuscator.rb +1 -0
- data/lib/new_relic/agent/database.rb +41 -1
- data/lib/new_relic/agent/database_adapter.rb +1 -1
- data/lib/new_relic/agent/datastores/redis.rb +1 -1
- data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -1
- data/lib/new_relic/agent/distributed_tracing.rb +4 -2
- data/lib/new_relic/agent/error_collector.rb +37 -10
- data/lib/new_relic/agent/external.rb +2 -0
- 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/action_dispatch.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_mailbox.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_mailer.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +6 -2
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +0 -13
- data/lib/new_relic/agent/instrumentation/active_record.rb +7 -12
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +7 -3
- data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +11 -9
- data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +2 -2
- 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 +2 -3
- 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/chain.rb +37 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs/instrumentation.rb +67 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs/prepend.rb +21 -0
- data/lib/new_relic/agent/instrumentation/aws_sqs.rb +23 -0
- data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +14 -0
- data/lib/new_relic/agent/instrumentation/bunny.rb +3 -4
- data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +1 -3
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/curb.rb +4 -5
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +0 -23
- 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 +23 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +1 -2
- data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +53 -7
- data/lib/new_relic/agent/instrumentation/elasticsearch.rb +1 -3
- data/lib/new_relic/agent/instrumentation/ethon.rb +1 -5
- data/lib/new_relic/agent/instrumentation/excon.rb +1 -17
- data/lib/new_relic/agent/instrumentation/fiber/chain.rb +1 -1
- data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +1 -1
- 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 -1
- data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -5
- data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/httpx.rb +1 -5
- data/lib/new_relic/agent/instrumentation/logger.rb +1 -3
- data/lib/new_relic/agent/instrumentation/logstasher/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/logstasher/instrumentation.rb +24 -0
- data/lib/new_relic/agent/instrumentation/logstasher/prepend.rb +13 -0
- data/lib/new_relic/agent/instrumentation/logstasher.rb +25 -0
- data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache/helper.rb +2 -2
- data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache.rb +0 -1
- data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +3 -3
- data/lib/new_relic/agent/instrumentation/net_http.rb +2 -1
- data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +0 -2
- data/lib/new_relic/agent/instrumentation/opensearch/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/opensearch/instrumentation.rb +66 -0
- data/lib/{tasks/instrumentation_generator/templates/instrumentation.tt → new_relic/agent/instrumentation/opensearch/prepend.rb} +4 -4
- data/lib/new_relic/agent/instrumentation/opensearch.rb +23 -0
- data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
- data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +3 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +9 -5
- data/lib/new_relic/agent/instrumentation/rake.rb +1 -2
- data/lib/new_relic/agent/instrumentation/rdkafka/chain.rb +72 -0
- data/lib/new_relic/agent/instrumentation/rdkafka/instrumentation.rb +70 -0
- data/lib/new_relic/agent/instrumentation/rdkafka/prepend.rb +67 -0
- data/lib/new_relic/agent/instrumentation/rdkafka.rb +25 -0
- data/lib/new_relic/agent/instrumentation/redis/cluster_middleware.rb +26 -0
- data/lib/new_relic/agent/instrumentation/redis/constants.rb +2 -2
- data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +14 -11
- data/lib/new_relic/agent/instrumentation/redis/middleware.rb +3 -0
- data/lib/new_relic/agent/instrumentation/redis.rb +11 -5
- data/lib/new_relic/agent/instrumentation/resque.rb +8 -6
- data/lib/new_relic/agent/instrumentation/roda.rb +5 -5
- data/lib/new_relic/agent/instrumentation/ruby_kafka/chain.rb +55 -0
- data/lib/new_relic/agent/instrumentation/ruby_kafka/instrumentation.rb +67 -0
- data/lib/new_relic/agent/instrumentation/ruby_kafka/prepend.rb +60 -0
- data/lib/new_relic/agent/instrumentation/ruby_kafka.rb +25 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai.rb +2 -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 +2 -2
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +9 -15
- data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -19
- data/lib/new_relic/agent/instrumentation/stripe.rb +1 -1
- data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +22 -1
- 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/instrumentation.rb +2 -2
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
- data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +11 -5
- data/lib/new_relic/agent/instrumentation/view_component.rb +0 -2
- data/lib/new_relic/agent/javascript_instrumentor.rb +2 -3
- data/lib/new_relic/agent/llm/chat_completion_summary.rb +1 -1
- data/lib/new_relic/agent/llm/embedding.rb +1 -1
- data/lib/new_relic/agent/local_log_decorator.rb +20 -3
- data/lib/new_relic/agent/log_event_aggregator.rb +119 -28
- data/lib/new_relic/agent/logging.rb +1 -1
- data/lib/new_relic/agent/messaging.rb +16 -5
- data/lib/new_relic/agent/method_tracer.rb +3 -0
- data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
- data/lib/new_relic/agent/monitors/synthetics_monitor.rb +1 -1
- data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +2 -2
- data/lib/new_relic/agent/new_relic_service.rb +8 -2
- data/lib/new_relic/agent/opentelemetry/context/propagation/trace_propagator.rb +66 -0
- data/lib/new_relic/agent/opentelemetry/context/propagation.rb +15 -0
- data/lib/{tasks/instrumentation_generator/templates/Envfile.tt → new_relic/agent/opentelemetry/context.rb} +9 -5
- data/lib/new_relic/agent/opentelemetry/trace/span.rb +31 -0
- data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +129 -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/transaction_patch.rb +69 -0
- data/lib/new_relic/agent/opentelemetry_bridge.rb +32 -0
- data/lib/new_relic/agent/parameter_filtering.rb +1 -1
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
- data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
- data/lib/new_relic/agent/serverless_handler.rb +247 -12
- data/lib/new_relic/agent/serverless_handler_event_sources.json +155 -0
- data/lib/new_relic/agent/serverless_handler_event_sources.rb +49 -0
- data/lib/new_relic/agent/span_event_primitive.rb +16 -11
- data/lib/new_relic/agent/system_info.rb +14 -0
- data/lib/new_relic/agent/threading/backtrace_node.rb +10 -1
- data/lib/new_relic/agent/tracer.rb +1 -1
- data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -1
- data/lib/new_relic/agent/transaction/datastore_segment.rb +1 -1
- data/lib/new_relic/agent/transaction/distributed_tracer.rb +3 -3
- data/lib/new_relic/agent/transaction/external_request_segment.rb +0 -10
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +4 -1
- data/lib/new_relic/agent/transaction/request_attributes.rb +14 -7
- data/lib/new_relic/agent/transaction/trace_context.rb +34 -5
- data/lib/new_relic/agent/transaction/tracing.rb +3 -3
- data/lib/new_relic/agent/transaction.rb +4 -7
- data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -1
- data/lib/new_relic/agent/utilization/ecs.rb +22 -0
- data/lib/new_relic/agent/utilization/ecs_v4.rb +22 -0
- data/lib/new_relic/agent/utilization_data.rb +40 -5
- data/lib/new_relic/agent/vm/c_ruby_vm.rb +3 -3
- data/lib/new_relic/agent.rb +124 -2
- data/lib/new_relic/constants.rb +1 -0
- data/lib/new_relic/control/frameworks/grape.rb +14 -0
- data/lib/new_relic/control/frameworks/padrino.rb +14 -0
- data/lib/new_relic/control/frameworks/rails4.rb +1 -3
- data/lib/new_relic/control/instance_methods.rb +6 -0
- data/lib/new_relic/control/instrumentation.rb +1 -1
- data/lib/new_relic/control/private_instance_methods.rb +4 -0
- data/lib/new_relic/control/security_interface.rb +57 -0
- data/lib/new_relic/control.rb +1 -1
- data/lib/new_relic/dependency_detection.rb +11 -14
- data/lib/new_relic/environment_report.rb +2 -2
- data/lib/new_relic/helper.rb +22 -0
- data/lib/new_relic/language_support.rb +3 -1
- data/lib/new_relic/local_environment.rb +1 -4
- data/lib/new_relic/rack/browser_monitoring.rb +20 -8
- data/lib/new_relic/version.rb +1 -1
- data/lib/sequel/extensions/new_relic_instrumentation.rb +3 -2
- data/lib/tasks/config.rake +7 -3
- data/lib/tasks/gha.rake +31 -0
- data/lib/tasks/helpers/config.html.erb +3 -2
- data/lib/tasks/helpers/format.rb +1 -1
- data/lib/tasks/helpers/newrelicyml.rb +80 -13
- data/newrelic.yml +425 -162
- data/newrelic_rpm.gemspec +3 -1
- data/test/agent_helper.rb +24 -2
- metadata +91 -22
- 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 -121
- 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_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
@@ -0,0 +1,66 @@
|
|
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 Context
|
9
|
+
module Propagation
|
10
|
+
class TracePropagator
|
11
|
+
# The carrier is the object carrying the headers
|
12
|
+
# The context argument is a no-op, as the OpenTelemetry context is not used
|
13
|
+
# The setter argument is a no-op, added for consistency with the OpenTelemetry API
|
14
|
+
def inject(carrier, context: ::OpenTelemetry::Context.current, setter: nil)
|
15
|
+
# TODO: determine if we need to update this method to take Context into account
|
16
|
+
NewRelic::Agent::DistributedTracing.insert_distributed_trace_headers(carrier)
|
17
|
+
end
|
18
|
+
|
19
|
+
# The return value for this method should be an instance of the
|
20
|
+
# OpenTelemetry Context class. The return value of
|
21
|
+
# #accept_distributed_trace_headers is a transaction, so we cannot
|
22
|
+
# use it to extract the context.
|
23
|
+
def extract(carrier, context: ::OpenTelemetry::Context.current, getter: ::OpenTelemetry::Context::Propagation.text_map_getter)
|
24
|
+
carrier_format = determine_format(getter)
|
25
|
+
trace_context = NewRelic::Agent::DistributedTracing::TraceContext.parse(
|
26
|
+
carrier: carrier,
|
27
|
+
format: carrier_format,
|
28
|
+
trace_state_entry_key: Transaction::TraceContext::AccountHelpers.trace_state_entry_key
|
29
|
+
)
|
30
|
+
tp = trace_context.trace_parent
|
31
|
+
span_context = ::OpenTelemetry::Trace::SpanContext.new(
|
32
|
+
trace_id: tp['trace_id'],
|
33
|
+
span_id: tp['parent_id'],
|
34
|
+
trace_flags: tp['trace_flags'],
|
35
|
+
tracestate: trace_context.trace_state_payload,
|
36
|
+
remote: true
|
37
|
+
)
|
38
|
+
span = ::OpenTelemetry::Trace.non_recording_span(span_context)
|
39
|
+
|
40
|
+
::OpenTelemetry::Trace.context_with_span(span, parent_context: context)
|
41
|
+
rescue StandardError => e
|
42
|
+
NewRelic::Agent.logger.error("Unable to extract context: #{e.message}")
|
43
|
+
context
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# The getter is the way OpenTelemetry handles Rack vs. non-Rack
|
49
|
+
# formats. Rather than using their parser, get the class info we
|
50
|
+
# need to do things the New Relic way
|
51
|
+
def determine_format(getter)
|
52
|
+
case getter
|
53
|
+
when ::OpenTelemetry::Context::Propagation::RackEnvGetter
|
54
|
+
FORMAT_RACK
|
55
|
+
when defined?(::OpenTelemetry::Common) && ::OpenTelemetry::Common::Propagation::RackEnvGetter
|
56
|
+
FORMAT_RACK
|
57
|
+
else
|
58
|
+
FORMAT_NON_RACK
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
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 Context
|
9
|
+
module Propagation
|
10
|
+
require_relative 'propagation/trace_propagator'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -2,8 +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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
module NewRelic
|
6
|
+
module Agent
|
7
|
+
module OpenTelemetry
|
8
|
+
module Context
|
9
|
+
require_relative 'context/propagation'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# This file is distributed under New Relic's license terms.
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module NewRelic
|
6
|
+
module Agent
|
7
|
+
module OpenTelemetry
|
8
|
+
module Trace
|
9
|
+
class Span < ::OpenTelemetry::Trace::Span
|
10
|
+
attr_accessor :finishable
|
11
|
+
|
12
|
+
def finish(end_timestamp: nil)
|
13
|
+
finishable&.finish
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_attribute(key, value)
|
17
|
+
NewRelic::Agent.add_custom_span_attributes(key => value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_attributes(attributes)
|
21
|
+
NewRelic::Agent.add_custom_span_attributes(attributes)
|
22
|
+
end
|
23
|
+
|
24
|
+
def record_exception(exception, attributes: nil)
|
25
|
+
NewRelic::Agent.notice_error(exception, attributes: attributes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,129 @@
|
|
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 start_span(name, with_parent: nil, attributes: nil, links: nil, start_timestamp: nil, kind: nil)
|
16
|
+
parent_otel_context = ::OpenTelemetry::Trace.current_span(with_parent).context
|
17
|
+
|
18
|
+
finishable = if can_start_transaction?(parent_otel_context)
|
19
|
+
return if internal_span_kind_with_invalid_parent?(kind, parent_otel_context)
|
20
|
+
|
21
|
+
nr_item = NewRelic::Agent::Tracer.start_transaction_or_segment(name: name, category: :otel)
|
22
|
+
add_remote_context_to_txn(nr_item, parent_otel_context)
|
23
|
+
nr_item
|
24
|
+
else
|
25
|
+
NewRelic::Agent::Tracer.start_segment(name: name)
|
26
|
+
end
|
27
|
+
|
28
|
+
otel_span = get_otel_span_from_finishable(finishable)
|
29
|
+
otel_span.finishable = finishable
|
30
|
+
add_remote_context_to_otel_span(otel_span, parent_otel_context)
|
31
|
+
otel_span.add_attributes(attributes) if attributes
|
32
|
+
otel_span
|
33
|
+
end
|
34
|
+
|
35
|
+
def in_span(name, attributes: nil, links: nil, start_timestamp: nil, kind: nil)
|
36
|
+
span = start_span(name, attributes: attributes, links: links, start_timestamp: start_timestamp, kind: kind)
|
37
|
+
begin
|
38
|
+
yield
|
39
|
+
rescue => e
|
40
|
+
# TODO: Update for segment errors if finishable is a segment
|
41
|
+
NewRelic::Agent.notice_error(e)
|
42
|
+
raise
|
43
|
+
end
|
44
|
+
ensure
|
45
|
+
span&.finish
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def get_otel_span_from_finishable(finishable)
|
51
|
+
case finishable
|
52
|
+
when NewRelic::Agent::Transaction
|
53
|
+
finishable.segments.first.instance_variable_get(:@otel_span)
|
54
|
+
when NewRelic::Agent::Transaction::Segment
|
55
|
+
finishable.instance_variable_get(:@otel_span)
|
56
|
+
else
|
57
|
+
NewRelic::Agent.logger.warn('Tracer#get_otel_span_from_finishable failed to get span from finishable - finishable is not a transaction or segment')
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def can_start_transaction?(parent_otel_context)
|
63
|
+
parent_otel_context.remote? || !parent_otel_context.valid?
|
64
|
+
end
|
65
|
+
|
66
|
+
def internal_span_kind_with_invalid_parent?(kind, parent_otel_context)
|
67
|
+
!parent_otel_context.valid? && kind == :internal
|
68
|
+
end
|
69
|
+
|
70
|
+
def transaction_and_remote_parent?(txn, parent_otel_context)
|
71
|
+
txn.is_a?(NewRelic::Agent::Transaction) && parent_otel_context.remote?
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_remote_context_to_txn(txn, parent_otel_context)
|
75
|
+
return unless transaction_and_remote_parent?(txn, parent_otel_context)
|
76
|
+
|
77
|
+
txn.trace_id = parent_otel_context.trace_id
|
78
|
+
txn.parent_span_id = parent_otel_context.span_id
|
79
|
+
|
80
|
+
set_tracestate(txn.distributed_tracer, parent_otel_context)
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_tracestate(distributed_tracer, otel_context)
|
84
|
+
case otel_context.tracestate
|
85
|
+
when ::OpenTelemetry::Trace::Tracestate
|
86
|
+
set_otel_trace_state(distributed_tracer, otel_context)
|
87
|
+
when NewRelic::Agent::TraceContextPayload
|
88
|
+
set_nr_trace_state(distributed_tracer, otel_context)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def set_nr_trace_state(distributed_tracer, otel_context)
|
93
|
+
distributed_tracer.instance_variable_set(:@trace_state_payload, otel_context.tracestate)
|
94
|
+
distributed_tracer.parent_transaction_id = distributed_tracer.trace_state_payload.transaction_id
|
95
|
+
distributed_tracer.determine_sampling_decision(otel_context.tracestate, otel_context.trace_flags)
|
96
|
+
end
|
97
|
+
|
98
|
+
def set_otel_trace_state(distributed_tracer, otel_context)
|
99
|
+
nr_entry = otel_context.tracestate.value(Transaction::TraceContext::AccountHelpers.trace_state_entry_key)
|
100
|
+
return unless nr_entry
|
101
|
+
|
102
|
+
nr_payload = NewRelic::Agent::TraceContextPayload.from_s(nr_entry)
|
103
|
+
distributed_tracer.instance_variable_set(:@trace_state_payload, nr_payload)
|
104
|
+
distributed_tracer.parent_transaction_id = distributed_tracer.trace_state_payload.transaction_id
|
105
|
+
trace_flags = parse_trace_flags(otel_context.trace_flags)
|
106
|
+
distributed_tracer.determine_sampling_decision(nr_payload, trace_flags)
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_trace_flags(trace_flags)
|
110
|
+
case trace_flags
|
111
|
+
when String
|
112
|
+
trace_flags
|
113
|
+
when Integer
|
114
|
+
trace_flags.to_s
|
115
|
+
when ::OpenTelemetry::Trace::TraceFlags
|
116
|
+
trace_flags.sampled? ? '01' : '00'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_remote_context_to_otel_span(otel_span, parent_otel_context)
|
121
|
+
return unless transaction_and_remote_parent?(otel_span.finishable, parent_otel_context)
|
122
|
+
|
123
|
+
otel_span.context.instance_variable_set(:@trace_id, otel_span.finishable.trace_id)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
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,69 @@
|
|
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 TransactionPatch
|
9
|
+
attr_accessor :opentelemetry_context
|
10
|
+
|
11
|
+
def initialize(_category, _options)
|
12
|
+
@opentelemetry_context = {}
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_current_segment(new_segment)
|
17
|
+
@current_segment_lock.synchronize do
|
18
|
+
unless opentelemetry_context.empty?
|
19
|
+
::OpenTelemetry::Context.detach(opentelemetry_context[otel_current_span_key])
|
20
|
+
end
|
21
|
+
|
22
|
+
span = find_or_create_span(new_segment)
|
23
|
+
ctx = ::OpenTelemetry::Context.current.set_value(otel_current_span_key, span)
|
24
|
+
token = ::OpenTelemetry::Context.attach(ctx)
|
25
|
+
|
26
|
+
opentelemetry_context[otel_current_span_key] = token
|
27
|
+
end
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def remove_current_segment_by_thread_id(id)
|
33
|
+
# make sure the context is fully detached when the transaction ends
|
34
|
+
@current_segment_lock.synchronize do
|
35
|
+
::OpenTelemetry::Context.detach(opentelemetry_context[otel_current_span_key])
|
36
|
+
opentelemetry_context.delete(id)
|
37
|
+
end
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def find_or_create_span(segment)
|
45
|
+
if segment.instance_variable_defined?(:@otel_span)
|
46
|
+
segment.instance_variable_get(:@otel_span)
|
47
|
+
else
|
48
|
+
span = Trace::Span.new(span_context: span_context_from_segment(segment))
|
49
|
+
segment.instance_variable_set(:@otel_span, span)
|
50
|
+
span
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def span_context_from_segment(segment)
|
55
|
+
::OpenTelemetry::Trace::SpanContext.new(
|
56
|
+
trace_id: segment.transaction.trace_id,
|
57
|
+
span_id: segment.guid,
|
58
|
+
remote: false
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def otel_current_span_key
|
63
|
+
# CURRENT_SPAN_KEY is a private constant
|
64
|
+
::OpenTelemetry::Trace.const_get(:CURRENT_SPAN_KEY)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,32 @@
|
|
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
|
+
require_relative 'opentelemetry/transaction_patch'
|
22
|
+
require_relative 'opentelemetry/context'
|
23
|
+
|
24
|
+
# TODO: Add a warning if SDK gem is installed
|
25
|
+
|
26
|
+
::OpenTelemetry.tracer_provider = OpenTelemetry::Trace::TracerProvider.new
|
27
|
+
Transaction.prepend(OpenTelemetry::TransactionPatch)
|
28
|
+
::OpenTelemetry.propagation = OpenTelemetry::Context::Propagation::TracePropagator.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -9,7 +9,7 @@ module NewRelic
|
|
9
9
|
|
10
10
|
ACTION_DISPATCH_PARAMETER_FILTER ||= 'action_dispatch.parameter_filter'.freeze
|
11
11
|
|
12
|
-
if defined?(Rails) &&
|
12
|
+
if defined?(Rails) && NewRelic::Helper.version_satisfied?(::Rails::VERSION::STRING, '>=', '5.0.0')
|
13
13
|
Rails.application.config.to_prepare do
|
14
14
|
RAILS_FILTER_CLASS ||= if defined?(ActiveSupport::ParameterFilter)
|
15
15
|
ActiveSupport::ParameterFilter
|
@@ -42,7 +42,7 @@ module NewRelic
|
|
42
42
|
# Process.times on JRuby < 1.7.0 reports wall clock elapsed time,
|
43
43
|
# not actual cpu time used, so this sampler can only be used on JRuby >= 1.7.0.
|
44
44
|
if defined?(JRuby)
|
45
|
-
return JRUBY_VERSION >= '1.7.0'
|
45
|
+
return NewRelic::Helper.version_satisfied?(JRUBY_VERSION, '>=', '1.7.0')
|
46
46
|
end
|
47
47
|
|
48
48
|
true
|