newrelic_rpm 9.1.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 +27 -0
- data/CHANGELOG.md +841 -7
- data/CONTRIBUTING.md +2 -9
- data/README.md +25 -22
- data/Rakefile +2 -2
- data/bin/newrelic +3 -9
- data/bin/newrelic_rpm +15 -0
- data/init.rb +2 -2
- data/lib/boot/strap.rb +102 -0
- data/lib/new_relic/agent/agent.rb +11 -2
- data/lib/new_relic/agent/agent_helpers/connect.rb +13 -8
- data/lib/new_relic/agent/agent_helpers/harvest.rb +3 -0
- data/lib/new_relic/agent/agent_helpers/shutdown.rb +4 -1
- data/lib/new_relic/agent/agent_helpers/special_startup.rb +1 -1
- data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +4 -3
- data/lib/new_relic/agent/agent_helpers/startup.rb +11 -3
- data/lib/new_relic/agent/agent_logger.rb +3 -1
- data/lib/new_relic/agent/attribute_filter.rb +3 -3
- data/lib/new_relic/agent/attribute_pre_filtering.rb +109 -0
- data/lib/new_relic/agent/aws.rb +68 -0
- data/lib/new_relic/agent/configuration/default_source.rb +918 -166
- data/lib/new_relic/agent/configuration/environment_source.rb +15 -3
- data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
- data/lib/new_relic/agent/configuration/manager.rb +72 -11
- data/lib/new_relic/agent/configuration/security_policy_source.rb +11 -0
- data/lib/new_relic/agent/configuration/yaml_source.rb +22 -2
- data/lib/new_relic/agent/connect/request_builder.rb +1 -1
- data/lib/new_relic/agent/custom_event_aggregator.rb +27 -1
- 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/mongo/metric_translator.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/distributed_trace_payload.rb +4 -8
- data/lib/new_relic/agent/distributed_tracing.rb +5 -3
- data/lib/new_relic/agent/error_collector.rb +40 -11
- data/lib/new_relic/agent/event_loop.rb +1 -1
- data/lib/new_relic/agent/external.rb +2 -0
- data/lib/new_relic/agent/harvester.rb +1 -1
- data/lib/new_relic/agent/health_check.rb +136 -0
- data/lib/new_relic/agent/http_clients/abstract.rb +4 -0
- data/lib/new_relic/agent/http_clients/async_http_wrappers.rb +80 -0
- data/lib/new_relic/agent/http_clients/curb_wrappers.rb +1 -3
- data/lib/new_relic/agent/http_clients/ethon_wrappers.rb +109 -0
- data/lib/new_relic/agent/http_clients/excon_wrappers.rb +0 -3
- data/lib/new_relic/agent/http_clients/http_rb_wrappers.rb +1 -3
- data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +0 -3
- data/lib/new_relic/agent/http_clients/httpx_wrappers.rb +91 -0
- data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +1 -4
- data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +0 -3
- data/lib/new_relic/agent/http_clients/uri_util.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.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 +3 -16
- data/lib/new_relic/agent/instrumentation/active_record.rb +8 -13
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +8 -5
- data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +13 -10
- 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/chain.rb +69 -0
- data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/instrumentation.rb +17 -0
- data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/prepend.rb +37 -0
- data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger.rb +21 -0
- data/lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/active_support_logger.rb +3 -3
- data/lib/new_relic/agent/instrumentation/async_http/chain.rb +23 -0
- data/lib/new_relic/agent/instrumentation/async_http/instrumentation.rb +37 -0
- data/lib/new_relic/agent/instrumentation/async_http/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/async_http.rb +27 -0
- 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/chain.rb +1 -1
- data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +23 -0
- data/lib/new_relic/agent/instrumentation/bunny.rb +4 -5
- data/lib/new_relic/agent/instrumentation/concurrent_ruby/chain.rb +1 -1
- data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +3 -4
- data/lib/new_relic/agent/instrumentation/concurrent_ruby/prepend.rb +1 -1
- data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +2 -3
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +5 -2
- data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/curb.rb +4 -5
- data/lib/new_relic/agent/instrumentation/delayed_job/chain.rb +1 -0
- data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +3 -0
- 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 +2 -3
- data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +65 -10
- data/lib/new_relic/agent/instrumentation/elasticsearch.rb +2 -4
- data/lib/new_relic/agent/instrumentation/ethon/chain.rb +39 -0
- data/lib/new_relic/agent/instrumentation/ethon/instrumentation.rb +105 -0
- data/lib/new_relic/agent/instrumentation/ethon/prepend.rb +35 -0
- data/lib/new_relic/agent/instrumentation/ethon.rb +35 -0
- data/lib/new_relic/agent/instrumentation/excon/middleware.rb +3 -0
- data/lib/new_relic/agent/instrumentation/excon.rb +1 -17
- data/lib/new_relic/agent/instrumentation/fiber/chain.rb +11 -4
- data/lib/new_relic/agent/instrumentation/fiber/instrumentation.rb +2 -6
- data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +10 -3
- data/lib/new_relic/agent/instrumentation/fiber.rb +1 -3
- data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +4 -3
- data/lib/new_relic/agent/instrumentation/grape.rb +1 -1
- data/lib/new_relic/agent/instrumentation/grpc/client/chain.rb +1 -1
- data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +5 -2
- data/lib/new_relic/agent/instrumentation/grpc/client/prepend.rb +1 -1
- data/lib/new_relic/agent/instrumentation/grpc/client/request_wrapper.rb +1 -1
- data/lib/new_relic/agent/instrumentation/grpc/server/instrumentation.rb +5 -1
- data/lib/new_relic/agent/instrumentation/grpc_client.rb +2 -2
- data/lib/new_relic/agent/instrumentation/grpc_server.rb +2 -2
- data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -5
- data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
- data/lib/new_relic/agent/instrumentation/httpx/chain.rb +20 -0
- data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +51 -0
- data/lib/new_relic/agent/instrumentation/httpx/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/httpx.rb +23 -0
- data/lib/new_relic/agent/instrumentation/logger/instrumentation.rb +3 -0
- 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 +4 -2
- data/lib/new_relic/agent/instrumentation/memcache/helper.rb +2 -2
- data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +13 -4
- data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +4 -2
- data/lib/new_relic/agent/instrumentation/memcache.rb +4 -5
- data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +3 -5
- data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +13 -3
- data/lib/new_relic/agent/instrumentation/net_http.rb +2 -1
- data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +4 -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/new_relic/agent/instrumentation/opensearch/prepend.rb +13 -0
- data/lib/new_relic/agent/instrumentation/opensearch.rb +23 -0
- data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
- data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +9 -0
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +4 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +10 -5
- data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +4 -0
- 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 +18 -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/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/resque.rb +8 -6
- data/lib/new_relic/agent/instrumentation/roda/chain.rb +43 -0
- data/lib/new_relic/agent/instrumentation/roda/ignorer.rb +45 -0
- data/lib/new_relic/agent/instrumentation/roda/instrumentation.rb +68 -0
- data/lib/new_relic/agent/instrumentation/roda/prepend.rb +24 -0
- data/lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb +29 -0
- data/lib/new_relic/agent/instrumentation/roda.rb +36 -0
- 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/chain.rb +36 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai/instrumentation.rb +196 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai/prepend.rb +20 -0
- data/lib/new_relic/agent/instrumentation/ruby_openai.rb +35 -0
- data/lib/new_relic/agent/instrumentation/sequel.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sidekiq/client.rb +4 -0
- 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/server.rb +26 -3
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +13 -16
- data/lib/new_relic/agent/instrumentation/sinatra/ignorer.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +1 -3
- data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -19
- data/lib/new_relic/agent/instrumentation/stripe.rb +28 -0
- data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +98 -0
- data/lib/new_relic/agent/instrumentation/thread/chain.rb +1 -1
- data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +1 -5
- data/lib/new_relic/agent/instrumentation/thread/prepend.rb +1 -1
- data/lib/new_relic/agent/instrumentation/thread.rb +0 -2
- data/lib/new_relic/agent/instrumentation/tilt/instrumentation.rb +4 -0
- data/lib/new_relic/agent/instrumentation/tilt.rb +0 -4
- data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +7 -3
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
- data/lib/new_relic/agent/instrumentation/view_component/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +45 -0
- data/lib/{tasks/instrumentation_generator/templates/instrumentation.tt → new_relic/agent/instrumentation/view_component/prepend.rb} +4 -4
- data/lib/new_relic/agent/instrumentation/view_component.rb +24 -0
- data/lib/new_relic/agent/javascript_instrumentor.rb +2 -4
- data/lib/new_relic/agent/llm/chat_completion_message.rb +25 -0
- data/lib/new_relic/agent/llm/chat_completion_summary.rb +66 -0
- data/lib/new_relic/agent/llm/embedding.rb +60 -0
- data/lib/new_relic/agent/llm/llm_event.rb +95 -0
- data/lib/new_relic/agent/llm/response_headers.rb +80 -0
- data/lib/new_relic/agent/llm.rb +49 -0
- data/lib/new_relic/agent/local_log_decorator.rb +20 -3
- data/lib/new_relic/agent/log_event_aggregator.rb +149 -26
- data/lib/new_relic/agent/log_event_attributes.rb +115 -0
- data/lib/new_relic/agent/logging.rb +5 -5
- data/lib/new_relic/agent/messaging.rb +18 -7
- data/lib/new_relic/agent/method_tracer.rb +4 -1
- data/lib/new_relic/agent/method_tracer_helpers.rb +26 -5
- data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
- data/lib/new_relic/agent/monitors/synthetics_monitor.rb +12 -1
- data/lib/new_relic/agent/new_relic_service/encoders.rb +2 -2
- data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +2 -2
- data/lib/new_relic/agent/new_relic_service.rb +61 -28
- data/lib/new_relic/agent/obfuscator.rb +0 -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/pipe_channel_manager.rb +2 -2
- data/lib/new_relic/agent/pipe_service.rb +1 -1
- data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +1 -2
- data/lib/new_relic/agent/rules_engine.rb +1 -1
- data/lib/new_relic/agent/sampler.rb +1 -0
- 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 +406 -0
- 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 +32 -15
- data/lib/new_relic/agent/sql_sampler.rb +0 -1
- data/lib/new_relic/agent/system_info.rb +40 -0
- data/lib/new_relic/agent/threading/agent_thread.rb +1 -2
- data/lib/new_relic/agent/threading/backtrace_node.rb +10 -1
- data/lib/new_relic/agent/tracer.rb +16 -16
- data/lib/new_relic/agent/transaction/abstract_segment.rb +103 -41
- 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/distributed_tracing.rb +7 -8
- data/lib/new_relic/agent/transaction/external_request_segment.rb +5 -12
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +5 -3
- data/lib/new_relic/agent/transaction/request_attributes.rb +54 -11
- data/lib/new_relic/agent/transaction/trace_context.rb +34 -5
- data/lib/new_relic/agent/transaction/tracing.rb +20 -4
- data/lib/new_relic/agent/transaction.rb +38 -13
- data/lib/new_relic/agent/transaction_error_primitive.rb +39 -19
- data/lib/new_relic/agent/transaction_event_primitive.rb +19 -0
- 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/gcp.rb +1 -3
- data/lib/new_relic/agent/utilization/vendor.rb +5 -7
- data/lib/new_relic/agent/utilization_data.rb +40 -5
- data/lib/new_relic/agent/vm/{mri_vm.rb → c_ruby_vm.rb} +10 -18
- data/lib/new_relic/agent/vm.rb +2 -2
- data/lib/new_relic/agent/worker_loop.rb +1 -1
- data/lib/new_relic/agent.rb +286 -17
- data/lib/new_relic/base64.rb +25 -0
- data/lib/new_relic/cli/command.rb +6 -3
- data/lib/new_relic/constants.rb +8 -0
- data/lib/new_relic/control/class_methods.rb +1 -7
- 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/rails.rb +17 -5
- data/lib/new_relic/control/frameworks/rails4.rb +1 -3
- data/lib/new_relic/control/frameworks/roda.rb +20 -0
- data/lib/new_relic/control/instance_methods.rb +13 -0
- data/lib/new_relic/control/instrumentation.rb +2 -16
- 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 +25 -13
- data/lib/new_relic/environment_report.rb +2 -2
- data/lib/new_relic/helper.rb +22 -0
- data/lib/new_relic/language_support.rb +12 -1
- data/lib/new_relic/latest_changes.rb +1 -1
- data/lib/new_relic/local_environment.rb +31 -18
- data/lib/new_relic/noticed_error.rb +5 -2
- data/lib/new_relic/rack/agent_hooks.rb +1 -1
- data/lib/new_relic/rack/agent_middleware.rb +0 -16
- data/lib/new_relic/rack/browser_monitoring.rb +29 -13
- data/lib/new_relic/supportability_helper.rb +5 -1
- data/lib/new_relic/thread_local_storage.rb +31 -0
- data/lib/new_relic/traced_thread.rb +2 -3
- data/lib/new_relic/version.rb +1 -1
- data/lib/sequel/extensions/new_relic_instrumentation.rb +4 -3
- data/lib/tasks/bump_version.rake +21 -0
- data/lib/tasks/config.rake +11 -5
- data/lib/tasks/coverage_report.rake +1 -1
- data/lib/tasks/gha.rake +31 -0
- data/lib/tasks/helpers/config.html.erb +94 -0
- data/lib/tasks/helpers/format.rb +11 -7
- data/lib/tasks/helpers/newrelicyml.rb +211 -0
- data/lib/tasks/helpers/version_bump.rb +62 -0
- data/lib/tasks/newrelic.rb +1 -0
- data/lib/tasks/newrelicyml.rake +13 -0
- data/lib/tasks/tests.rake +71 -0
- data/newrelic.yml +657 -251
- data/newrelic_rpm.gemspec +17 -10
- data/test/agent_helper.rb +38 -4
- metadata +230 -44
- data/.gitignore +0 -43
- data/.project +0 -23
- data/.rubocop.yml +0 -1909
- data/.rubocop_todo.yml +0 -61
- data/.simplecov +0 -15
- data/.snyk +0 -11
- data/.yardopts +0 -27
- data/Brewfile +0 -12
- data/DOCKER.md +0 -167
- data/Dockerfile +0 -10
- data/Guardfile +0 -26
- data/bin/newrelic_cmd +0 -6
- data/config/database.yml +0 -5
- data/config.dot +0 -278
- data/docker-compose.yml +0 -107
- data/lefthook.yml +0 -9
- data/lib/new_relic/agent/range_extensions.rb +0 -27
- data/lib/tasks/helpers/removers.rb +0 -33
- 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 -22
- data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -8
- 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
- data/lib/tasks/multiverse.rake +0 -6
- data/lib/tasks/multiverse.rb +0 -83
|
@@ -19,7 +19,7 @@ module NewRelic
|
|
|
19
19
|
def warn_for_yajl
|
|
20
20
|
if defined?(::Yajl)
|
|
21
21
|
require 'yajl/version'
|
|
22
|
-
if
|
|
22
|
+
if NewRelic::Helper.version_satisfied?(::Yajl::VERSION, '<', OK_YAJL_VERSION)
|
|
23
23
|
::NewRelic::Agent.logger.warn("Detected yajl-ruby version #{::Yajl::VERSION} which can cause segfaults with newrelic_rpm's thread profiling features. We strongly recommend you upgrade to the latest yajl-ruby version available.")
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -42,7 +42,7 @@ module NewRelic
|
|
|
42
42
|
return nil
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
return_value(::JSON.
|
|
45
|
+
return_value(::JSON.parse(data))
|
|
46
46
|
rescue => e
|
|
47
47
|
::NewRelic::Agent.logger.debug("#{e.class.name} : #{e.message} encountered loading collector response: #{data}")
|
|
48
48
|
raise
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# frozen_string_literal: true
|
|
4
4
|
|
|
5
5
|
require 'zlib'
|
|
6
|
-
require 'timeout'
|
|
7
6
|
require 'new_relic/agent/audit_logger'
|
|
8
7
|
require 'new_relic/agent/new_relic_service/encoders'
|
|
9
8
|
require 'new_relic/agent/new_relic_service/marshaller'
|
|
@@ -19,7 +18,13 @@ module NewRelic
|
|
|
19
18
|
|
|
20
19
|
# These include Errno connection errors, and all indicate that the
|
|
21
20
|
# underlying TCP connection may be in a bad state.
|
|
22
|
-
CONNECTION_ERRORS = [
|
|
21
|
+
CONNECTION_ERRORS = [Net::OpenTimeout, Net::ReadTimeout, EOFError, SystemCallError, SocketError]
|
|
22
|
+
# TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until Ruby 2.6.
|
|
23
|
+
# Once support for Ruby 2.5 is dropped, we should simply include
|
|
24
|
+
# Net::WriteTimeout in the connection errors array directly instead
|
|
25
|
+
# of with a conditional
|
|
26
|
+
CONNECTION_ERRORS << Net::WriteTimeout if defined?(Net::WriteTimeout)
|
|
27
|
+
CONNECTION_ERRORS.freeze
|
|
23
28
|
|
|
24
29
|
# The maximum number of times to attempt an HTTP request
|
|
25
30
|
MAX_ATTEMPTS = 2
|
|
@@ -138,6 +143,9 @@ module NewRelic
|
|
|
138
143
|
end
|
|
139
144
|
|
|
140
145
|
def metric_data(stats_hash)
|
|
146
|
+
# let the serverless handler handle serialization
|
|
147
|
+
return NewRelic::Agent.agent.serverless_handler.metric_data(stats_hash) if NewRelic::Agent.agent.serverless?
|
|
148
|
+
|
|
141
149
|
timeslice_start = stats_hash.started_at
|
|
142
150
|
timeslice_end = stats_hash.harvested_at || Process.clock_gettime(Process::CLOCK_REALTIME)
|
|
143
151
|
metric_data_array = build_metric_data_array(stats_hash)
|
|
@@ -149,6 +157,9 @@ module NewRelic
|
|
|
149
157
|
end
|
|
150
158
|
|
|
151
159
|
def error_data(unsent_errors)
|
|
160
|
+
# let the serverless handler handle serialization
|
|
161
|
+
return NewRelic::Agent.agent.serverless_handler.error_data(unsent_errors) if NewRelic::Agent.agent.serverless?
|
|
162
|
+
|
|
152
163
|
invoke_remote(:error_data, [@agent_id, unsent_errors],
|
|
153
164
|
:item_count => unsent_errors.size)
|
|
154
165
|
end
|
|
@@ -319,13 +330,15 @@ module NewRelic
|
|
|
319
330
|
|
|
320
331
|
def start_connection(conn)
|
|
321
332
|
NewRelic::Agent.logger.debug("Opening TCP connection to #{conn.address}:#{conn.port}")
|
|
322
|
-
|
|
323
|
-
conn
|
|
333
|
+
conn.start
|
|
324
334
|
end
|
|
325
335
|
|
|
326
336
|
def setup_connection_timeouts(conn)
|
|
327
|
-
|
|
328
|
-
conn.read_timeout =
|
|
337
|
+
conn.open_timeout = @request_timeout
|
|
338
|
+
conn.read_timeout = @request_timeout
|
|
339
|
+
# TODO: MAJOR VERSION - #write_timeout= requires Ruby 2.6+, so remove
|
|
340
|
+
# the conditional check once support for Ruby 2.5 is dropped
|
|
341
|
+
conn.write_timeout = @request_timeout if conn.respond_to?(:write_timeout=)
|
|
329
342
|
|
|
330
343
|
if conn.respond_to?(:keep_alive_timeout) && NewRelic::Agent.config[:aggressive_keepalive]
|
|
331
344
|
conn.keep_alive_timeout = NewRelic::Agent.config[:keep_alive_timeout]
|
|
@@ -362,8 +375,8 @@ module NewRelic
|
|
|
362
375
|
conn = create_http_connection
|
|
363
376
|
start_connection(conn)
|
|
364
377
|
conn
|
|
365
|
-
rescue
|
|
366
|
-
::NewRelic::Agent.logger.info('
|
|
378
|
+
rescue Net::OpenTimeout
|
|
379
|
+
::NewRelic::Agent.logger.info('Timed out while attempting to connect. For SSL issues, you may need to install system-level CA Certificates to be used by Net::HTTP.')
|
|
367
380
|
raise
|
|
368
381
|
end
|
|
369
382
|
|
|
@@ -407,7 +420,7 @@ module NewRelic
|
|
|
407
420
|
else
|
|
408
421
|
request = Net::HTTP::Post.new(opts[:uri], headers)
|
|
409
422
|
end
|
|
410
|
-
@audit_logger.log_request_headers(opts[:uri], headers)
|
|
423
|
+
@audit_logger.log_request_headers(filtered_uri(opts[:uri]), headers)
|
|
411
424
|
request['user-agent'] = user_agent
|
|
412
425
|
request.content_type = 'application/octet-stream'
|
|
413
426
|
request.body = opts[:data]
|
|
@@ -424,7 +437,7 @@ module NewRelic
|
|
|
424
437
|
rescue *CONNECTION_ERRORS => e
|
|
425
438
|
close_shared_connection
|
|
426
439
|
if attempts < MAX_ATTEMPTS
|
|
427
|
-
::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
|
|
440
|
+
::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{filtered_uri(opts[:uri])} after #{e}")
|
|
428
441
|
retry
|
|
429
442
|
else
|
|
430
443
|
raise ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
|
|
@@ -436,21 +449,21 @@ module NewRelic
|
|
|
436
449
|
end
|
|
437
450
|
|
|
438
451
|
def attempt_request(request, opts)
|
|
439
|
-
response = nil
|
|
440
452
|
conn = http_connection
|
|
441
|
-
::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}")
|
|
442
|
-
|
|
443
|
-
response = conn.request(request)
|
|
444
|
-
end
|
|
445
|
-
response
|
|
453
|
+
::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{filtered_uri(opts[:uri])} with #{request.method}")
|
|
454
|
+
conn.request(request)
|
|
446
455
|
end
|
|
447
456
|
|
|
448
457
|
def handle_error_response(response, endpoint)
|
|
458
|
+
NewRelic::Agent.agent&.health_check&.update_status(NewRelic::Agent::HealthCheck::HTTP_ERROR, [response.code, endpoint])
|
|
459
|
+
|
|
449
460
|
case response
|
|
450
461
|
when Net::HTTPRequestTimeOut,
|
|
451
462
|
Net::HTTPTooManyRequests,
|
|
452
463
|
Net::HTTPInternalServerError,
|
|
453
|
-
Net::HTTPServiceUnavailable
|
|
464
|
+
Net::HTTPServiceUnavailable,
|
|
465
|
+
Net::OpenTimeout,
|
|
466
|
+
Net::ReadTimeout
|
|
454
467
|
handle_server_connection_exception(response, endpoint)
|
|
455
468
|
when Net::HTTPBadRequest,
|
|
456
469
|
Net::HTTPForbidden,
|
|
@@ -462,7 +475,6 @@ module NewRelic
|
|
|
462
475
|
Net::HTTPRequestURITooLong,
|
|
463
476
|
Net::HTTPUnsupportedMediaType,
|
|
464
477
|
Net::HTTPExpectationFailed,
|
|
465
|
-
Net::HTTPUnsupportedMediaType,
|
|
466
478
|
Net::HTTPRequestHeaderFieldsTooLarge
|
|
467
479
|
handle_unrecoverable_server_exception(response, endpoint)
|
|
468
480
|
when Net::HTTPConflict,
|
|
@@ -472,9 +484,20 @@ module NewRelic
|
|
|
472
484
|
when Net::HTTPGone
|
|
473
485
|
handle_gone_response(response, endpoint)
|
|
474
486
|
else
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
487
|
+
# TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until
|
|
488
|
+
# Ruby 2.6, so it can't be included in the case statement
|
|
489
|
+
# as a constant and instead needs to be found here. Once
|
|
490
|
+
# support for Ruby 2.5 is dropped, we should have
|
|
491
|
+
# Net::WriteTimeout sit in the 'when' clause above alongside
|
|
492
|
+
# Net::OpenTimeout and Net::ReadTimeout and this entire if/else
|
|
493
|
+
# conditional can be removed.
|
|
494
|
+
if response.respond_to?(:name) && response.name == 'Net::WriteTimeout'
|
|
495
|
+
handle_server_connection_exception(response, endpoint)
|
|
496
|
+
else
|
|
497
|
+
record_endpoint_attempts_supportability_metrics(endpoint)
|
|
498
|
+
record_error_response_supportability_metrics(response.code)
|
|
499
|
+
raise UnrecoverableServerException, "#{response.code}: #{response.message}"
|
|
500
|
+
end
|
|
478
501
|
end
|
|
479
502
|
response
|
|
480
503
|
end
|
|
@@ -539,6 +562,8 @@ module NewRelic
|
|
|
539
562
|
# enough to be worth compressing, and handles any errors the
|
|
540
563
|
# server may return
|
|
541
564
|
def invoke_remote(method, payload = [], options = {})
|
|
565
|
+
return NewRelic::Agent.agent.serverless_handler.store_payload(method, payload) if NewRelic::Agent.agent.serverless?
|
|
566
|
+
|
|
542
567
|
start_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
543
568
|
request_send_ts, response_check_ts = nil
|
|
544
569
|
data, encoding, size, serialize_finish_ts = marshal_payload(method, payload, options)
|
|
@@ -546,8 +571,10 @@ module NewRelic
|
|
|
546
571
|
response, request_send_ts, response_check_ts = invoke_remote_send_request(method, payload, data, encoding)
|
|
547
572
|
@marshaller.load(decompress_response(response))
|
|
548
573
|
ensure
|
|
549
|
-
|
|
550
|
-
|
|
574
|
+
unless NewRelic::Agent.agent.serverless?
|
|
575
|
+
record_timing_supportability_metrics(method, start_ts, serialize_finish_ts, request_send_ts, response_check_ts)
|
|
576
|
+
record_size_supportability_metrics(method, size, options[:item_count]) if size
|
|
577
|
+
end
|
|
551
578
|
end
|
|
552
579
|
|
|
553
580
|
def handle_serialization_error(method, e)
|
|
@@ -612,9 +639,13 @@ module NewRelic
|
|
|
612
639
|
def send_request(opts)
|
|
613
640
|
request = prep_request(opts)
|
|
614
641
|
response = relay_request(request, opts)
|
|
615
|
-
return response if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPAccepted)
|
|
616
642
|
|
|
617
|
-
|
|
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
|
|
618
649
|
end
|
|
619
650
|
|
|
620
651
|
def log_response(response)
|
|
@@ -674,9 +705,7 @@ module NewRelic
|
|
|
674
705
|
|
|
675
706
|
def invoke_remote_send_request(method, payload, data, encoding)
|
|
676
707
|
uri = remote_method_uri(method)
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
@audit_logger.log_request(full_uri, payload, @marshaller)
|
|
708
|
+
@audit_logger.log_request("#{@collector}#{filtered_uri(uri)}", payload, @marshaller)
|
|
680
709
|
request_send_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
681
710
|
response = send_request(:data => data,
|
|
682
711
|
:uri => uri,
|
|
@@ -685,6 +714,10 @@ module NewRelic
|
|
|
685
714
|
:endpoint => method)
|
|
686
715
|
[response, request_send_ts, Process.clock_gettime(Process::CLOCK_MONOTONIC)]
|
|
687
716
|
end
|
|
717
|
+
|
|
718
|
+
def filtered_uri(uri)
|
|
719
|
+
uri.gsub(license_key, ASTERISK * license_key.size)
|
|
720
|
+
end
|
|
688
721
|
end
|
|
689
722
|
end
|
|
690
723
|
end
|
|
@@ -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
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
|
3
3
|
# frozen_string_literal: true
|
|
4
4
|
|
|
5
|
-
require 'base64'
|
|
5
|
+
require 'new_relic/base64'
|
|
6
6
|
|
|
7
7
|
module NewRelic
|
|
8
8
|
module Agent
|
|
@@ -257,7 +257,7 @@ module NewRelic
|
|
|
257
257
|
Marshal.load(data)
|
|
258
258
|
rescue StandardError => e
|
|
259
259
|
::NewRelic::Agent.logger.error('Failure unmarshalling message from Resque child process', e)
|
|
260
|
-
::NewRelic::Agent.logger.debug(Base64.encode64(data))
|
|
260
|
+
::NewRelic::Agent.logger.debug(NewRelic::Base64.encode64(data))
|
|
261
261
|
nil
|
|
262
262
|
end
|
|
263
263
|
|