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
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
require 'new_relic/agent/event_aggregator'
|
|
6
6
|
require 'new_relic/agent/log_priority'
|
|
7
|
+
require 'new_relic/agent/log_event_attributes'
|
|
7
8
|
|
|
8
9
|
module NewRelic
|
|
9
10
|
module Agent
|
|
@@ -19,10 +20,12 @@ module NewRelic
|
|
|
19
20
|
DROPPED_METRIC = 'Logging/Forwarding/Dropped'.freeze
|
|
20
21
|
SEEN_METRIC = 'Supportability/Logging/Forwarding/Seen'.freeze
|
|
21
22
|
SENT_METRIC = 'Supportability/Logging/Forwarding/Sent'.freeze
|
|
22
|
-
|
|
23
|
+
LOGGER_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Ruby/Logger/%s'.freeze
|
|
24
|
+
LOGSTASHER_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Ruby/LogStasher/%s'.freeze
|
|
23
25
|
METRICS_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Metrics/Ruby/%s'.freeze
|
|
24
26
|
FORWARDING_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Forwarding/Ruby/%s'.freeze
|
|
25
27
|
DECORATING_SUPPORTABILITY_FORMAT = 'Supportability/Logging/LocalDecorating/Ruby/%s'.freeze
|
|
28
|
+
LABELS_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Labels/Ruby/%s'.freeze
|
|
26
29
|
MAX_BYTES = 32768 # 32 * 1024 bytes (32 kibibytes)
|
|
27
30
|
|
|
28
31
|
named :LogEventAggregator
|
|
@@ -36,6 +39,11 @@ module NewRelic
|
|
|
36
39
|
METRICS_ENABLED_KEY = :'application_logging.metrics.enabled'
|
|
37
40
|
FORWARDING_ENABLED_KEY = :'application_logging.forwarding.enabled'
|
|
38
41
|
DECORATING_ENABLED_KEY = :'application_logging.local_decorating.enabled'
|
|
42
|
+
LABELS_ENABLED_KEY = :'application_logging.forwarding.labels.enabled'
|
|
43
|
+
LOG_LEVEL_KEY = :'application_logging.forwarding.log_level'
|
|
44
|
+
CUSTOM_ATTRIBUTES_KEY = :'application_logging.forwarding.custom_attributes'
|
|
45
|
+
|
|
46
|
+
attr_reader :attributes
|
|
39
47
|
|
|
40
48
|
def initialize(events)
|
|
41
49
|
super(events)
|
|
@@ -44,6 +52,8 @@ module NewRelic
|
|
|
44
52
|
@seen_by_severity = Hash.new(0)
|
|
45
53
|
@high_security = NewRelic::Agent.config[:high_security]
|
|
46
54
|
@instrumentation_logger_enabled = NewRelic::Agent::Instrumentation::Logger.enabled?
|
|
55
|
+
@attributes = NewRelic::Agent::LogEventAttributes.new
|
|
56
|
+
|
|
47
57
|
register_for_done_configuring(events)
|
|
48
58
|
end
|
|
49
59
|
|
|
@@ -52,37 +62,71 @@ module NewRelic
|
|
|
52
62
|
end
|
|
53
63
|
|
|
54
64
|
def record(formatted_message, severity)
|
|
55
|
-
return unless
|
|
65
|
+
return unless logger_enabled?
|
|
56
66
|
|
|
57
67
|
severity = 'UNKNOWN' if severity.nil? || severity.empty?
|
|
68
|
+
increment_event_counters(severity)
|
|
69
|
+
|
|
70
|
+
return if formatted_message.nil? || formatted_message.empty?
|
|
71
|
+
return unless monitoring_conditions_met?(severity)
|
|
72
|
+
|
|
73
|
+
txn = NewRelic::Agent::Transaction.tl_current
|
|
74
|
+
priority = LogPriority.priority_for(txn)
|
|
75
|
+
|
|
76
|
+
return txn.add_log_event(create_event(priority, formatted_message, severity)) if txn
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
@
|
|
61
|
-
|
|
62
|
-
@seen_by_severity[severity] += 1
|
|
78
|
+
@lock.synchronize do
|
|
79
|
+
@buffer.append(priority: priority) do
|
|
80
|
+
create_event(priority, formatted_message, severity)
|
|
63
81
|
end
|
|
64
82
|
end
|
|
83
|
+
rescue
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
65
86
|
|
|
66
|
-
|
|
67
|
-
return unless
|
|
68
|
-
|
|
87
|
+
def record_logstasher_event(log)
|
|
88
|
+
return unless logstasher_enabled?
|
|
89
|
+
|
|
90
|
+
# LogStasher logs do not inherently include a message key, so most logs are recorded.
|
|
91
|
+
# But when the key exists, we should not record the log if the message value is nil or empty.
|
|
92
|
+
return if log.key?('message') && (log['message'].nil? || log['message'].empty?)
|
|
93
|
+
|
|
94
|
+
severity = determine_severity(log)
|
|
95
|
+
increment_event_counters(severity)
|
|
96
|
+
|
|
97
|
+
return unless monitoring_conditions_met?(severity)
|
|
69
98
|
|
|
70
99
|
txn = NewRelic::Agent::Transaction.tl_current
|
|
71
100
|
priority = LogPriority.priority_for(txn)
|
|
72
101
|
|
|
73
|
-
if txn
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
create_event(priority, formatted_message, severity)
|
|
79
|
-
end
|
|
102
|
+
return txn.add_log_event(create_logstasher_event(priority, severity, log)) if txn
|
|
103
|
+
|
|
104
|
+
@lock.synchronize do
|
|
105
|
+
@buffer.append(priority: priority) do
|
|
106
|
+
create_logstasher_event(priority, severity, log)
|
|
80
107
|
end
|
|
81
108
|
end
|
|
82
109
|
rescue
|
|
83
110
|
nil
|
|
84
111
|
end
|
|
85
112
|
|
|
113
|
+
def monitoring_conditions_met?(severity)
|
|
114
|
+
!severity_too_low?(severity) && NewRelic::Agent.config[FORWARDING_ENABLED_KEY] && !@high_security
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def determine_severity(log)
|
|
118
|
+
log['level'] ? log['level'].to_s.upcase : 'UNKNOWN'
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def increment_event_counters(severity)
|
|
122
|
+
return unless NewRelic::Agent.config[METRICS_ENABLED_KEY]
|
|
123
|
+
|
|
124
|
+
@counter_lock.synchronize do
|
|
125
|
+
@seen += 1
|
|
126
|
+
@seen_by_severity[severity] += 1
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
86
130
|
def record_batch(txn, logs)
|
|
87
131
|
# Ensure we have the same shared priority
|
|
88
132
|
priority = LogPriority.priority_for(txn)
|
|
@@ -97,15 +141,17 @@ module NewRelic
|
|
|
97
141
|
end
|
|
98
142
|
end
|
|
99
143
|
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
event = LinkingMetadata.append_trace_linking_metadata({
|
|
144
|
+
def add_event_metadata(formatted_message, severity)
|
|
145
|
+
metadata = {
|
|
104
146
|
LEVEL_KEY => severity,
|
|
105
|
-
MESSAGE_KEY => formatted_message,
|
|
106
147
|
TIMESTAMP_KEY => Process.clock_gettime(Process::CLOCK_REALTIME) * 1000
|
|
107
|
-
}
|
|
148
|
+
}
|
|
149
|
+
metadata[MESSAGE_KEY] = formatted_message unless formatted_message.nil?
|
|
150
|
+
|
|
151
|
+
LinkingMetadata.append_trace_linking_metadata(metadata)
|
|
152
|
+
end
|
|
108
153
|
|
|
154
|
+
def create_prioritized_event(priority, event)
|
|
109
155
|
[
|
|
110
156
|
{
|
|
111
157
|
PrioritySampledBuffer::PRIORITY_KEY => priority
|
|
@@ -114,6 +160,39 @@ module NewRelic
|
|
|
114
160
|
]
|
|
115
161
|
end
|
|
116
162
|
|
|
163
|
+
def create_event(priority, formatted_message, severity)
|
|
164
|
+
formatted_message = truncate_message(formatted_message)
|
|
165
|
+
event = add_event_metadata(formatted_message, severity)
|
|
166
|
+
|
|
167
|
+
create_prioritized_event(priority, event)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def create_logstasher_event(priority, severity, log)
|
|
171
|
+
formatted_message = log['message'] ? truncate_message(log['message']) : nil
|
|
172
|
+
event = add_event_metadata(formatted_message, severity)
|
|
173
|
+
add_logstasher_event_attributes(event, log)
|
|
174
|
+
|
|
175
|
+
create_prioritized_event(priority, event)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def add_logstasher_event_attributes(event, log)
|
|
179
|
+
log_copy = log.dup
|
|
180
|
+
# Delete previously reported attributes
|
|
181
|
+
log_copy.delete('message')
|
|
182
|
+
log_copy.delete('level')
|
|
183
|
+
log_copy.delete('@timestamp')
|
|
184
|
+
|
|
185
|
+
event['attributes'] = log_copy
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def add_custom_attributes(custom_attributes)
|
|
189
|
+
attributes.add_custom_attributes(custom_attributes)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def labels
|
|
193
|
+
@labels ||= create_labels
|
|
194
|
+
end
|
|
195
|
+
|
|
117
196
|
# Because our transmission format (MELT) is different than historical
|
|
118
197
|
# agent payloads, extract the munging here to keep the service focused
|
|
119
198
|
# on the general harvest + transmit instead of the format.
|
|
@@ -129,6 +208,9 @@ module NewRelic
|
|
|
129
208
|
# To save on unnecessary data transmission, trim the entity.type
|
|
130
209
|
# sent by classic logs-in-context
|
|
131
210
|
common_attributes.delete(ENTITY_TYPE_KEY)
|
|
211
|
+
aggregator = NewRelic::Agent.agent.log_event_aggregator
|
|
212
|
+
common_attributes.merge!(aggregator.attributes.custom_attributes)
|
|
213
|
+
common_attributes.merge!(aggregator.labels)
|
|
132
214
|
|
|
133
215
|
_, items = data
|
|
134
216
|
payload = [{
|
|
@@ -149,13 +231,18 @@ module NewRelic
|
|
|
149
231
|
@seen = 0
|
|
150
232
|
@seen_by_severity.clear
|
|
151
233
|
end
|
|
234
|
+
|
|
152
235
|
super
|
|
153
236
|
end
|
|
154
237
|
|
|
155
|
-
def
|
|
238
|
+
def logger_enabled?
|
|
156
239
|
@enabled && @instrumentation_logger_enabled
|
|
157
240
|
end
|
|
158
241
|
|
|
242
|
+
def logstasher_enabled?
|
|
243
|
+
@enabled && NewRelic::Agent::Instrumentation::LogStasher.enabled?
|
|
244
|
+
end
|
|
245
|
+
|
|
159
246
|
private
|
|
160
247
|
|
|
161
248
|
# We record once-per-connect metrics for enabled/disabled state at the
|
|
@@ -163,11 +250,14 @@ module NewRelic
|
|
|
163
250
|
def register_for_done_configuring(events)
|
|
164
251
|
events.subscribe(:server_source_configuration_added) do
|
|
165
252
|
@high_security = NewRelic::Agent.config[:high_security]
|
|
166
|
-
|
|
167
|
-
record_configuration_metric(
|
|
253
|
+
record_configuration_metric(LOGGER_SUPPORTABILITY_FORMAT, OVERALL_ENABLED_KEY)
|
|
254
|
+
record_configuration_metric(LOGSTASHER_SUPPORTABILITY_FORMAT, OVERALL_ENABLED_KEY)
|
|
168
255
|
record_configuration_metric(METRICS_SUPPORTABILITY_FORMAT, METRICS_ENABLED_KEY)
|
|
169
256
|
record_configuration_metric(FORWARDING_SUPPORTABILITY_FORMAT, FORWARDING_ENABLED_KEY)
|
|
170
257
|
record_configuration_metric(DECORATING_SUPPORTABILITY_FORMAT, DECORATING_ENABLED_KEY)
|
|
258
|
+
record_configuration_metric(LABELS_SUPPORTABILITY_FORMAT, LABELS_ENABLED_KEY)
|
|
259
|
+
|
|
260
|
+
add_custom_attributes(NewRelic::Agent.config[CUSTOM_ATTRIBUTES_KEY])
|
|
171
261
|
end
|
|
172
262
|
end
|
|
173
263
|
|
|
@@ -191,7 +281,7 @@ module NewRelic
|
|
|
191
281
|
# these until harvest before recording them
|
|
192
282
|
def record_customer_metrics
|
|
193
283
|
return unless enabled?
|
|
194
|
-
return unless NewRelic::Agent.config[
|
|
284
|
+
return unless NewRelic::Agent.config[METRICS_ENABLED_KEY]
|
|
195
285
|
|
|
196
286
|
@counter_lock.synchronize do
|
|
197
287
|
return unless @seen > 0
|
|
@@ -230,6 +320,39 @@ module NewRelic
|
|
|
230
320
|
|
|
231
321
|
message.byteslice(0...MAX_BYTES)
|
|
232
322
|
end
|
|
323
|
+
|
|
324
|
+
def configured_log_level_constant
|
|
325
|
+
format_log_level_constant(NewRelic::Agent.config[LOG_LEVEL_KEY])
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def format_log_level_constant(log_level)
|
|
329
|
+
log_level.upcase.to_sym
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def severity_too_low?(severity)
|
|
333
|
+
severity_constant = format_log_level_constant(severity)
|
|
334
|
+
# always record custom log levels
|
|
335
|
+
return false unless Logger::Severity.constants.include?(severity_constant)
|
|
336
|
+
|
|
337
|
+
Logger::Severity.const_get(severity_constant) < Logger::Severity.const_get(configured_log_level_constant)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def create_labels
|
|
341
|
+
return NewRelic::EMPTY_HASH unless NewRelic::Agent.config[LABELS_ENABLED_KEY]
|
|
342
|
+
|
|
343
|
+
downcased_exclusions = NewRelic::Agent.config[:'application_logging.forwarding.labels.exclude'].map(&:downcase)
|
|
344
|
+
log_labels = {}
|
|
345
|
+
|
|
346
|
+
NewRelic::Agent.config.parsed_labels.each do |parsed_label|
|
|
347
|
+
next if downcased_exclusions.include?(parsed_label['label_type'].downcase)
|
|
348
|
+
|
|
349
|
+
# labels are referred to as tags in the UI, so prefix the
|
|
350
|
+
# label-related attributes with 'tags.*'
|
|
351
|
+
log_labels["tags.#{parsed_label['label_type']}"] = parsed_label['label_value']
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
log_labels
|
|
355
|
+
end
|
|
233
356
|
end
|
|
234
357
|
end
|
|
235
358
|
end
|
|
@@ -0,0 +1,115 @@
|
|
|
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 LogEventAttributes
|
|
8
|
+
MAX_ATTRIBUTE_COUNT = 240 # limit is 255, assume we send 15
|
|
9
|
+
ATTRIBUTE_KEY_CHARACTER_LIMIT = 255
|
|
10
|
+
ATTRIBUTE_VALUE_CHARACTER_LIMIT = 4094
|
|
11
|
+
|
|
12
|
+
def add_custom_attributes(attributes)
|
|
13
|
+
return if defined?(@custom_attribute_limit_reached) && @custom_attribute_limit_reached
|
|
14
|
+
|
|
15
|
+
attributes.each do |key, value|
|
|
16
|
+
next if absent?(key) || absent?(value)
|
|
17
|
+
|
|
18
|
+
add_custom_attribute(key, value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def custom_attributes
|
|
23
|
+
@custom_attributes ||= {}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
class TruncationError < StandardError
|
|
29
|
+
attr_reader :attribute, :limit
|
|
30
|
+
|
|
31
|
+
def initialize(attribute, limit, msg = "Can't truncate")
|
|
32
|
+
@attribute = attribute
|
|
33
|
+
@limit = limit
|
|
34
|
+
super(msg)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class InvalidTypeError < StandardError
|
|
39
|
+
attr_reader :attribute
|
|
40
|
+
|
|
41
|
+
def initialize(attribute, msg = 'Invalid attribute type')
|
|
42
|
+
@attribute = attribute
|
|
43
|
+
super(msg)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def absent?(value)
|
|
48
|
+
value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def add_custom_attribute(key, value)
|
|
52
|
+
if custom_attributes.size >= MAX_ATTRIBUTE_COUNT
|
|
53
|
+
NewRelic::Agent.logger.warn(
|
|
54
|
+
'Too many custom log attributes defined. ' \
|
|
55
|
+
"Only taking the first #{MAX_ATTRIBUTE_COUNT}."
|
|
56
|
+
)
|
|
57
|
+
@custom_attribute_limit_reached = true
|
|
58
|
+
return
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@custom_attributes.merge!(truncate_attributes(key_to_string(key), value))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def key_to_string(key)
|
|
65
|
+
key.is_a?(String) ? key : key.to_s
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def truncate_attribute(attribute, limit)
|
|
69
|
+
case attribute
|
|
70
|
+
when Integer
|
|
71
|
+
if attribute.digits.length > limit
|
|
72
|
+
raise TruncationError.new(attribute, limit)
|
|
73
|
+
end
|
|
74
|
+
when Float
|
|
75
|
+
if attribute.to_s.length > limit
|
|
76
|
+
raise TruncationError.new(attribute, limit)
|
|
77
|
+
end
|
|
78
|
+
when String, Symbol
|
|
79
|
+
if attribute.length > limit
|
|
80
|
+
attribute = attribute.slice(0..(limit - 1))
|
|
81
|
+
end
|
|
82
|
+
when TrueClass, FalseClass
|
|
83
|
+
attribute
|
|
84
|
+
else
|
|
85
|
+
raise InvalidTypeError.new(attribute)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
attribute
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def truncate_attributes(key, value)
|
|
92
|
+
key = truncate_attribute(key, ATTRIBUTE_KEY_CHARACTER_LIMIT)
|
|
93
|
+
value = truncate_attribute(value, ATTRIBUTE_VALUE_CHARACTER_LIMIT)
|
|
94
|
+
|
|
95
|
+
{key => value}
|
|
96
|
+
rescue TruncationError => e
|
|
97
|
+
NewRelic::Agent.logger.warn(
|
|
98
|
+
"Dropping custom log attribute #{key} => #{value} \n" \
|
|
99
|
+
"Length exceeds character limit of #{e.limit}. " \
|
|
100
|
+
"Can't truncate: #{e.attribute}"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
{}
|
|
104
|
+
rescue InvalidTypeError => e
|
|
105
|
+
NewRelic::Agent.logger.warn(
|
|
106
|
+
"Dropping custom log attribute #{key} => #{value} \n" \
|
|
107
|
+
"Invalid type of #{e.attribute.class} given. " \
|
|
108
|
+
"Can't send #{e.attribute}."
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
{}
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -62,6 +62,10 @@ module NewRelic
|
|
|
62
62
|
message << CLOSING_BRACE << NEWLINE
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
+
def clear_tags!
|
|
66
|
+
# No-op; just avoiding issues with act-fluent-logger-rails
|
|
67
|
+
end
|
|
68
|
+
|
|
65
69
|
private
|
|
66
70
|
|
|
67
71
|
def add_app_name(message)
|
|
@@ -138,10 +142,6 @@ module NewRelic
|
|
|
138
142
|
end
|
|
139
143
|
message.to_json
|
|
140
144
|
end
|
|
141
|
-
|
|
142
|
-
def clear_tags!
|
|
143
|
-
# No-op; just avoiding issues with act-fluent-logger-rails
|
|
144
|
-
end
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
# This logger decorates logs with trace and entity metadata, and emits log
|
|
@@ -165,7 +165,7 @@ module NewRelic
|
|
|
165
165
|
# Positional and Keyword arguments are separated beginning with Ruby 2.7
|
|
166
166
|
# Signature of ::Logger constructor changes in Ruby 2.4 to have both positional and keyword args
|
|
167
167
|
# We pivot on Ruby 2.7 for widest supportability with least amount of hassle.
|
|
168
|
-
if RUBY_VERSION < '2.7.0'
|
|
168
|
+
if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
|
|
169
169
|
def initialize(*args)
|
|
170
170
|
super(*args)
|
|
171
171
|
self.formatter = DecoratingFormatter.new
|
|
@@ -49,6 +49,7 @@ module NewRelic
|
|
|
49
49
|
#
|
|
50
50
|
# @return [NewRelic::Agent::Transaction::MessageBrokerSegment]
|
|
51
51
|
#
|
|
52
|
+
# @!scope class
|
|
52
53
|
# @api public
|
|
53
54
|
#
|
|
54
55
|
def start_message_broker_segment(action: nil,
|
|
@@ -107,6 +108,7 @@ module NewRelic
|
|
|
107
108
|
# @return return value of given block, which will be the same as the
|
|
108
109
|
# return value of an un-instrumented subscribed callback
|
|
109
110
|
#
|
|
111
|
+
# @!scope class
|
|
110
112
|
# @api public
|
|
111
113
|
#
|
|
112
114
|
def wrap_message_broker_consume_transaction(library:,
|
|
@@ -117,7 +119,8 @@ module NewRelic
|
|
|
117
119
|
queue_name: nil,
|
|
118
120
|
exchange_type: nil,
|
|
119
121
|
reply_to: nil,
|
|
120
|
-
correlation_id: nil
|
|
122
|
+
correlation_id: nil,
|
|
123
|
+
action: nil)
|
|
121
124
|
|
|
122
125
|
state = Tracer.state
|
|
123
126
|
return yield if state.current_transaction
|
|
@@ -125,12 +128,12 @@ module NewRelic
|
|
|
125
128
|
txn = nil
|
|
126
129
|
|
|
127
130
|
begin
|
|
128
|
-
txn_name = transaction_name(library, destination_type, destination_name)
|
|
131
|
+
txn_name = transaction_name(library, destination_type, destination_name, action)
|
|
129
132
|
|
|
130
133
|
txn = Tracer.start_transaction(name: txn_name, category: :message)
|
|
131
|
-
|
|
132
134
|
if headers
|
|
133
|
-
|
|
135
|
+
NewRelic::Agent::DistributedTracing::accept_distributed_trace_headers(headers, library) # to handle the new w3c headers
|
|
136
|
+
txn.distributed_tracer.consume_message_headers(headers, state, library) # to do the expected old things
|
|
134
137
|
CrossAppTracing.reject_messaging_cat_headers(headers).each do |k, v|
|
|
135
138
|
txn.add_agent_attribute(:"message.headers.#{k}", v, AttributeFilter::DST_NONE) unless v.nil?
|
|
136
139
|
end
|
|
@@ -179,6 +182,7 @@ module NewRelic
|
|
|
179
182
|
#
|
|
180
183
|
# @return [NewRelic::Agent::Transaction::MessageBrokerSegment]
|
|
181
184
|
#
|
|
185
|
+
# @!scope class
|
|
182
186
|
# @api public
|
|
183
187
|
#
|
|
184
188
|
def start_amqp_publish_segment(library:,
|
|
@@ -239,6 +243,7 @@ module NewRelic
|
|
|
239
243
|
#
|
|
240
244
|
# @return [NewRelic::Agent::Transaction::MessageBrokerSegment]
|
|
241
245
|
#
|
|
246
|
+
# @!scope class
|
|
242
247
|
# @api public
|
|
243
248
|
#
|
|
244
249
|
def start_amqp_consume_segment(library:,
|
|
@@ -300,6 +305,7 @@ module NewRelic
|
|
|
300
305
|
# @return return value of given block, which will be the same as the
|
|
301
306
|
# return value of an un-instrumented subscribed callback
|
|
302
307
|
#
|
|
308
|
+
# @!scope class
|
|
303
309
|
# @api public
|
|
304
310
|
#
|
|
305
311
|
def wrap_amqp_consume_transaction(library: nil,
|
|
@@ -327,11 +333,16 @@ module NewRelic
|
|
|
327
333
|
NewRelic::Agent.config[:'message_tracer.segment_parameters.enabled']
|
|
328
334
|
end
|
|
329
335
|
|
|
330
|
-
def transaction_name(library, destination_type, destination_name)
|
|
336
|
+
def transaction_name(library, destination_type, destination_name, action = nil)
|
|
331
337
|
transaction_name = Transaction::MESSAGE_PREFIX + library
|
|
332
|
-
transaction_name <<
|
|
338
|
+
transaction_name << NewRelic::SLASH
|
|
333
339
|
transaction_name << Transaction::MessageBrokerSegment::TYPES[destination_type]
|
|
334
|
-
transaction_name <<
|
|
340
|
+
transaction_name << NewRelic::SLASH
|
|
341
|
+
|
|
342
|
+
if action == :consume
|
|
343
|
+
transaction_name << 'Consume'
|
|
344
|
+
transaction_name << NewRelic::SLASH
|
|
345
|
+
end
|
|
335
346
|
|
|
336
347
|
case destination_type
|
|
337
348
|
when :queue
|
|
@@ -65,6 +65,7 @@ module NewRelic
|
|
|
65
65
|
# categories, but generally this *should never ever be done*. Most of the time you can aggregate
|
|
66
66
|
# on the server.
|
|
67
67
|
#
|
|
68
|
+
# @!scope class
|
|
68
69
|
# @api public
|
|
69
70
|
#
|
|
70
71
|
def trace_execution_scoped(metric_names, options = NewRelic::EMPTY_HASH) # THREAD_LOCAL_ACCESS
|
|
@@ -81,6 +82,7 @@ module NewRelic
|
|
|
81
82
|
#
|
|
82
83
|
# * <tt>metric_names</tt> is a single name or an array of names of metrics
|
|
83
84
|
#
|
|
85
|
+
# @!scope class
|
|
84
86
|
# @api public
|
|
85
87
|
#
|
|
86
88
|
def trace_execution_unscoped(metric_names, options = NewRelic::EMPTY_HASH) # THREAD_LOCAL_ACCESS
|
|
@@ -134,7 +136,7 @@ module NewRelic
|
|
|
134
136
|
# Foo._nr_default_metric_name_code('bar') #=> "Custom/#{Foo.name}/bar"
|
|
135
137
|
def _nr_default_metric_name(method_name)
|
|
136
138
|
class_name = _nr_derived_class_name
|
|
137
|
-
->
|
|
139
|
+
->(*) { "Custom/#{class_name}/#{method_name}" }
|
|
138
140
|
end
|
|
139
141
|
|
|
140
142
|
# Checks to see if the method we are attempting to trace
|
|
@@ -241,6 +243,7 @@ module NewRelic
|
|
|
241
243
|
# # Instrument foo in transaction traces only
|
|
242
244
|
# add_method_tracer :foo, 'Custom/foo', :metric => false
|
|
243
245
|
#
|
|
246
|
+
# @!scope class
|
|
244
247
|
# @api public
|
|
245
248
|
#
|
|
246
249
|
def add_method_tracer(method_name, metric_name = nil, options = {})
|
|
@@ -46,13 +46,15 @@ module NewRelic
|
|
|
46
46
|
cache_key = "#{object.object_id}#{method_name}".freeze
|
|
47
47
|
return @code_information[cache_key] if @code_information.key?(cache_key)
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
info = namespace_and_location(object, method_name.to_sym)
|
|
50
|
+
return ::NewRelic::EMPTY_HASH if info.empty?
|
|
50
51
|
|
|
52
|
+
namespace, location, is_class_method = info
|
|
51
53
|
@code_information[cache_key] = {filepath: location.first,
|
|
52
54
|
lineno: location.last,
|
|
53
55
|
function: "#{'self.' if is_class_method}#{method_name}",
|
|
54
56
|
namespace: namespace}.freeze
|
|
55
|
-
rescue => e
|
|
57
|
+
rescue StandardError => e
|
|
56
58
|
::NewRelic::Agent.logger.warn("Unable to determine source code info for '#{object}', " \
|
|
57
59
|
"method '#{method_name}' - #{e.class}: #{e.message}")
|
|
58
60
|
::NewRelic::Agent.increment_metric(SOURCE_CODE_INFORMATION_FAILURE_METRIC, 1)
|
|
@@ -66,10 +68,10 @@ module NewRelic
|
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
# The string representation of a singleton class looks like
|
|
69
|
-
# '#<Class:MyModule::MyClass>'
|
|
70
|
-
# that string
|
|
71
|
+
# '#<Class:MyModule::MyClass>', or '#<Class:MyModule::MyClass(id: integer, attribute: string)>'
|
|
72
|
+
# Return the 'MyModule::MyClass' part of that string
|
|
71
73
|
def klass_name(object)
|
|
72
|
-
name = Regexp.last_match(1) if object.to_s =~ /^#<Class:(
|
|
74
|
+
name = Regexp.last_match(1) if object.to_s =~ /^#<Class:([\w:]+).*>$/
|
|
73
75
|
return name if name
|
|
74
76
|
|
|
75
77
|
raise "Unable to glean a class name from string '#{object}'"
|
|
@@ -101,6 +103,9 @@ module NewRelic
|
|
|
101
103
|
klass = object.singleton_class? ? klassify_singleton(object) : object
|
|
102
104
|
name = klass.name || '(Anonymous)'
|
|
103
105
|
is_class_method = false
|
|
106
|
+
|
|
107
|
+
return controller_info(klass, name, is_class_method) if controller_without_method?(klass, method_name)
|
|
108
|
+
|
|
104
109
|
method = if (klass.instance_methods + klass.private_instance_methods).include?(method_name)
|
|
105
110
|
klass.instance_method(method_name)
|
|
106
111
|
else
|
|
@@ -109,6 +114,22 @@ module NewRelic
|
|
|
109
114
|
end
|
|
110
115
|
[name, method.source_location, is_class_method]
|
|
111
116
|
end
|
|
117
|
+
|
|
118
|
+
# Rails controllers can be a special case because by default, controllers in Rails
|
|
119
|
+
# automatically render views with names that correspond to valid routes. This means
|
|
120
|
+
# that a controller method may not have a corresponding method in the controller class.
|
|
121
|
+
def controller_without_method?(klass, method_name)
|
|
122
|
+
defined?(Rails) &&
|
|
123
|
+
defined?(ApplicationController) &&
|
|
124
|
+
klass < ApplicationController &&
|
|
125
|
+
!klass.method_defined?(method_name)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def controller_info(klass, name, is_class_method)
|
|
129
|
+
path = Rails.root.join("app/controllers/#{klass.name.underscore}.rb")
|
|
130
|
+
|
|
131
|
+
File.exist?(path) ? [name, [path.to_s, 1], is_class_method] : []
|
|
132
|
+
end
|
|
112
133
|
end
|
|
113
134
|
end
|
|
114
135
|
end
|
|
@@ -32,7 +32,7 @@ module NewRelic
|
|
|
32
32
|
|
|
33
33
|
def deserialize_header(encoded_header, key)
|
|
34
34
|
decoded_header = obfuscator.deobfuscate(encoded_header)
|
|
35
|
-
::JSON.
|
|
35
|
+
::JSON.parse(decoded_header)
|
|
36
36
|
rescue => err
|
|
37
37
|
# If we have a failure of any type here, just return nil and carry on
|
|
38
38
|
NewRelic::Agent.logger.debug("Failure deserializing encoded header '#{key}' in #{self.class}, #{err.class}, #{err.message}")
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
module NewRelic
|
|
6
6
|
module Agent
|
|
7
7
|
class SyntheticsMonitor < InboundRequestMonitor
|
|
8
|
-
SYNTHETICS_HEADER_KEY = 'HTTP_X_NEWRELIC_SYNTHETICS'
|
|
8
|
+
SYNTHETICS_HEADER_KEY = 'HTTP_X_NEWRELIC_SYNTHETICS'
|
|
9
|
+
SYNTHETICS_INFO_HEADER_KEY = 'HTTP_X_NEWRELIC_SYNTHETICS_INFO'
|
|
9
10
|
|
|
10
11
|
SUPPORTED_VERSION = 1
|
|
11
12
|
EXPECTED_PAYLOAD_LENGTH = 5
|
|
@@ -16,6 +17,7 @@ module NewRelic
|
|
|
16
17
|
|
|
17
18
|
def on_before_call(request) # THREAD_LOCAL_ACCESS
|
|
18
19
|
encoded_header = request[SYNTHETICS_HEADER_KEY]
|
|
20
|
+
info_header = request[SYNTHETICS_INFO_HEADER_KEY]
|
|
19
21
|
return unless encoded_header
|
|
20
22
|
|
|
21
23
|
incoming_payload = deserialize_header(encoded_header, SYNTHETICS_HEADER_KEY)
|
|
@@ -27,7 +29,16 @@ module NewRelic
|
|
|
27
29
|
|
|
28
30
|
txn = Tracer.current_transaction
|
|
29
31
|
txn.raw_synthetics_header = encoded_header
|
|
32
|
+
txn.raw_synthetics_info_header = info_header
|
|
30
33
|
txn.synthetics_payload = incoming_payload
|
|
34
|
+
txn.synthetics_info_payload = load_json(info_header, SYNTHETICS_INFO_HEADER_KEY)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def load_json(header, key)
|
|
38
|
+
::JSON.parse(header)
|
|
39
|
+
rescue => err
|
|
40
|
+
NewRelic::Agent.logger.debug("Failure loading json header '#{key}' in #{self.class}, #{err.class}, #{err.message}")
|
|
41
|
+
nil
|
|
31
42
|
end
|
|
32
43
|
|
|
33
44
|
class << self
|
|
@@ -2,10 +2,10 @@
|
|
|
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'
|
|
6
5
|
require 'json'
|
|
7
6
|
require 'stringio'
|
|
8
7
|
require 'zlib'
|
|
8
|
+
require 'new_relic/base64'
|
|
9
9
|
|
|
10
10
|
module NewRelic
|
|
11
11
|
module Agent
|
|
@@ -45,7 +45,7 @@ module NewRelic
|
|
|
45
45
|
data = NewRelic::Agent::EncodingNormalizer.normalize_object(data)
|
|
46
46
|
end
|
|
47
47
|
json = ::JSON.dump(data)
|
|
48
|
-
Base64.encode64(Compressed::Deflate.encode(json))
|
|
48
|
+
NewRelic::Base64.encode64(Compressed::Deflate.encode(json))
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
end
|