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
|
@@ -29,17 +29,23 @@ module NewRelic
|
|
|
29
29
|
CATEGORY_KEY = 'category'
|
|
30
30
|
HTTP_URL_KEY = 'http.url'
|
|
31
31
|
HTTP_METHOD_KEY = 'http.method'
|
|
32
|
+
HTTP_REQUEST_METHOD_KEY = 'http.request.method'
|
|
32
33
|
HTTP_STATUS_CODE_KEY = 'http.statusCode'
|
|
33
34
|
COMPONENT_KEY = 'component'
|
|
34
35
|
DB_INSTANCE_KEY = 'db.instance'
|
|
35
36
|
DB_STATEMENT_KEY = 'db.statement'
|
|
37
|
+
DB_SYSTEM_KEY = 'db.system'
|
|
36
38
|
PEER_ADDRESS_KEY = 'peer.address'
|
|
37
39
|
PEER_HOSTNAME_KEY = 'peer.hostname'
|
|
40
|
+
SERVER_ADDRESS_KEY = 'server.address'
|
|
41
|
+
SERVER_PORT_KEY = 'server.port'
|
|
38
42
|
SPAN_KIND_KEY = 'span.kind'
|
|
43
|
+
STACKTRACE_KEY = 'code.stacktrace'
|
|
39
44
|
ENTRY_POINT_KEY = 'nr.entryPoint'
|
|
40
45
|
TRUSTED_PARENT_KEY = 'trustedParentId'
|
|
41
46
|
TRACING_VENDORS_KEY = 'tracingVendors'
|
|
42
47
|
TRANSACTION_NAME_KEY = 'transaction.name'
|
|
48
|
+
THREAD_ID_KEY = 'thread.id'
|
|
43
49
|
|
|
44
50
|
# Strings for static values of the event structure
|
|
45
51
|
EVENT_TYPE = 'Span'
|
|
@@ -48,6 +54,8 @@ module NewRelic
|
|
|
48
54
|
DATASTORE_CATEGORY = 'datastore'
|
|
49
55
|
CLIENT = 'client'
|
|
50
56
|
|
|
57
|
+
DB_STATEMENT_MAX_BYTES = 4096
|
|
58
|
+
|
|
51
59
|
# Builds a Hash of error attributes as well as the Span ID when
|
|
52
60
|
# an error is present. Otherwise, returns nil when no error present.
|
|
53
61
|
def error_attributes(segment)
|
|
@@ -69,31 +77,29 @@ module NewRelic
|
|
|
69
77
|
|
|
70
78
|
intrinsics[COMPONENT_KEY] = segment.library
|
|
71
79
|
intrinsics[HTTP_METHOD_KEY] = segment.procedure
|
|
80
|
+
intrinsics[HTTP_REQUEST_METHOD_KEY] = segment.procedure
|
|
72
81
|
intrinsics[HTTP_STATUS_CODE_KEY] = segment.http_status_code if segment.http_status_code
|
|
73
82
|
intrinsics[CATEGORY_KEY] = HTTP_CATEGORY
|
|
74
83
|
intrinsics[SPAN_KIND_KEY] = CLIENT
|
|
75
|
-
|
|
76
|
-
|
|
84
|
+
intrinsics[SERVER_ADDRESS_KEY] = segment.uri.host
|
|
85
|
+
intrinsics[SERVER_PORT_KEY] = segment.uri.port
|
|
86
|
+
agent_attributes = {}
|
|
77
87
|
|
|
78
88
|
if allowed?(HTTP_URL_KEY)
|
|
79
89
|
agent_attributes[HTTP_URL_KEY] = truncate(segment.uri)
|
|
80
90
|
end
|
|
81
91
|
|
|
82
|
-
|
|
83
|
-
agent_attributes.merge!(agent_attributes(segment))
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
[intrinsics, custom_attributes(segment), agent_attributes]
|
|
92
|
+
[intrinsics, custom_attributes(segment), agent_attributes.merge(agent_attributes(segment))]
|
|
87
93
|
end
|
|
88
94
|
|
|
89
|
-
def for_datastore_segment(segment)
|
|
95
|
+
def for_datastore_segment(segment) # rubocop:disable Metrics/AbcSize
|
|
90
96
|
intrinsics = intrinsics_for(segment)
|
|
91
97
|
|
|
92
98
|
intrinsics[COMPONENT_KEY] = segment.product
|
|
93
99
|
intrinsics[SPAN_KIND_KEY] = CLIENT
|
|
94
100
|
intrinsics[CATEGORY_KEY] = DATASTORE_CATEGORY
|
|
95
101
|
|
|
96
|
-
agent_attributes =
|
|
102
|
+
agent_attributes = {}
|
|
97
103
|
|
|
98
104
|
if segment.database_name && allowed?(DB_INSTANCE_KEY)
|
|
99
105
|
agent_attributes[DB_INSTANCE_KEY] = truncate(segment.database_name)
|
|
@@ -101,17 +107,27 @@ module NewRelic
|
|
|
101
107
|
if segment.host && segment.port_path_or_id && allowed?(PEER_ADDRESS_KEY)
|
|
102
108
|
agent_attributes[PEER_ADDRESS_KEY] = truncate("#{segment.host}:#{segment.port_path_or_id}")
|
|
103
109
|
end
|
|
104
|
-
if segment.host
|
|
105
|
-
|
|
110
|
+
if segment.host
|
|
111
|
+
[PEER_HOSTNAME_KEY, SERVER_ADDRESS_KEY].each do |key|
|
|
112
|
+
agent_attributes[key] = truncate(segment.host) if allowed?(key)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
if segment.port_path_or_id&.match?(/^\d+$/) && allowed?(SERVER_PORT_KEY)
|
|
116
|
+
agent_attributes[SERVER_PORT_KEY] = segment.port_path_or_id
|
|
106
117
|
end
|
|
118
|
+
agent_attributes[DB_SYSTEM_KEY] = segment.product if allowed?(DB_SYSTEM_KEY)
|
|
107
119
|
|
|
108
120
|
if segment.sql_statement && allowed?(DB_STATEMENT_KEY)
|
|
109
|
-
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.sql_statement.safe_sql,
|
|
121
|
+
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.sql_statement.safe_sql, DB_STATEMENT_MAX_BYTES)
|
|
110
122
|
elsif segment.nosql_statement && allowed?(DB_STATEMENT_KEY)
|
|
111
|
-
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.nosql_statement,
|
|
123
|
+
agent_attributes[DB_STATEMENT_KEY] = truncate(segment.nosql_statement, DB_STATEMENT_MAX_BYTES)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
if segment.params[:backtrace]
|
|
127
|
+
agent_attributes[STACKTRACE_KEY] = segment.params[:backtrace]
|
|
112
128
|
end
|
|
113
129
|
|
|
114
|
-
[intrinsics, custom_attributes(segment), agent_attributes]
|
|
130
|
+
[intrinsics, custom_attributes(segment), agent_attributes.merge(agent_attributes(segment))]
|
|
115
131
|
end
|
|
116
132
|
|
|
117
133
|
private
|
|
@@ -125,7 +141,8 @@ module NewRelic
|
|
|
125
141
|
PRIORITY_KEY => segment.transaction.priority,
|
|
126
142
|
TIMESTAMP_KEY => milliseconds_since_epoch(segment),
|
|
127
143
|
DURATION_KEY => segment.duration,
|
|
128
|
-
NAME_KEY => segment.name
|
|
144
|
+
NAME_KEY => segment.name,
|
|
145
|
+
THREAD_ID_KEY => segment.thread_id
|
|
129
146
|
}
|
|
130
147
|
|
|
131
148
|
# with infinite-tracing, transactions may or may not be sampled!
|
|
@@ -13,10 +13,26 @@ require 'socket'
|
|
|
13
13
|
module NewRelic
|
|
14
14
|
module Agent
|
|
15
15
|
module SystemInfo
|
|
16
|
+
DOCKER_CGROUPS_V2_PATTERN = %r{.*/docker/containers/([0-9a-f]{64})/.*}.freeze
|
|
17
|
+
|
|
16
18
|
def self.ruby_os_identifier
|
|
17
19
|
RbConfig::CONFIG['target_os']
|
|
18
20
|
end
|
|
19
21
|
|
|
22
|
+
def self.os_distribution
|
|
23
|
+
case
|
|
24
|
+
when darwin? then :darwin
|
|
25
|
+
when linux? then :linux
|
|
26
|
+
when bsd? then :bsd
|
|
27
|
+
when windows? then :windows
|
|
28
|
+
else ruby_os_identifier
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.windows?
|
|
33
|
+
!!(ruby_os_identifier[/mingw|mswin/i])
|
|
34
|
+
end
|
|
35
|
+
|
|
20
36
|
def self.darwin?
|
|
21
37
|
!!(ruby_os_identifier =~ /darwin/i)
|
|
22
38
|
end
|
|
@@ -172,15 +188,39 @@ module NewRelic
|
|
|
172
188
|
proc_try_read('/proc/version')
|
|
173
189
|
end
|
|
174
190
|
|
|
191
|
+
# When operating within a Docker container, attempt to obtain the
|
|
192
|
+
# container id.
|
|
193
|
+
#
|
|
194
|
+
# First look for `/proc/self/mountinfo` to exist on disk to signify
|
|
195
|
+
# cgroups v2. If that file exists, read it and expect it to contain one
|
|
196
|
+
# or more "/docker/containers/<container_id>/" lines from which the
|
|
197
|
+
# container id can be gleaned.
|
|
198
|
+
#
|
|
199
|
+
# Next look for `/proc/self/cgroup` to exist on disk to signify cgroup v1.
|
|
200
|
+
# If that file exists, read it and parse the "cpu" group info in the hope
|
|
201
|
+
# of finding a 64 character container id value.
|
|
202
|
+
#
|
|
203
|
+
# For non-cgroups based containers, use a `nil` value for the container
|
|
204
|
+
# id without generating any warnings or errors.
|
|
175
205
|
def self.docker_container_id
|
|
176
206
|
return unless ruby_os_identifier.include?('linux')
|
|
177
207
|
|
|
208
|
+
cgroupsv2_based_id = docker_container_id_for_cgroupsv2
|
|
209
|
+
return cgroupsv2_based_id if cgroupsv2_based_id
|
|
210
|
+
|
|
178
211
|
cgroup_info = proc_try_read('/proc/self/cgroup')
|
|
179
212
|
return unless cgroup_info
|
|
180
213
|
|
|
181
214
|
parse_docker_container_id(cgroup_info)
|
|
182
215
|
end
|
|
183
216
|
|
|
217
|
+
def self.docker_container_id_for_cgroupsv2
|
|
218
|
+
mountinfo = proc_try_read('/proc/self/mountinfo')
|
|
219
|
+
return unless mountinfo
|
|
220
|
+
|
|
221
|
+
Regexp.last_match(1) if mountinfo =~ DOCKER_CGROUPS_V2_PATTERN
|
|
222
|
+
end
|
|
223
|
+
|
|
184
224
|
def self.parse_docker_container_id(cgroup_info)
|
|
185
225
|
cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu']
|
|
186
226
|
return unless cpu_cgroup
|
|
@@ -9,8 +9,7 @@ module NewRelic
|
|
|
9
9
|
def self.create(label, &blk)
|
|
10
10
|
::NewRelic::Agent.logger.debug("Creating AgentThread: #{label}")
|
|
11
11
|
wrapped_blk = proc do
|
|
12
|
-
if
|
|
13
|
-
txn = ::Thread.current[:newrelic_tracer_state].current_transaction
|
|
12
|
+
if (txn = ::NewRelic::ThreadLocalStorage[:newrelic_tracer_state]&.current_transaction)
|
|
14
13
|
::NewRelic::Agent.logger.warn("AgentThread created with current transaction #{txn.best_name}")
|
|
15
14
|
end
|
|
16
15
|
begin
|
|
@@ -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
|
|
@@ -66,9 +66,10 @@ module NewRelic
|
|
|
66
66
|
#
|
|
67
67
|
# @api public
|
|
68
68
|
def transaction_sampled?
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
txn = current_transaction
|
|
70
|
+
return false unless txn
|
|
71
|
+
|
|
72
|
+
txn.sampled?
|
|
72
73
|
end
|
|
73
74
|
alias_method :sampled?, :transaction_sampled?
|
|
74
75
|
|
|
@@ -246,7 +247,7 @@ module NewRelic
|
|
|
246
247
|
log_error('start_segment', exception)
|
|
247
248
|
end
|
|
248
249
|
|
|
249
|
-
UNKNOWN =
|
|
250
|
+
UNKNOWN = NewRelic::UNKNOWN
|
|
250
251
|
OTHER = 'other'.freeze
|
|
251
252
|
|
|
252
253
|
# Creates and starts a datastore segment used to time
|
|
@@ -356,9 +357,7 @@ module NewRelic
|
|
|
356
357
|
yield
|
|
357
358
|
rescue => exception
|
|
358
359
|
# needs else branch coverage
|
|
359
|
-
|
|
360
|
-
segment.notice_error(exception)
|
|
361
|
-
end
|
|
360
|
+
segment.notice_error(exception) if segment&.is_a?(Transaction::AbstractSegment)
|
|
362
361
|
raise
|
|
363
362
|
end
|
|
364
363
|
|
|
@@ -393,11 +392,11 @@ module NewRelic
|
|
|
393
392
|
#
|
|
394
393
|
# If ever exposed, this requires additional synchronization
|
|
395
394
|
def state_for(thread)
|
|
396
|
-
state = thread
|
|
395
|
+
state = ThreadLocalStorage.get(thread, :newrelic_tracer_state)
|
|
397
396
|
|
|
398
397
|
if state.nil?
|
|
399
398
|
state = Tracer::State.new
|
|
400
|
-
thread
|
|
399
|
+
ThreadLocalStorage.set(thread, :newrelic_tracer_state, state)
|
|
401
400
|
end
|
|
402
401
|
|
|
403
402
|
state
|
|
@@ -406,7 +405,7 @@ module NewRelic
|
|
|
406
405
|
alias_method :tl_state_for, :state_for
|
|
407
406
|
|
|
408
407
|
def clear_state
|
|
409
|
-
|
|
408
|
+
ThreadLocalStorage[:newrelic_tracer_state] = nil
|
|
410
409
|
end
|
|
411
410
|
|
|
412
411
|
alias_method :tl_clear, :clear_state
|
|
@@ -419,16 +418,17 @@ module NewRelic
|
|
|
419
418
|
NewRelic::Agent.config[:'instrumentation.thread.tracing']
|
|
420
419
|
end
|
|
421
420
|
|
|
422
|
-
def thread_block_with_current_transaction(
|
|
421
|
+
def thread_block_with_current_transaction(segment_name: nil, parent: nil, &block)
|
|
423
422
|
parent ||= current_segment
|
|
424
|
-
current_txn =
|
|
425
|
-
proc do
|
|
423
|
+
current_txn = ThreadLocalStorage[:newrelic_tracer_state]&.current_transaction if ThreadLocalStorage[:newrelic_tracer_state]&.is_execution_traced?
|
|
424
|
+
proc do |*args|
|
|
426
425
|
begin
|
|
427
|
-
if current_txn
|
|
426
|
+
if current_txn && !current_txn.finished?
|
|
428
427
|
NewRelic::Agent::Tracer.state.current_transaction = current_txn
|
|
428
|
+
ThreadLocalStorage[:newrelic_thread_span_parent] = parent
|
|
429
429
|
current_txn.async = true
|
|
430
|
-
segment_name
|
|
431
|
-
segment = NewRelic::Agent::Tracer.start_segment(name: segment_name, parent: parent)
|
|
430
|
+
segment_name = "#{segment_name}/Thread#{::Thread.current.object_id}/Fiber#{::Fiber.current.object_id}" if NewRelic::Agent.config[:'thread_ids_enabled']
|
|
431
|
+
segment = NewRelic::Agent::Tracer.start_segment(name: segment_name, parent: parent) if segment_name
|
|
432
432
|
end
|
|
433
433
|
NewRelic::Agent::Tracer.capture_segment_error(segment) do
|
|
434
434
|
yield(*args)
|
|
@@ -2,7 +2,6 @@
|
|
|
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 'new_relic/agent/range_extensions'
|
|
6
5
|
require 'new_relic/agent/guid_generator'
|
|
7
6
|
|
|
8
7
|
module NewRelic
|
|
@@ -20,14 +19,18 @@ module NewRelic
|
|
|
20
19
|
# after its parent. We will use the optimized exclusive duration
|
|
21
20
|
# calculation in all other cases.
|
|
22
21
|
#
|
|
23
|
-
attr_reader :start_time, :end_time, :duration, :exclusive_duration, :guid, :starting_segment_key
|
|
24
|
-
attr_accessor :name, :parent, :children_time, :transaction, :transaction_name
|
|
22
|
+
attr_reader :start_time, :end_time, :duration, :exclusive_duration, :guid, :starting_segment_key, :thread_id
|
|
23
|
+
attr_accessor :name, :parent, :children_time, :transaction, :transaction_name, :llm_event
|
|
25
24
|
attr_writer :record_metrics, :record_scoped_metric, :record_on_finish
|
|
26
25
|
attr_reader :noticed_error
|
|
27
26
|
|
|
27
|
+
CALLBACK = :@callback
|
|
28
|
+
SEGMENT = 'segment'
|
|
29
|
+
|
|
28
30
|
def initialize(name = nil, start_time = nil)
|
|
29
31
|
@name = name
|
|
30
32
|
@starting_segment_key = NewRelic::Agent::Tracer.current_segment_key
|
|
33
|
+
@thread_id = Thread.current.object_id
|
|
31
34
|
@transaction_name = nil
|
|
32
35
|
@transaction = nil
|
|
33
36
|
@guid = NewRelic::Agent::GuidGenerator.generate_guid
|
|
@@ -50,6 +53,7 @@ module NewRelic
|
|
|
50
53
|
@code_function = nil
|
|
51
54
|
@code_lineno = nil
|
|
52
55
|
@code_namespace = nil
|
|
56
|
+
invoke_callback
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
def start
|
|
@@ -105,38 +109,6 @@ module NewRelic
|
|
|
105
109
|
@start_time.to_f..@end_time.to_f
|
|
106
110
|
end
|
|
107
111
|
|
|
108
|
-
def timings_overlap?(timing1, timing2)
|
|
109
|
-
(timing1.first >= timing2.first && timing1.first <= timing2.last) ||
|
|
110
|
-
(timing2.first >= timing1.first && timing2.first <= timing1.last)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def merge_timings(timing1, timing2)
|
|
114
|
-
[([timing1.first, timing2.first].min),
|
|
115
|
-
([timing1.last, timing2.last].max)]
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# @children_timings is an array of array, with each inner array
|
|
119
|
-
# holding exactly 2 values, a child segment's start time and finish
|
|
120
|
-
# time (in that order). When it's time to record, these timings are
|
|
121
|
-
# converted into an array of range objects (using the same start and
|
|
122
|
-
# end values as the original array). Any two range objects that
|
|
123
|
-
# intersect and merged into a larger range. This checking for a
|
|
124
|
-
# intersections and merging of ranges is expensive, so the operation
|
|
125
|
-
# is only done at recording time.
|
|
126
|
-
def children_time_ranges
|
|
127
|
-
@children_time_ranges ||= begin
|
|
128
|
-
overlapped = @children_timings.each_with_object([]) do |timing, timings|
|
|
129
|
-
i = timings.index { |t| timings_overlap?(t, timing) }
|
|
130
|
-
if i
|
|
131
|
-
timings[i] = merge_timings(timing, timings[i])
|
|
132
|
-
else
|
|
133
|
-
timings << timing
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
overlapped.map { |t| Range.new(t.first, t.last) }
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
|
|
140
112
|
def children_time_ranges?
|
|
141
113
|
!@children_timings.empty?
|
|
142
114
|
end
|
|
@@ -299,12 +271,6 @@ module NewRelic
|
|
|
299
271
|
end
|
|
300
272
|
|
|
301
273
|
def record_exclusive_duration
|
|
302
|
-
overlapping_duration = if children_time_ranges?
|
|
303
|
-
RangeExtensions.compute_overlap(time_range, children_time_ranges)
|
|
304
|
-
else
|
|
305
|
-
0.0
|
|
306
|
-
end
|
|
307
|
-
|
|
308
274
|
@exclusive_duration = duration - children_time - overlapping_duration
|
|
309
275
|
transaction.total_time += @exclusive_duration
|
|
310
276
|
params[:exclusive_duration_millis] = @exclusive_duration * 1000 if transaction.async?
|
|
@@ -314,6 +280,51 @@ module NewRelic
|
|
|
314
280
|
transaction.metrics
|
|
315
281
|
end
|
|
316
282
|
|
|
283
|
+
def ranges_intersect?(r1, r2)
|
|
284
|
+
r1.begin > r2.begin ? r2.cover?(r1.begin) : r1.cover?(r2.begin)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def range_overlap(range)
|
|
288
|
+
return 0.0 unless ranges_intersect?(range, time_range)
|
|
289
|
+
|
|
290
|
+
[range.end, time_range.end].min - [range.begin, time_range.begin].max
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Child segments operating concurrently with this segment may have
|
|
294
|
+
# start and end times that overlap with this segment's own times. The
|
|
295
|
+
# amount of overlap needs to be removed from the `children_time` total
|
|
296
|
+
# when calculating an `@exclusive_duration` value to be added to the
|
|
297
|
+
# transaction's total time.
|
|
298
|
+
#
|
|
299
|
+
# If there aren't any child segments, return 0.0. Otherwise, take the
|
|
300
|
+
# `@children_timings` array of arrays (each array holds a child
|
|
301
|
+
# segment's start time and end time), sort it by the first elements
|
|
302
|
+
# (start times), and use the start and finish times to create Range
|
|
303
|
+
# objects. Combine all of the child segment ranges that overlap with
|
|
304
|
+
# one another into new bigger ranges. Then take those bigger ranges
|
|
305
|
+
# and calculate how much overlap there is between them and this
|
|
306
|
+
# segment's own time range. Keep a running sum of all of the overlap
|
|
307
|
+
# amounts and then return it.
|
|
308
|
+
def overlapping_duration
|
|
309
|
+
sum = 0.0
|
|
310
|
+
return sum unless children_time_ranges?
|
|
311
|
+
|
|
312
|
+
@children_timings.sort_by!(&:first)
|
|
313
|
+
range = Range.new(*@children_timings.first)
|
|
314
|
+
(1..(@children_timings.size - 1)).each do |i|
|
|
315
|
+
possible = Range.new(*@children_timings[i])
|
|
316
|
+
|
|
317
|
+
if ranges_intersect?(range, possible)
|
|
318
|
+
range = range.begin..possible.end
|
|
319
|
+
else
|
|
320
|
+
sum += range_overlap(range)
|
|
321
|
+
range = possible
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
sum += range_overlap(range)
|
|
326
|
+
end
|
|
327
|
+
|
|
317
328
|
def transaction_state
|
|
318
329
|
@transaction_state ||= if @transaction
|
|
319
330
|
transaction.state
|
|
@@ -321,6 +332,57 @@ module NewRelic
|
|
|
321
332
|
Tracer.state
|
|
322
333
|
end
|
|
323
334
|
end
|
|
335
|
+
|
|
336
|
+
# for segment callback usage info, see self.set_segment_callback
|
|
337
|
+
def invoke_callback
|
|
338
|
+
return unless self.class.instance_variable_defined?(CALLBACK)
|
|
339
|
+
|
|
340
|
+
NewRelic::Agent.logger.debug("Invoking callback for #{self.class.name}...")
|
|
341
|
+
self.class.instance_variable_get(CALLBACK).call
|
|
342
|
+
rescue Exception => e
|
|
343
|
+
NewRelic::Agent.logger.error("Error encountered while invoking callback for #{self.class.name}: " +
|
|
344
|
+
"#{e.class} - #{e.message}")
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Setting and invoking a segment callback
|
|
348
|
+
# =======================================
|
|
349
|
+
# Each individual segment class such as `ExternalRequestSegment` allows
|
|
350
|
+
# for exactly one instance of a `Proc` (meaning a proc or lambda) to be
|
|
351
|
+
# set as a callback. A callback can be set on a segment class by calling
|
|
352
|
+
# `.set_segment_callback` with a proc or lambda as the only argument.
|
|
353
|
+
# If set, the callback will be invoked with `#call` at segment class
|
|
354
|
+
# initialization time.
|
|
355
|
+
#
|
|
356
|
+
# Example usage:
|
|
357
|
+
# callback = -> { puts 'Hello, World! }
|
|
358
|
+
# ExternalRequestSegment.set_segment_callback(callback)
|
|
359
|
+
# ExternalRequestSegment.new(library, uri, procedure)
|
|
360
|
+
#
|
|
361
|
+
# A callback set on a segment class will only be called when that
|
|
362
|
+
# specific segment class is initialized. Other segment classes will not
|
|
363
|
+
# be impacted.
|
|
364
|
+
#
|
|
365
|
+
# Great caution should be taken in the defining of the callback block
|
|
366
|
+
# to not have the block perform anything too time consuming or resource
|
|
367
|
+
# intensive in order to keep the New Relic Ruby agent operating
|
|
368
|
+
# normally.
|
|
369
|
+
#
|
|
370
|
+
# Given that callbacks are user defined, they must be set entirely at
|
|
371
|
+
# the user's own risk. It is recommended that each callback use
|
|
372
|
+
# conditional logic that only performs work for certain qualified
|
|
373
|
+
# segments. It is recommended that each callback be thoroughly tested
|
|
374
|
+
# in non-production environments before being introduced to production
|
|
375
|
+
# environments.
|
|
376
|
+
def self.set_segment_callback(callback_proc)
|
|
377
|
+
unless callback_proc.is_a?(Proc)
|
|
378
|
+
NewRelic::Agent.logger.error("#{self}.#{__method__}: expected an argument of type Proc, " \
|
|
379
|
+
"got #{callback_proc.class}")
|
|
380
|
+
return
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
NewRelic::Agent.record_api_supportability_metric(:set_segment_callback)
|
|
384
|
+
instance_variable_set(CALLBACK, callback_proc)
|
|
385
|
+
end
|
|
324
386
|
end
|
|
325
387
|
end
|
|
326
388
|
end
|
|
@@ -11,7 +11,7 @@ module NewRelic
|
|
|
11
11
|
module Agent
|
|
12
12
|
class Transaction
|
|
13
13
|
class DatastoreSegment < Segment
|
|
14
|
-
UNKNOWN =
|
|
14
|
+
UNKNOWN = NewRelic::UNKNOWN_LOWER
|
|
15
15
|
|
|
16
16
|
attr_reader :product, :operation, :collection, :sql_statement, :nosql_statement, :host, :port_path_or_id
|
|
17
17
|
attr_accessor :database_name, :record_sql
|
|
@@ -35,7 +35,7 @@ module NewRelic
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def caller_transport_type
|
|
38
|
-
@caller_transport_type ||=
|
|
38
|
+
@caller_transport_type ||= NewRelic::UNKNOWN
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def accept_transport_type_from_api(value)
|
|
@@ -127,7 +127,7 @@ module NewRelic
|
|
|
127
127
|
def consume_message_synthetics_headers(headers)
|
|
128
128
|
synthetics_header = headers[CrossAppTracing::NR_MESSAGE_BROKER_SYNTHETICS_HEADER]
|
|
129
129
|
if synthetics_header and
|
|
130
|
-
incoming_payload = ::JSON.
|
|
130
|
+
incoming_payload = ::JSON.parse(deobfuscate(synthetics_header)) and
|
|
131
131
|
SyntheticsMonitor.is_valid_payload?(incoming_payload) and
|
|
132
132
|
SyntheticsMonitor.is_supported_version?(incoming_payload) and
|
|
133
133
|
SyntheticsMonitor.is_trusted?(incoming_payload)
|
|
@@ -167,7 +167,7 @@ module NewRelic
|
|
|
167
167
|
return unless CrossAppTracing.trusted_valid_cross_app_id?(decoded_id)
|
|
168
168
|
|
|
169
169
|
txn_header = headers[CrossAppTracing::NR_MESSAGE_BROKER_TXN_HEADER]
|
|
170
|
-
txn_info = ::JSON.
|
|
170
|
+
txn_info = ::JSON.parse(deobfuscate(txn_header))
|
|
171
171
|
payload = CrossAppPayload.new(decoded_id, transaction, txn_info)
|
|
172
172
|
|
|
173
173
|
@cross_app_payload = payload
|
|
@@ -119,14 +119,13 @@ module NewRelic
|
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
def check_required_fields_present(payload)
|
|
122
|
-
if
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
!payload.timestamp.nil?
|
|
122
|
+
if !payload.version.nil? &&
|
|
123
|
+
!payload.parent_account_id.nil? &&
|
|
124
|
+
!payload.parent_app_id.nil? &&
|
|
125
|
+
!payload.parent_type.nil? &&
|
|
126
|
+
(!payload.transaction_id.nil? || !payload.id.nil?) &&
|
|
127
|
+
!payload.trace_id.nil? &&
|
|
128
|
+
!payload.timestamp.nil?
|
|
130
129
|
|
|
131
130
|
true
|
|
132
131
|
else
|
|
@@ -14,6 +14,7 @@ module NewRelic
|
|
|
14
14
|
# @api public
|
|
15
15
|
class ExternalRequestSegment < Segment
|
|
16
16
|
NR_SYNTHETICS_HEADER = 'X-NewRelic-Synthetics'
|
|
17
|
+
NR_SYNTHETICS_INFO_HEADER = 'X-NewRelic-Synthetics-Info'
|
|
17
18
|
APP_DATA_KEY = 'NewRelicAppData'
|
|
18
19
|
|
|
19
20
|
EXTERNAL_ALL = 'External/all'
|
|
@@ -22,7 +23,6 @@ module NewRelic
|
|
|
22
23
|
MISSING_STATUS_CODE = 'MissingHTTPStatusCode'
|
|
23
24
|
|
|
24
25
|
attr_reader :library, :uri, :procedure, :http_status_code
|
|
25
|
-
attr_writer :record_agent_attributes
|
|
26
26
|
|
|
27
27
|
def initialize(library, uri, procedure, start_time = nil) # :nodoc:
|
|
28
28
|
@library = library
|
|
@@ -31,7 +31,6 @@ module NewRelic
|
|
|
31
31
|
@host_header = nil
|
|
32
32
|
@app_data = nil
|
|
33
33
|
@http_status_code = nil
|
|
34
|
-
@record_agent_attributes = false
|
|
35
34
|
super(nil, nil, start_time)
|
|
36
35
|
end
|
|
37
36
|
|
|
@@ -43,14 +42,6 @@ module NewRelic
|
|
|
43
42
|
@host_header || uri.host
|
|
44
43
|
end
|
|
45
44
|
|
|
46
|
-
# By default external request segments only have errors and the http
|
|
47
|
-
# url recorded as agent attributes. To have all the agent attributes
|
|
48
|
-
# recorded, use the attr_writer like so `segment.record_agent_attributes = true`
|
|
49
|
-
# See: SpanEventPrimitive#for_external_request_segment
|
|
50
|
-
def record_agent_attributes?
|
|
51
|
-
@record_agent_attributes
|
|
52
|
-
end
|
|
53
|
-
|
|
54
45
|
# This method adds New Relic request headers to a given request made to an
|
|
55
46
|
# external API and checks to see if a host header is used for the request.
|
|
56
47
|
# If a host header is used, it updates the segment name to match the host
|
|
@@ -63,7 +54,8 @@ module NewRelic
|
|
|
63
54
|
def add_request_headers(request)
|
|
64
55
|
process_host_header(request)
|
|
65
56
|
synthetics_header = transaction&.raw_synthetics_header
|
|
66
|
-
|
|
57
|
+
synthetics_info_header = transaction&.raw_synthetics_info_header
|
|
58
|
+
insert_synthetics_header(request, synthetics_header, synthetics_info_header) if synthetics_header
|
|
67
59
|
|
|
68
60
|
return unless record_metrics?
|
|
69
61
|
|
|
@@ -207,8 +199,9 @@ module NewRelic
|
|
|
207
199
|
end
|
|
208
200
|
end
|
|
209
201
|
|
|
210
|
-
def insert_synthetics_header(request, header)
|
|
202
|
+
def insert_synthetics_header(request, header, info)
|
|
211
203
|
request[NR_SYNTHETICS_HEADER] = header
|
|
204
|
+
request[NR_SYNTHETICS_INFO_HEADER] = info if info
|
|
212
205
|
end
|
|
213
206
|
|
|
214
207
|
def segment_complete
|
|
@@ -15,14 +15,15 @@ module NewRelic
|
|
|
15
15
|
PRODUCE = 'Produce'.freeze
|
|
16
16
|
QUEUE = 'Queue'.freeze
|
|
17
17
|
PURGE = 'Purge'.freeze
|
|
18
|
-
|
|
18
|
+
STREAM = 'Stream'.freeze
|
|
19
19
|
TEMP = 'Temp'.freeze
|
|
20
20
|
TOPIC = 'Topic'.freeze
|
|
21
|
-
UNKNOWN =
|
|
21
|
+
UNKNOWN = NewRelic::UNKNOWN
|
|
22
22
|
|
|
23
23
|
DESTINATION_TYPES = [
|
|
24
24
|
:exchange,
|
|
25
25
|
:queue,
|
|
26
|
+
:stream,
|
|
26
27
|
:topic,
|
|
27
28
|
:temporary_queue,
|
|
28
29
|
:temporary_topic,
|
|
@@ -38,6 +39,7 @@ module NewRelic
|
|
|
38
39
|
TYPES = {
|
|
39
40
|
exchange: EXCHANGE,
|
|
40
41
|
temporary_queue: QUEUE,
|
|
42
|
+
stream: STREAM,
|
|
41
43
|
queue: QUEUE,
|
|
42
44
|
temporary_topic: TOPIC,
|
|
43
45
|
topic: TOPIC,
|
|
@@ -73,7 +75,7 @@ module NewRelic
|
|
|
73
75
|
return @name if @name
|
|
74
76
|
|
|
75
77
|
@name = METRIC_PREFIX + library
|
|
76
|
-
@name << SLASH << TYPES[destination_type] << SLASH << ACTIONS[action] << SLASH
|
|
78
|
+
@name << NewRelic::SLASH << TYPES[destination_type] << NewRelic::SLASH << ACTIONS[action] << NewRelic::SLASH
|
|
77
79
|
|
|
78
80
|
if destination_type == :temporary_queue || destination_type == :temporary_topic
|
|
79
81
|
@name << TEMP
|