newrelic_rpm 5.7.0.350 → 9.0.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/.gitignore +15 -1
- data/.rubocop.yml +1919 -0
- data/.rubocop_todo.yml +100 -0
- data/.simplecov +15 -0
- data/.snyk +11 -0
- data/.yardopts +2 -0
- data/Brewfile +12 -0
- data/CHANGELOG.md +4056 -2339
- data/CONTRIBUTING.md +132 -19
- data/DOCKER.md +167 -0
- data/Dockerfile +10 -0
- data/Gemfile +5 -2
- data/Guardfile +22 -4
- data/LICENSE +202 -38
- data/README.md +87 -87
- data/Rakefile +27 -27
- data/THIRD_PARTY_NOTICES.md +28 -0
- data/Thorfile +5 -0
- data/bin/newrelic +3 -2
- data/bin/newrelic_cmd +1 -0
- data/bin/nrdebug +77 -54
- data/config.dot +5 -5
- data/docker-compose.yml +107 -0
- data/init.rb +5 -7
- data/install.rb +3 -3
- data/lefthook.yml +9 -0
- data/lib/new_relic/agent/adaptive_sampler.rb +14 -10
- data/lib/new_relic/agent/agent.rb +125 -969
- data/lib/new_relic/agent/agent_helpers/connect.rb +227 -0
- data/lib/new_relic/agent/agent_helpers/harvest.rb +153 -0
- data/lib/new_relic/agent/agent_helpers/shutdown.rb +72 -0
- data/lib/new_relic/agent/agent_helpers/special_startup.rb +74 -0
- data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +167 -0
- data/lib/new_relic/agent/agent_helpers/startup.rb +202 -0
- data/lib/new_relic/agent/agent_helpers/transmit.rb +76 -0
- data/lib/new_relic/agent/agent_logger.rb +26 -18
- data/lib/new_relic/agent/attribute_filter.rb +69 -52
- data/lib/new_relic/agent/attribute_processing.rb +8 -8
- data/lib/new_relic/agent/attributes.rb +153 -0
- data/lib/new_relic/agent/audit_logger.rb +19 -4
- data/lib/new_relic/agent/autostart.rb +34 -28
- data/lib/new_relic/agent/chained_call.rb +2 -2
- data/lib/new_relic/agent/commands/agent_command.rb +4 -4
- data/lib/new_relic/agent/commands/agent_command_router.rb +15 -33
- data/lib/new_relic/agent/commands/thread_profiler_session.rb +13 -11
- data/lib/new_relic/agent/configuration/default_source.rb +1480 -1053
- data/lib/new_relic/agent/configuration/dotted_hash.rb +7 -6
- data/lib/new_relic/agent/configuration/environment_source.rb +15 -11
- data/lib/new_relic/agent/configuration/event_harvest_config.rb +68 -0
- data/lib/new_relic/agent/configuration/high_security_source.rb +9 -9
- data/lib/new_relic/agent/configuration/manager.rb +96 -79
- data/lib/new_relic/agent/configuration/manual_source.rb +2 -2
- data/lib/new_relic/agent/configuration/mask_defaults.rb +4 -4
- data/lib/new_relic/agent/configuration/security_policy_source.rb +83 -86
- data/lib/new_relic/agent/configuration/server_source.rb +49 -12
- data/lib/new_relic/agent/configuration/yaml_source.rb +42 -13
- data/lib/new_relic/agent/configuration.rb +2 -2
- data/lib/new_relic/agent/connect/request_builder.rb +61 -0
- data/lib/new_relic/agent/connect/response_handler.rb +58 -0
- data/lib/new_relic/agent/custom_event_aggregator.rb +15 -15
- data/lib/new_relic/agent/database/explain_plan_helpers.rb +5 -6
- data/lib/new_relic/agent/database/obfuscation_helpers.rb +16 -15
- data/lib/new_relic/agent/database/obfuscator.rb +3 -3
- data/lib/new_relic/agent/database/postgres_explain_obfuscator.rb +4 -4
- data/lib/new_relic/agent/database.rb +44 -53
- data/lib/new_relic/agent/database_adapter.rb +35 -0
- data/lib/new_relic/agent/datastores/metric_helper.rb +18 -20
- data/lib/new_relic/agent/datastores/mongo/event_formatter.rb +9 -8
- data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +7 -11
- data/lib/new_relic/agent/datastores/mongo.rb +7 -12
- data/lib/new_relic/agent/datastores/nosql_obfuscator.rb +41 -0
- data/lib/new_relic/agent/datastores/redis.rb +6 -12
- data/lib/new_relic/agent/datastores.rb +19 -23
- data/lib/new_relic/agent/deprecator.rb +2 -2
- data/lib/new_relic/agent/{cross_app_payload.rb → distributed_tracing/cross_app_payload.rb} +13 -12
- data/lib/new_relic/agent/{cross_app_tracing.rb → distributed_tracing/cross_app_tracing.rb} +87 -66
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_attributes.rb +84 -0
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_metrics.rb +75 -0
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_payload.rb +163 -0
- data/lib/new_relic/agent/distributed_tracing/distributed_trace_transport_type.rb +38 -0
- data/lib/new_relic/agent/distributed_tracing/trace_context.rb +245 -0
- data/lib/new_relic/agent/distributed_tracing/trace_context_payload.rb +127 -0
- data/lib/new_relic/agent/distributed_tracing.rb +113 -32
- data/lib/new_relic/agent/encoding_normalizer.rb +5 -3
- data/lib/new_relic/agent/error_collector.rb +99 -63
- data/lib/new_relic/agent/error_event_aggregator.rb +10 -8
- data/lib/new_relic/agent/error_filter.rb +174 -0
- data/lib/new_relic/agent/error_trace_aggregator.rb +6 -4
- data/lib/new_relic/agent/event_aggregator.rb +43 -48
- data/lib/new_relic/agent/event_buffer.rb +8 -9
- data/lib/new_relic/agent/event_listener.rb +2 -3
- data/lib/new_relic/agent/event_loop.rb +27 -25
- data/lib/new_relic/agent/external.rb +20 -51
- data/lib/new_relic/agent/guid_generator.rb +30 -0
- data/lib/new_relic/agent/harvester.rb +5 -6
- data/lib/new_relic/agent/heap.rb +8 -10
- data/lib/new_relic/agent/hostname.rb +26 -5
- data/lib/new_relic/agent/http_clients/abstract.rb +81 -0
- data/lib/new_relic/agent/http_clients/curb_wrappers.rb +26 -26
- data/lib/new_relic/agent/http_clients/excon_wrappers.rb +31 -17
- data/lib/new_relic/agent/http_clients/http_rb_wrappers.rb +18 -23
- data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +12 -15
- data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +24 -8
- data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +9 -12
- data/lib/new_relic/agent/http_clients/uri_util.rb +12 -13
- data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +22 -52
- data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +39 -0
- data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +59 -72
- data/lib/new_relic/agent/instrumentation/action_dispatch.rb +31 -0
- data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +64 -0
- data/lib/new_relic/agent/instrumentation/action_mailbox.rb +30 -0
- data/lib/new_relic/agent/instrumentation/action_mailbox_subscriber.rb +33 -0
- data/lib/new_relic/agent/instrumentation/action_mailer.rb +30 -0
- data/lib/new_relic/agent/instrumentation/action_mailer_subscriber.rb +85 -0
- data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +86 -62
- data/lib/new_relic/agent/instrumentation/active_job.rb +38 -19
- data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +41 -0
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +21 -7
- data/lib/new_relic/agent/instrumentation/active_record.rb +95 -46
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +82 -61
- data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +155 -0
- data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +36 -12
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +69 -64
- data/lib/new_relic/agent/instrumentation/active_storage.rb +8 -4
- data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +11 -32
- data/lib/new_relic/agent/instrumentation/active_support.rb +27 -0
- data/lib/new_relic/agent/instrumentation/active_support_logger/chain.rb +23 -0
- data/lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb +20 -0
- data/lib/new_relic/agent/instrumentation/active_support_logger/prepend.rb +12 -0
- data/lib/new_relic/agent/instrumentation/active_support_logger.rb +24 -0
- data/lib/new_relic/agent/instrumentation/active_support_subscriber.rb +41 -0
- data/lib/new_relic/agent/instrumentation/bunny/chain.rb +45 -0
- data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +150 -0
- data/lib/new_relic/agent/instrumentation/bunny/prepend.rb +35 -0
- data/lib/new_relic/agent/instrumentation/bunny.rb +14 -134
- data/lib/new_relic/agent/instrumentation/concurrent_ruby/chain.rb +36 -0
- data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +21 -0
- data/lib/new_relic/agent/instrumentation/concurrent_ruby/prepend.rb +27 -0
- data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +31 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +77 -61
- data/lib/new_relic/agent/instrumentation/curb/chain.rb +91 -0
- data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +221 -0
- data/lib/new_relic/agent/instrumentation/curb/prepend.rb +61 -0
- data/lib/new_relic/agent/instrumentation/curb.rb +15 -187
- data/lib/new_relic/agent/instrumentation/custom_events.rb +12 -0
- data/lib/new_relic/agent/instrumentation/custom_events_subscriber.rb +37 -0
- data/lib/new_relic/agent/instrumentation/delayed_job/chain.rb +35 -0
- data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +48 -0
- data/lib/new_relic/agent/instrumentation/delayed_job/prepend.rb +33 -0
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +30 -52
- data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +29 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +66 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch/prepend.rb +13 -0
- data/lib/new_relic/agent/instrumentation/elasticsearch.rb +31 -0
- data/lib/new_relic/agent/instrumentation/excon/middleware.rb +8 -7
- data/lib/new_relic/agent/instrumentation/excon.rb +29 -31
- data/lib/new_relic/agent/instrumentation/fiber/chain.rb +20 -0
- data/lib/new_relic/agent/instrumentation/fiber/instrumentation.rb +24 -0
- data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +18 -0
- data/lib/new_relic/agent/instrumentation/fiber.rb +25 -0
- data/lib/new_relic/agent/instrumentation/grape/chain.rb +24 -0
- data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +100 -0
- data/lib/new_relic/agent/instrumentation/grape/prepend.rb +17 -0
- data/lib/new_relic/agent/instrumentation/grape.rb +16 -121
- data/lib/new_relic/agent/instrumentation/grpc/client/chain.rb +97 -0
- data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +89 -0
- data/lib/new_relic/agent/instrumentation/grpc/client/prepend.rb +111 -0
- data/lib/new_relic/agent/instrumentation/grpc/client/request_wrapper.rb +30 -0
- data/lib/new_relic/agent/instrumentation/grpc/helper.rb +32 -0
- data/lib/new_relic/agent/instrumentation/grpc/server/chain.rb +69 -0
- data/lib/new_relic/agent/instrumentation/grpc/server/instrumentation.rb +134 -0
- data/lib/new_relic/agent/instrumentation/grpc/server/rpc_desc_prepend.rb +35 -0
- data/lib/new_relic/agent/instrumentation/grpc/server/rpc_server_prepend.rb +26 -0
- data/lib/new_relic/agent/instrumentation/grpc_client.rb +23 -0
- data/lib/new_relic/agent/instrumentation/grpc_server.rb +25 -0
- data/lib/new_relic/agent/instrumentation/httpclient/chain.rb +24 -0
- data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +37 -0
- data/lib/new_relic/agent/instrumentation/httpclient/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/httpclient.rb +12 -32
- data/lib/new_relic/agent/instrumentation/httprb/chain.rb +22 -0
- data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +30 -0
- data/lib/new_relic/agent/instrumentation/httprb/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/httprb.rb +29 -0
- data/lib/new_relic/agent/instrumentation/ignore_actions.rb +5 -6
- data/lib/new_relic/agent/instrumentation/logger/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/logger/instrumentation.rb +66 -0
- data/lib/new_relic/agent/instrumentation/logger/prepend.rb +13 -0
- data/lib/new_relic/agent/instrumentation/logger.rb +26 -0
- data/lib/new_relic/agent/instrumentation/memcache/chain.rb +15 -0
- data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +58 -125
- data/lib/new_relic/agent/instrumentation/memcache/helper.rb +59 -0
- data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +90 -0
- data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +101 -0
- data/lib/new_relic/agent/instrumentation/memcache.rb +57 -71
- data/lib/new_relic/agent/instrumentation/middleware_proxy.rb +15 -14
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +21 -14
- data/lib/new_relic/agent/instrumentation/mongo.rb +7 -132
- data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +49 -13
- data/lib/new_relic/agent/instrumentation/net_http/chain.rb +24 -0
- data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +40 -0
- data/lib/new_relic/agent/instrumentation/net_http/prepend.rb +21 -0
- data/lib/new_relic/agent/instrumentation/net_http.rb +44 -0
- data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +142 -0
- data/lib/new_relic/agent/instrumentation/padrino/chain.rb +38 -0
- data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +28 -0
- data/lib/new_relic/agent/instrumentation/padrino/prepend.rb +20 -0
- data/lib/new_relic/agent/instrumentation/padrino.rb +22 -58
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +7 -7
- data/lib/new_relic/agent/instrumentation/queue_time.rb +9 -10
- data/lib/new_relic/agent/instrumentation/rack/chain.rb +66 -0
- data/lib/new_relic/agent/instrumentation/rack/helpers.rb +33 -0
- data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +75 -0
- data/lib/new_relic/agent/instrumentation/rack/prepend.rb +43 -0
- data/lib/new_relic/agent/instrumentation/rack.rb +33 -141
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +19 -55
- data/lib/new_relic/agent/instrumentation/rails_middleware.rb +5 -5
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +36 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +45 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/action_view.rb +30 -0
- data/lib/new_relic/agent/instrumentation/rails_notifications/custom_events.rb +30 -0
- data/lib/new_relic/agent/instrumentation/rake/chain.rb +20 -0
- data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +142 -0
- data/lib/new_relic/agent/instrumentation/rake/prepend.rb +14 -0
- data/lib/new_relic/agent/instrumentation/rake.rb +18 -159
- data/lib/new_relic/agent/instrumentation/redis/chain.rb +45 -0
- data/lib/new_relic/agent/instrumentation/redis/constants.rb +17 -0
- data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +93 -0
- data/lib/new_relic/agent/instrumentation/redis/middleware.rb +16 -0
- data/lib/new_relic/agent/instrumentation/redis/prepend.rb +29 -0
- data/lib/new_relic/agent/instrumentation/redis.rb +20 -103
- data/lib/new_relic/agent/instrumentation/resque/chain.rb +21 -0
- data/lib/new_relic/agent/instrumentation/resque/helper.rb +19 -0
- data/lib/new_relic/agent/instrumentation/resque/instrumentation.rb +34 -0
- data/lib/new_relic/agent/instrumentation/resque/prepend.rb +15 -0
- data/lib/new_relic/agent/instrumentation/resque.rb +33 -41
- data/lib/new_relic/agent/instrumentation/sequel.rb +17 -20
- data/lib/new_relic/agent/instrumentation/sequel_helper.rb +3 -3
- data/lib/new_relic/agent/instrumentation/sidekiq/client.rb +20 -0
- data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +30 -0
- data/lib/new_relic/agent/instrumentation/sidekiq/server.rb +37 -0
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +29 -46
- data/lib/new_relic/agent/instrumentation/sinatra/chain.rb +55 -0
- data/lib/new_relic/agent/instrumentation/sinatra/ignorer.rb +31 -37
- data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +125 -0
- data/lib/new_relic/agent/instrumentation/sinatra/prepend.rb +33 -0
- data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +3 -3
- data/lib/new_relic/agent/instrumentation/sinatra.rb +35 -165
- data/lib/new_relic/agent/instrumentation/thread/chain.rb +24 -0
- data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +28 -0
- data/lib/new_relic/agent/instrumentation/thread/prepend.rb +22 -0
- data/lib/new_relic/agent/instrumentation/thread.rb +20 -0
- data/lib/new_relic/agent/instrumentation/tilt/chain.rb +24 -0
- data/lib/new_relic/agent/instrumentation/tilt/instrumentation.rb +41 -0
- data/lib/new_relic/agent/instrumentation/tilt/prepend.rb +13 -0
- data/lib/new_relic/agent/instrumentation/tilt.rb +25 -0
- data/lib/new_relic/agent/instrumentation/typhoeus/chain.rb +22 -0
- data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +80 -0
- data/lib/new_relic/agent/instrumentation/typhoeus/prepend.rb +14 -0
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +14 -76
- data/lib/new_relic/agent/instrumentation.rb +2 -2
- data/lib/new_relic/agent/internal_agent_error.rb +3 -3
- data/lib/new_relic/agent/javascript_instrumentor.rb +51 -45
- data/lib/new_relic/agent/linking_metadata.rb +44 -0
- data/lib/new_relic/agent/local_log_decorator.rb +37 -0
- data/lib/new_relic/agent/log_event_aggregator.rb +235 -0
- data/lib/new_relic/agent/log_once.rb +2 -2
- data/lib/new_relic/agent/log_priority.rb +20 -0
- data/lib/new_relic/agent/logging.rb +142 -0
- data/lib/new_relic/agent/memory_logger.rb +3 -3
- data/lib/new_relic/agent/messaging.rb +81 -164
- data/lib/new_relic/agent/method_tracer.rb +152 -145
- data/lib/new_relic/agent/method_tracer_helpers.rb +90 -13
- data/lib/new_relic/agent/monitors/cross_app_monitor.rb +117 -0
- data/lib/new_relic/agent/monitors/distributed_tracing_monitor.rb +28 -0
- data/lib/new_relic/agent/{inbound_request_monitor.rb → monitors/inbound_request_monitor.rb} +5 -6
- data/lib/new_relic/agent/{synthetics_monitor.rb → monitors/synthetics_monitor.rb} +9 -15
- data/lib/new_relic/agent/monitors.rb +26 -0
- data/lib/new_relic/agent/new_relic_service/encoders.rb +7 -7
- data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +6 -7
- data/lib/new_relic/agent/new_relic_service/marshaller.rb +8 -29
- data/lib/new_relic/agent/new_relic_service/security_policy_settings.rb +5 -5
- data/lib/new_relic/agent/new_relic_service.rb +282 -166
- data/lib/new_relic/agent/noticeable_error.rb +19 -0
- data/lib/new_relic/agent/null_logger.rb +8 -4
- data/lib/new_relic/agent/obfuscator.rb +9 -11
- data/lib/new_relic/agent/parameter_filtering.rb +35 -8
- data/lib/new_relic/agent/payload_metric_mapping.rb +10 -11
- data/lib/new_relic/agent/pipe_channel_manager.rb +28 -18
- data/lib/new_relic/agent/pipe_service.rb +9 -6
- data/lib/new_relic/agent/prepend_supportability.rb +3 -3
- data/lib/new_relic/agent/priority_sampled_buffer.rb +16 -14
- data/lib/new_relic/agent/range_extensions.rb +9 -29
- data/lib/new_relic/agent/rules_engine/replacement_rule.rb +12 -12
- data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +13 -14
- data/lib/new_relic/agent/rules_engine.rb +6 -5
- data/lib/new_relic/agent/sampler.rb +4 -5
- data/lib/new_relic/agent/sampler_collection.rb +4 -5
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +4 -3
- data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +14 -11
- data/lib/new_relic/agent/samplers/memory_sampler.rb +26 -15
- data/lib/new_relic/agent/samplers/object_sampler.rb +2 -2
- data/lib/new_relic/agent/samplers/vm_sampler.rb +22 -20
- data/lib/new_relic/agent/span_event_aggregator.rb +14 -16
- data/lib/new_relic/agent/span_event_primitive.rb +118 -58
- data/lib/new_relic/agent/sql_sampler.rb +25 -25
- data/lib/new_relic/agent/stats.rb +79 -42
- data/lib/new_relic/agent/stats_engine/gc_profiler.rb +11 -13
- data/lib/new_relic/agent/stats_engine/stats_hash.rb +13 -14
- data/lib/new_relic/agent/stats_engine.rb +11 -11
- data/lib/new_relic/agent/synthetics_event_aggregator.rb +8 -9
- data/lib/new_relic/agent/system_info.rb +100 -66
- data/lib/new_relic/agent/threading/agent_thread.rb +20 -16
- data/lib/new_relic/agent/threading/backtrace_node.rb +13 -14
- data/lib/new_relic/agent/threading/backtrace_service.rb +18 -18
- data/lib/new_relic/agent/threading/thread_profile.rb +31 -45
- data/lib/new_relic/agent/timestamp_sampled_buffer.rb +2 -2
- data/lib/new_relic/agent/tracer.rb +513 -0
- data/lib/new_relic/agent/transaction/abstract_segment.rb +131 -41
- data/lib/new_relic/agent/transaction/datastore_segment.rb +22 -18
- data/lib/new_relic/agent/transaction/distributed_tracer.rb +184 -0
- data/lib/new_relic/agent/transaction/distributed_tracing.rb +72 -163
- data/lib/new_relic/agent/transaction/external_request_segment.rb +66 -63
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +34 -46
- data/lib/new_relic/agent/transaction/request_attributes.rb +36 -36
- data/lib/new_relic/agent/transaction/segment.rb +46 -10
- data/lib/new_relic/agent/transaction/slowest_sample_buffer.rb +2 -4
- data/lib/new_relic/agent/transaction/synthetics_sample_buffer.rb +2 -2
- data/lib/new_relic/agent/transaction/trace.rb +21 -24
- data/lib/new_relic/agent/transaction/trace_builder.rb +11 -12
- data/lib/new_relic/agent/transaction/trace_context.rb +168 -0
- data/lib/new_relic/agent/transaction/trace_node.rb +31 -28
- data/lib/new_relic/agent/transaction/tracing.rb +15 -111
- data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +6 -6
- data/lib/new_relic/agent/transaction.rb +252 -259
- data/lib/new_relic/agent/transaction_error_primitive.rb +34 -37
- data/lib/new_relic/agent/transaction_event_aggregator.rb +13 -13
- data/lib/new_relic/agent/transaction_event_primitive.rb +44 -56
- data/lib/new_relic/agent/transaction_event_recorder.rb +17 -16
- data/lib/new_relic/agent/transaction_metrics.rb +11 -10
- data/lib/new_relic/agent/transaction_sampler.rb +7 -12
- data/lib/new_relic/agent/transaction_time_aggregator.rb +41 -26
- data/lib/new_relic/agent/utilization/aws.rb +34 -4
- data/lib/new_relic/agent/utilization/azure.rb +4 -4
- data/lib/new_relic/agent/utilization/gcp.rb +8 -8
- data/lib/new_relic/agent/utilization/pcf.rb +6 -5
- data/lib/new_relic/agent/utilization/vendor.rb +44 -29
- data/lib/new_relic/agent/utilization_data.rb +43 -6
- data/lib/new_relic/agent/vm/jruby_vm.rb +2 -2
- data/lib/new_relic/agent/vm/monotonic_gc_profiler.rb +3 -3
- data/lib/new_relic/agent/vm/mri_vm.rb +46 -19
- data/lib/new_relic/agent/vm/snapshot.rb +6 -6
- data/lib/new_relic/agent/vm.rb +2 -2
- data/lib/new_relic/agent/worker_loop.rb +11 -13
- data/lib/new_relic/agent.rb +151 -79
- data/lib/new_relic/cli/command.rb +21 -23
- data/lib/new_relic/cli/commands/deployments.rb +94 -45
- data/lib/new_relic/cli/commands/install.rb +24 -26
- data/lib/new_relic/coerce.rb +42 -15
- data/lib/new_relic/collection_helper.rb +51 -49
- data/lib/new_relic/constants.rb +39 -0
- data/lib/new_relic/control/class_methods.rb +11 -5
- data/lib/new_relic/control/frameworks/external.rb +3 -3
- data/lib/new_relic/control/frameworks/rails.rb +24 -18
- data/lib/new_relic/control/frameworks/rails3.rb +4 -5
- data/lib/new_relic/control/frameworks/rails4.rb +2 -2
- data/lib/new_relic/control/frameworks/rails_notifications.rb +14 -0
- data/lib/new_relic/control/frameworks/ruby.rb +4 -4
- data/lib/new_relic/control/frameworks/sinatra.rb +8 -2
- data/lib/new_relic/control/frameworks.rb +2 -2
- data/lib/new_relic/control/instance_methods.rb +33 -42
- data/lib/new_relic/control/instrumentation.rb +40 -12
- data/lib/new_relic/control/private_instance_methods.rb +48 -0
- data/lib/new_relic/control/server_methods.rb +4 -5
- data/lib/new_relic/control.rb +2 -3
- data/lib/new_relic/delayed_job_injection.rb +2 -2
- data/lib/new_relic/dependency_detection.rb +129 -18
- data/lib/new_relic/environment_report.rb +41 -35
- data/lib/new_relic/helper.rb +49 -8
- data/lib/new_relic/language_support.rb +30 -6
- data/lib/new_relic/latest_changes.rb +9 -8
- data/lib/new_relic/local_environment.rb +23 -27
- data/lib/new_relic/metric_data.rb +32 -27
- data/lib/new_relic/metric_spec.rb +9 -7
- data/lib/new_relic/noticed_error.rb +46 -33
- data/lib/new_relic/rack/agent_hooks.rb +2 -2
- data/lib/new_relic/rack/agent_middleware.rb +7 -5
- data/lib/new_relic/rack/browser_monitoring.rb +134 -117
- data/lib/new_relic/rack.rb +2 -2
- data/lib/new_relic/recipes/capistrano3.rb +4 -62
- data/lib/new_relic/recipes/capistrano_legacy.rb +24 -27
- data/lib/new_relic/recipes/helpers/send_deployment.rb +70 -0
- data/lib/new_relic/recipes.rb +2 -2
- data/lib/new_relic/supportability_helper.rb +21 -7
- data/lib/new_relic/traced_thread.rb +39 -0
- data/lib/new_relic/version.rb +7 -18
- data/lib/newrelic_rpm.rb +20 -33
- data/lib/sequel/extensions/{newrelic_instrumentation.rb → new_relic_instrumentation.rb} +16 -19
- data/lib/sequel/plugins/{newrelic_instrumentation.rb → new_relic_instrumentation.rb} +9 -15
- data/lib/tasks/all.rb +4 -4
- data/lib/tasks/config.rake +22 -118
- data/lib/tasks/coverage_report.rake +28 -0
- data/lib/tasks/helpers/config.html.erb +21 -0
- data/lib/tasks/helpers/format.rb +123 -0
- data/lib/tasks/helpers/matches.rb +12 -0
- data/lib/tasks/helpers/prompt.rb +24 -0
- data/lib/tasks/helpers/removers.rb +33 -0
- data/lib/tasks/install.rake +4 -0
- data/lib/tasks/instrumentation_generator/README.md +63 -0
- data/lib/tasks/instrumentation_generator/TODO.md +33 -0
- data/lib/tasks/instrumentation_generator/instrumentation.thor +121 -0
- data/lib/tasks/instrumentation_generator/templates/Envfile.tt +9 -0
- data/lib/tasks/instrumentation_generator/templates/chain.tt +22 -0
- data/lib/tasks/instrumentation_generator/templates/chain_method.tt +8 -0
- data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +29 -0
- data/lib/tasks/instrumentation_generator/templates/instrumentation.tt +13 -0
- data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +3 -0
- data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +19 -0
- data/lib/tasks/instrumentation_generator/templates/prepend.tt +13 -0
- data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +3 -0
- data/lib/tasks/instrumentation_generator/templates/test.tt +15 -0
- data/lib/tasks/multiverse.rake +4 -0
- data/lib/tasks/multiverse.rb +12 -5
- data/lib/tasks/newrelic.rb +2 -2
- data/lib/tasks/tests.rake +14 -14
- data/newrelic.yml +672 -3
- data/newrelic_rpm.gemspec +40 -31
- data/recipes/newrelic.rb +3 -3
- data/test/agent_helper.rb +419 -98
- metadata +238 -127
- data/.travis.yml +0 -228
- data/bin/mongrel_rpm +0 -33
- data/cert/cacert.pem +0 -1177
- data/lib/new_relic/agent/commands/xray_session.rb +0 -55
- data/lib/new_relic/agent/commands/xray_session_collection.rb +0 -161
- data/lib/new_relic/agent/cross_app_monitor.rb +0 -110
- data/lib/new_relic/agent/datastores/mongo/obfuscator.rb +0 -44
- data/lib/new_relic/agent/datastores/mongo/statement_formatter.rb +0 -53
- data/lib/new_relic/agent/distributed_trace_monitor.rb +0 -41
- data/lib/new_relic/agent/distributed_trace_payload.rb +0 -246
- data/lib/new_relic/agent/http_clients/abstract_request.rb +0 -31
- data/lib/new_relic/agent/instrumentation/active_record_4.rb +0 -42
- data/lib/new_relic/agent/instrumentation/active_record_5.rb +0 -41
- data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +0 -74
- data/lib/new_relic/agent/instrumentation/authlogic.rb +0 -25
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +0 -202
- data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +0 -104
- data/lib/new_relic/agent/instrumentation/excon/connection.rb +0 -46
- data/lib/new_relic/agent/instrumentation/http.rb +0 -46
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +0 -44
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +0 -33
- data/lib/new_relic/agent/instrumentation/net.rb +0 -50
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +0 -125
- data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +0 -46
- data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +0 -32
- data/lib/new_relic/agent/instrumentation/rails4/action_view.rb +0 -27
- data/lib/new_relic/agent/instrumentation/rails5/action_cable.rb +0 -36
- data/lib/new_relic/agent/instrumentation/rails5/action_controller.rb +0 -33
- data/lib/new_relic/agent/instrumentation/rails5/action_view.rb +0 -27
- data/lib/new_relic/agent/instrumentation/rainbows_instrumentation.rb +0 -26
- data/lib/new_relic/agent/instrumentation/sunspot.rb +0 -33
- data/lib/new_relic/agent/supported_versions.rb +0 -275
- data/lib/new_relic/agent/transaction/attributes.rb +0 -154
- data/lib/new_relic/agent/transaction/xray_sample_buffer.rb +0 -64
- data/lib/new_relic/agent/transaction_state.rb +0 -186
- data/lib/new_relic/build.rb +0 -2
- data/lib/new_relic/control/frameworks/merb.rb +0 -29
- data/lib/new_relic/control/frameworks/rails5.rb +0 -14
- data/lib/new_relic/metrics.rb +0 -13
- data/lib/tasks/config.html.erb +0 -32
- data/lib/tasks/versions.html.erb +0 -28
- data/lib/tasks/versions.postface.html +0 -8
- data/lib/tasks/versions.preface.html +0 -9
- data/lib/tasks/versions.rake +0 -65
- data/lib/tasks/versions.txt.erb +0 -14
- /data/lib/tasks/{config.text.erb → helpers/config.text.erb} +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
4
|
|
5
5
|
# This file may be independently required to set up method tracing prior to
|
6
6
|
# the full agent loading. In those cases, we do need at least this require to
|
@@ -47,12 +47,12 @@ module NewRelic
|
|
47
47
|
#
|
48
48
|
|
49
49
|
module MethodTracer
|
50
|
-
def self.included
|
51
|
-
|
50
|
+
def self.included(klass)
|
51
|
+
klass.extend(ClassMethods)
|
52
52
|
end
|
53
53
|
|
54
|
-
def self.extended
|
55
|
-
|
54
|
+
def self.extended(klass)
|
55
|
+
klass.extend(ClassMethods)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Trace a given block with stats and keep track of the caller.
|
@@ -67,8 +67,8 @@ module NewRelic
|
|
67
67
|
#
|
68
68
|
# @api public
|
69
69
|
#
|
70
|
-
def trace_execution_scoped(metric_names, options=
|
71
|
-
NewRelic::Agent.record_api_supportability_metric :
|
70
|
+
def trace_execution_scoped(metric_names, options = NewRelic::EMPTY_HASH) # THREAD_LOCAL_ACCESS
|
71
|
+
NewRelic::Agent.record_api_supportability_metric(:trace_execution_scoped) unless options[:internal]
|
72
72
|
NewRelic::Agent::MethodTracerHelpers.trace_execution_scoped(metric_names, options) do
|
73
73
|
# Using an implicit block avoids object allocation for a &block param
|
74
74
|
yield
|
@@ -78,19 +78,20 @@ module NewRelic
|
|
78
78
|
# Trace a given block with stats assigned to the given metric_name. It does not
|
79
79
|
# provide scoped measurements, meaning whatever is being traced will not 'blame the
|
80
80
|
# Controller'--that is to say appear in the breakdown chart.
|
81
|
-
#
|
81
|
+
#
|
82
82
|
# * <tt>metric_names</tt> is a single name or an array of names of metrics
|
83
83
|
#
|
84
84
|
# @api public
|
85
85
|
#
|
86
|
-
def trace_execution_unscoped(metric_names, options=
|
87
|
-
NewRelic::Agent.record_api_supportability_metric :
|
86
|
+
def trace_execution_unscoped(metric_names, options = NewRelic::EMPTY_HASH) # THREAD_LOCAL_ACCESS
|
87
|
+
NewRelic::Agent.record_api_supportability_metric(:trace_execution_unscoped) unless options[:internal]
|
88
88
|
return yield unless NewRelic::Agent.tl_is_execution_traced?
|
89
|
-
|
89
|
+
|
90
|
+
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
90
91
|
begin
|
91
92
|
yield
|
92
93
|
ensure
|
93
|
-
duration = (
|
94
|
+
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0
|
94
95
|
NewRelic::Agent.instance.stats_engine.tl_record_unscoped_metrics(metric_names, duration)
|
95
96
|
end
|
96
97
|
end
|
@@ -100,52 +101,40 @@ module NewRelic
|
|
100
101
|
module ClassMethods
|
101
102
|
# contains methods refactored out of the #add_method_tracer method
|
102
103
|
module AddMethodTracer
|
103
|
-
ALLOWED_KEYS = [:metric, :push_scope, :code_header, :code_footer].freeze
|
104
|
-
|
105
|
-
# raises an error when the
|
106
|
-
# NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer
|
107
|
-
# method is called with improper keys. This aids in
|
108
|
-
# debugging new instrumentation by failing fast
|
109
|
-
def check_for_illegal_keys!(method_name, options)
|
110
|
-
unrecognized_keys = options.keys - ALLOWED_KEYS
|
104
|
+
ALLOWED_KEYS = [:metric, :push_scope, :code_header, :code_information, :code_footer].freeze
|
111
105
|
|
112
|
-
|
113
|
-
raise "Unrecognized options when adding method tracer to #{method_name}: " +
|
114
|
-
unrecognized_keys.join(', ')
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# validity checking - add_method_tracer must receive either
|
119
|
-
# push scope or metric, or else it would record no
|
120
|
-
# data. Raises an error if this is the case
|
121
|
-
def check_for_push_scope_and_metric(options)
|
122
|
-
unless options[:push_scope] || options[:metric]
|
123
|
-
raise "Can't add a tracer where push_scope is false and metric is false"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
DEFAULT_SETTINGS = {:push_scope => true, :metric => true, :code_header => "", :code_footer => "" }.freeze
|
106
|
+
DEFAULT_SETTINGS = {:push_scope => true, :metric => true, :code_header => "", :code_footer => ""}.freeze
|
128
107
|
|
129
108
|
# Checks the provided options to make sure that they make
|
130
109
|
# sense. Raises an error if the options are incorrect to
|
131
110
|
# assist with debugging, so that errors occur at class
|
132
111
|
# construction time rather than instrumentation run time
|
133
|
-
def
|
112
|
+
def _nr_validate_method_tracer_options(method_name, options)
|
134
113
|
unless options.is_a?(Hash)
|
135
114
|
raise TypeError.new("Error adding method tracer to #{method_name}: provided options must be a Hash")
|
136
115
|
end
|
137
|
-
|
116
|
+
|
117
|
+
unrecognized_keys = options.keys - ALLOWED_KEYS
|
118
|
+
if unrecognized_keys.any?
|
119
|
+
raise "Unrecognized options when adding method tracer to #{method_name}: " +
|
120
|
+
unrecognized_keys.join(', ')
|
121
|
+
end
|
122
|
+
|
138
123
|
options = DEFAULT_SETTINGS.merge(options)
|
139
|
-
|
124
|
+
unless options[:push_scope] || options[:metric]
|
125
|
+
raise "Can't add a tracer where push_scope is false and metric is false"
|
126
|
+
end
|
127
|
+
|
140
128
|
options
|
141
129
|
end
|
142
130
|
|
143
131
|
# Default to the class where the method is defined.
|
144
132
|
#
|
145
133
|
# Example:
|
146
|
-
# Foo.
|
147
|
-
def
|
148
|
-
|
134
|
+
# Foo._nr_default_metric_name_code('bar') #=> "Custom/#{Foo.name}/bar"
|
135
|
+
def _nr_default_metric_name(method_name)
|
136
|
+
class_name = _nr_derived_class_name
|
137
|
+
-> (*) { "Custom/#{class_name}/#{method_name}" }
|
149
138
|
end
|
150
139
|
|
151
140
|
# Checks to see if the method we are attempting to trace
|
@@ -153,7 +142,7 @@ module NewRelic
|
|
153
142
|
# anything if the method doesn't exist.
|
154
143
|
def newrelic_method_exists?(method_name)
|
155
144
|
exists = method_defined?(method_name) || private_method_defined?(method_name)
|
156
|
-
::NewRelic::Agent.logger.error("Did not trace #{
|
145
|
+
::NewRelic::Agent.logger.error("Did not trace #{_nr_derived_class_name}##{method_name} because that method does not exist") unless exists
|
157
146
|
exists
|
158
147
|
end
|
159
148
|
|
@@ -161,67 +150,25 @@ module NewRelic
|
|
161
150
|
# given metric by checking to see if the traced method
|
162
151
|
# exists. Warns the user if methods are being double-traced
|
163
152
|
# to help with debugging custom instrumentation.
|
164
|
-
def
|
165
|
-
exists = method_defined?(
|
166
|
-
::NewRelic::Agent.logger.error("Attempt to trace a method twice
|
153
|
+
def method_traced?(method_name)
|
154
|
+
exists = method_name && _nr_traced_method_module.method_defined?(method_name)
|
155
|
+
::NewRelic::Agent.logger.error("Attempt to trace a method twice: Method = #{method_name}") if exists
|
167
156
|
exists
|
168
157
|
end
|
169
158
|
|
170
|
-
# Returns
|
171
|
-
|
172
|
-
|
173
|
-
# when the agent is disabled
|
174
|
-
def assemble_code_header(method_name, metric_name_code, options)
|
175
|
-
header = "return #{_untraced_method_name(method_name, metric_name_code)}(*args, &block) unless NewRelic::Agent.tl_is_execution_traced?\n"
|
176
|
-
header += options[:code_header].to_s
|
177
|
-
header
|
178
|
-
end
|
179
|
-
|
180
|
-
# returns an eval-able string that contains the traced
|
181
|
-
# method code used if the agent is not creating a scope for
|
182
|
-
# use in scoped metrics.
|
183
|
-
def method_without_push_scope(method_name, metric_name_code, options)
|
184
|
-
"def #{_traced_method_name(method_name, metric_name_code)}(*args, &block)
|
185
|
-
#{assemble_code_header(method_name, metric_name_code, options)}
|
186
|
-
t0 = Time.now
|
187
|
-
begin
|
188
|
-
#{_untraced_method_name(method_name, metric_name_code)}(*args, &block)\n
|
189
|
-
ensure
|
190
|
-
duration = (Time.now - t0).to_f
|
191
|
-
NewRelic::Agent.record_metric(\"#{metric_name_code}\", duration)
|
192
|
-
#{options[:code_footer]}
|
193
|
-
end
|
194
|
-
end"
|
159
|
+
# Returns an anonymous module that stores prepended trace methods.
|
160
|
+
def _nr_traced_method_module
|
161
|
+
@_nr_traced_method_module ||= Module.new
|
195
162
|
end
|
196
163
|
|
197
|
-
#
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
#{options[:code_header]}
|
202
|
-
result = ::NewRelic::Agent::MethodTracerHelpers.trace_execution_scoped(\"#{metric_name_code}\",
|
203
|
-
:metric => #{options[:metric]}) do
|
204
|
-
#{_untraced_method_name(method_name, metric_name_code)}(*args, &block)
|
205
|
-
end
|
206
|
-
#{options[:code_footer]}
|
207
|
-
result
|
208
|
-
end"
|
209
|
-
end
|
210
|
-
|
211
|
-
# Decides which code snippet we should be eval'ing in this
|
212
|
-
# context, based on the options.
|
213
|
-
def code_to_eval(method_name, metric_name_code, options)
|
214
|
-
options = validate_options(method_name, options)
|
215
|
-
if options[:push_scope]
|
216
|
-
method_with_push_scope(method_name, metric_name_code, options)
|
217
|
-
else
|
218
|
-
method_without_push_scope(method_name, metric_name_code, options)
|
164
|
+
# for testing only
|
165
|
+
def _nr_clear_traced_methods!
|
166
|
+
_nr_traced_method_module.module_eval do
|
167
|
+
self.instance_methods.each { |m| remove_method(m) }
|
219
168
|
end
|
220
169
|
end
|
221
170
|
|
222
|
-
|
223
|
-
|
224
|
-
def derived_class_name
|
171
|
+
def _nr_derived_class_name
|
225
172
|
return self.name if self.name && !self.name.empty?
|
226
173
|
return "AnonymousModule" if self.to_s.start_with?("#<Module:")
|
227
174
|
|
@@ -247,22 +194,26 @@ module NewRelic
|
|
247
194
|
#
|
248
195
|
# === Overriding the metric name
|
249
196
|
#
|
250
|
-
# +
|
251
|
-
#
|
252
|
-
# evaluated at call time, then single quote the value like this:
|
197
|
+
# +metric_name+ is a String or Proc. If a Proc is given, it is bound to
|
198
|
+
# the object that called the traced method. For example:
|
253
199
|
#
|
254
|
-
# add_method_tracer :foo,
|
200
|
+
# add_method_tracer :foo, -> { "Custom/#{self.class.name}/foo" }
|
255
201
|
#
|
256
202
|
# This would name the metric according to the class of the runtime
|
257
|
-
#
|
203
|
+
# instance, as opposed to the class where +foo+ is defined.
|
258
204
|
#
|
259
205
|
# If not provided, the metric name will be <tt>Custom/ClassName/method_name</tt>.
|
260
206
|
#
|
261
|
-
# @param [Symbol]
|
262
|
-
# @param [String]
|
263
|
-
# the traced method under. This may be either a
|
264
|
-
#
|
207
|
+
# @param method_name [Symbol] the name of the method to trace
|
208
|
+
# @param metric_name [String,Proc,Array] the metric name to record calls to
|
209
|
+
# the traced method under. This may be either a String, or a Proc
|
210
|
+
# to be evaluated at call-time in order to determine the metric
|
265
211
|
# name dynamically.
|
212
|
+
# This method also accepts an array of Strings/Procs, in which case the
|
213
|
+
# first metric given will be scoped, while the remaining metrics will be
|
214
|
+
# recorded as though passed with :push_scope => false. If an Array of
|
215
|
+
# metric names is given with :push_scope => false, all metrics will be
|
216
|
+
# unscoped.
|
266
217
|
# @param [Hash] options additional options controlling how the method is
|
267
218
|
# traced.
|
268
219
|
# @option options [Boolean] :push_scope (true) If false, the traced method will
|
@@ -271,16 +222,17 @@ module NewRelic
|
|
271
222
|
# @option options [Boolean] :metric (true) If false, the traced method will
|
272
223
|
# only appear in transaction traces, but no metrics will be recorded
|
273
224
|
# for it.
|
274
|
-
# @option options [
|
225
|
+
# @option options [Proc] :code_header ('') Ruby code to be inserted and run
|
275
226
|
# before the tracer begins timing.
|
276
|
-
# @option options [
|
227
|
+
# @option options [Proc] :code_footer ('') Ruby code to be inserted and run
|
277
228
|
# after the tracer stops timing.
|
278
229
|
#
|
279
230
|
# @example
|
280
231
|
# add_method_tracer :foo
|
281
232
|
#
|
282
233
|
# # With a custom metric name
|
283
|
-
# add_method_tracer :foo,
|
234
|
+
# add_method_tracer :foo, "Custom/MyClass/foo"
|
235
|
+
# add_method_tracer :bar, -> { "Custom/#{self.class.name}/bar" }
|
284
236
|
#
|
285
237
|
# # Instrument foo only for custom dashboards (not in transaction
|
286
238
|
# # traces or breakdown charts)
|
@@ -291,64 +243,119 @@ module NewRelic
|
|
291
243
|
#
|
292
244
|
# @api public
|
293
245
|
#
|
294
|
-
def add_method_tracer(method_name,
|
295
|
-
::NewRelic::Agent.add_or_defer_method_tracer(self, method_name,
|
246
|
+
def add_method_tracer(method_name, metric_name = nil, options = {})
|
247
|
+
::NewRelic::Agent.add_or_defer_method_tracer(self, method_name, metric_name, options)
|
296
248
|
end
|
297
249
|
|
298
250
|
# For tests only because tracers must be removed in reverse-order
|
299
251
|
# from when they were added, or else other tracers that were added to the same method
|
300
252
|
# may get removed as well.
|
301
|
-
def remove_method_tracer(method_name
|
253
|
+
def remove_method_tracer(method_name) # :nodoc:
|
302
254
|
return unless Agent.config[:agent_enabled]
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
::NewRelic::Agent.logger.debug("removed method tracer #{method_name}
|
255
|
+
|
256
|
+
if _nr_traced_method_module.method_defined?(method_name)
|
257
|
+
_nr_traced_method_module.send(:remove_method, method_name)
|
258
|
+
::NewRelic::Agent.logger.debug("removed method tracer #{method_name}\n")
|
307
259
|
else
|
308
|
-
raise "No tracer
|
260
|
+
raise "No tracer on method '#{method_name}'"
|
309
261
|
end
|
310
262
|
end
|
311
263
|
|
312
264
|
private
|
313
265
|
|
314
|
-
def
|
266
|
+
def _nr_add_method_tracer_now(method_name, metric_name, options)
|
315
267
|
NewRelic::Agent.record_api_supportability_metric(:add_method_tracer)
|
316
|
-
|
317
268
|
return unless newrelic_method_exists?(method_name)
|
318
|
-
metric_name_code ||= default_metric_name_code(method_name)
|
319
|
-
return if traced_method_exists?(method_name, metric_name_code)
|
320
269
|
|
321
|
-
|
270
|
+
remove_method_tracer(method_name) if method_traced?(method_name)
|
322
271
|
|
323
|
-
|
272
|
+
options = _nr_validate_method_tracer_options(method_name, options)
|
324
273
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
274
|
+
visibility = NewRelic::Helper.instance_method_visibility(self, method_name)
|
275
|
+
|
276
|
+
scoped_metric, unscoped_metrics = _nr_scoped_unscoped_metrics(metric_name, method_name, push_scope: options[:push_scope])
|
277
|
+
|
278
|
+
_nr_define_traced_method(method_name, scoped_metric: scoped_metric, unscoped_metrics: unscoped_metrics,
|
279
|
+
code_header: options[:code_header], code_footer: options[:code_footer],
|
280
|
+
record_metrics: options[:metric], visibility: visibility,
|
281
|
+
code_information: options[:code_information])
|
282
|
+
|
283
|
+
prepend(_nr_traced_method_module)
|
334
284
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
"#{_sanitize_name(method_name)}_without_trace_#{_sanitize_name(metric_name)}"
|
285
|
+
::NewRelic::Agent.logger.debug("Traced method: class = #{_nr_derived_class_name}," +
|
286
|
+
"method = #{method_name}, " +
|
287
|
+
"metric = '#{metric_name}'")
|
339
288
|
end
|
340
289
|
|
341
|
-
#
|
342
|
-
#
|
343
|
-
|
344
|
-
|
290
|
+
# See #add_method_tracer; if multiple metric names are given, the first is
|
291
|
+
# treated as scoped, the rest unscoped. If options[:push_scope] is false,
|
292
|
+
# all given metrics are unscoped.
|
293
|
+
def _nr_scoped_unscoped_metrics(metric_name, method_name, push_scope: true)
|
294
|
+
if metric_name.is_a?(Array) && push_scope
|
295
|
+
[metric_name.shift, metric_name]
|
296
|
+
elsif push_scope
|
297
|
+
[metric_name || _nr_default_metric_name(method_name), []]
|
298
|
+
else
|
299
|
+
[nil, Array(metric_name)]
|
300
|
+
end
|
345
301
|
end
|
346
302
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
303
|
+
def _nr_define_traced_method(method_name, scoped_metric: nil, unscoped_metrics: [],
|
304
|
+
code_header: nil, code_footer: nil, record_metrics: true,
|
305
|
+
visibility: :public, code_information: {})
|
306
|
+
|
307
|
+
_nr_traced_method_module.module_eval do
|
308
|
+
define_method(method_name) do |*args, &block|
|
309
|
+
return super(*args, &block) unless NewRelic::Agent.tl_is_execution_traced?
|
310
|
+
|
311
|
+
scoped_metric_eval, unscoped_metrics_eval = nil, []
|
312
|
+
|
313
|
+
scoped_metric_eval = case scoped_metric
|
314
|
+
when Proc
|
315
|
+
instance_exec(*args, &scoped_metric)
|
316
|
+
when String
|
317
|
+
scoped_metric
|
318
|
+
end
|
319
|
+
|
320
|
+
unscoped_metrics_eval = unscoped_metrics.map do |metric|
|
321
|
+
metric.kind_of?(Proc) ? instance_exec(*args, &metric) : metric.to_s
|
322
|
+
end
|
323
|
+
|
324
|
+
instance_exec(&code_header) if code_header.kind_of?(Proc)
|
325
|
+
|
326
|
+
# NOTE: Calling ::NewRelic::Agent::MethodTracer.trace_execution_scoped and
|
327
|
+
# .trace_execution_unscoped below relies on the fact that MethodTracer is included
|
328
|
+
# in Module on agent startup. If/when this changes, these methods should be
|
329
|
+
# explicitly namespaced and extended in MethodTracer.
|
330
|
+
|
331
|
+
# If tracing multiple metrics on this method, nest one unscoped trace inside the scoped trace.
|
332
|
+
begin
|
333
|
+
if scoped_metric_eval
|
334
|
+
::NewRelic::Agent::MethodTracer.trace_execution_scoped(scoped_metric_eval,
|
335
|
+
metric: record_metrics,
|
336
|
+
internal: true,
|
337
|
+
code_information: code_information) do
|
338
|
+
if unscoped_metrics_eval.empty?
|
339
|
+
super(*args, &block)
|
340
|
+
else
|
341
|
+
::NewRelic::Agent::MethodTracer.trace_execution_unscoped(unscoped_metrics_eval, internal: true) do
|
342
|
+
super(*args, &block)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
elsif !unscoped_metrics_eval.empty?
|
347
|
+
::NewRelic::Agent::MethodTracer.trace_execution_unscoped(unscoped_metrics_eval, internal: true) do
|
348
|
+
super(*args, &block)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
ensure
|
352
|
+
instance_exec(&code_footer) if code_footer.kind_of?(Proc)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
send(visibility, method_name)
|
357
|
+
ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
|
358
|
+
end
|
352
359
|
end
|
353
360
|
end
|
354
361
|
|
@@ -1,36 +1,113 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/
|
2
|
+
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
|
3
|
+
# frozen_string_literal: true
|
4
4
|
|
5
5
|
module NewRelic
|
6
6
|
module Agent
|
7
7
|
module MethodTracerHelpers
|
8
|
+
# These are code level metrics (CLM) attributes. For Ruby, they map like so:
|
9
|
+
# filepath: full path to an .rb file on disk
|
10
|
+
# lineno: the line number a Ruby method is defined on within a given .rb file
|
11
|
+
# function: the name of the Ruby method
|
12
|
+
# namespace: the Ruby class' namespace as a string, ex: 'MyModule::MyClass'
|
13
|
+
SOURCE_CODE_INFORMATION_PARAMETERS = %i[filepath lineno function namespace].freeze
|
14
|
+
SOURCE_CODE_INFORMATION_FAILURE_METRIC = "Supportability/CodeLevelMetrics/Ruby/Failure".freeze
|
8
15
|
MAX_ALLOWED_METRIC_DURATION = 1_000_000_000 # roughly 31 years
|
9
16
|
|
10
17
|
extend self
|
11
18
|
|
12
|
-
def trace_execution_scoped(metric_names, options=
|
13
|
-
|
14
|
-
return yield unless state.is_execution_traced?
|
19
|
+
def trace_execution_scoped(metric_names, options = NewRelic::EMPTY_HASH) # THREAD_LOCAL_ACCESS
|
20
|
+
return yield unless NewRelic::Agent::Tracer.state.is_execution_traced?
|
15
21
|
|
16
22
|
metric_names = Array(metric_names)
|
17
|
-
first_name
|
23
|
+
first_name = metric_names.shift
|
18
24
|
return yield unless first_name
|
19
25
|
|
20
|
-
segment = NewRelic::Agent::
|
26
|
+
segment = NewRelic::Agent::Tracer.start_segment(
|
21
27
|
name: first_name,
|
22
28
|
unscoped_metrics: metric_names
|
23
29
|
)
|
24
30
|
|
25
|
-
if options[:metric] == false
|
26
|
-
|
31
|
+
segment.record_metrics = false if options[:metric] == false
|
32
|
+
|
33
|
+
unless !options.key?(:code_information) || options[:code_information].nil? || options[:code_information].empty?
|
34
|
+
segment.code_information = options[:code_information]
|
27
35
|
end
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
37
|
+
Tracer.capture_segment_error(segment) { yield }
|
38
|
+
ensure
|
39
|
+
::NewRelic::Agent::Transaction::Segment.finish(segment)
|
40
|
+
end
|
41
|
+
|
42
|
+
def code_information(object, method_name)
|
43
|
+
return ::NewRelic::EMPTY_HASH unless clm_enabled? && object && method_name
|
44
|
+
|
45
|
+
@code_information ||= {}
|
46
|
+
cache_key = "#{object.object_id}#{method_name}".freeze
|
47
|
+
return @code_information[cache_key] if @code_information.key?(cache_key)
|
48
|
+
|
49
|
+
namespace, location, is_class_method = namespace_and_location(object, method_name.to_sym)
|
50
|
+
|
51
|
+
@code_information[cache_key] = {filepath: location.first,
|
52
|
+
lineno: location.last,
|
53
|
+
function: "#{'self.' if is_class_method}#{method_name}",
|
54
|
+
namespace: namespace}.freeze
|
55
|
+
rescue => e
|
56
|
+
::NewRelic::Agent.logger.warn("Unable to determine source code info for '#{object}', " \
|
57
|
+
"method '#{method_name}' - #{e.class}: #{e.message}")
|
58
|
+
::NewRelic::Agent.increment_metric(SOURCE_CODE_INFORMATION_FAILURE_METRIC, 1)
|
59
|
+
::NewRelic::EMPTY_HASH
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def clm_enabled?
|
65
|
+
::NewRelic::Agent.config[:'code_level_metrics.enabled']
|
66
|
+
end
|
67
|
+
|
68
|
+
# The string representation of a singleton class looks like
|
69
|
+
# '#<Class:MyModule::MyClass>'. Return the 'MyModule::MyClass' part of
|
70
|
+
# that string
|
71
|
+
def klass_name(object)
|
72
|
+
name = Regexp.last_match(1) if object.to_s =~ /^#<Class:(.*)>$/
|
73
|
+
return name if name
|
74
|
+
|
75
|
+
raise "Unable to glean a class name from string '#{object}'"
|
76
|
+
end
|
77
|
+
|
78
|
+
# get at the underlying class from the singleton class
|
79
|
+
#
|
80
|
+
# note: even with the regex hit from klass_name(), `Object.const_get`
|
81
|
+
# is more performant than iterating through `ObjectSpace`
|
82
|
+
def klassify_singleton(object)
|
83
|
+
Object.const_get(klass_name(object))
|
84
|
+
end
|
85
|
+
|
86
|
+
# determine the namespace (class name including all module names in scope)
|
87
|
+
# and source code location (file path and line number) for the given
|
88
|
+
# object and method name
|
89
|
+
#
|
90
|
+
# traced class methods:
|
91
|
+
# * object is a singleton class, `#<Class::MyClass>`
|
92
|
+
# * get at the underlying non-singleton class
|
93
|
+
#
|
94
|
+
# traced instance methods and Rails controller methods:
|
95
|
+
# * object is a class, `MyClass`
|
96
|
+
#
|
97
|
+
# anonymous class based methods (`c = Class.new { def method; end; }`:
|
98
|
+
# * `#name` returns `nil`, so use '(Anonymous)' instead
|
99
|
+
#
|
100
|
+
def namespace_and_location(object, method_name)
|
101
|
+
klass = object.singleton_class? ? klassify_singleton(object) : object
|
102
|
+
name = klass.name || '(Anonymous)'
|
103
|
+
is_class_method = false
|
104
|
+
method = if (klass.instance_methods + klass.private_instance_methods).include?(method_name)
|
105
|
+
klass.instance_method(method_name)
|
106
|
+
else
|
107
|
+
is_class_method = true
|
108
|
+
klass.method(method_name)
|
33
109
|
end
|
110
|
+
[name, method.source_location, is_class_method]
|
34
111
|
end
|
35
112
|
end
|
36
113
|
end
|