newrelic_rpm 3.9.1.236 → 3.9.2.239
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -4
- data/CHANGELOG +96 -2
- data/lib/new_relic/agent.rb +47 -4
- data/lib/new_relic/agent/agent.rb +51 -26
- data/lib/new_relic/agent/agent_logger.rb +4 -0
- data/lib/new_relic/agent/configuration.rb +2 -32
- data/lib/new_relic/agent/configuration/default_source.rb +153 -118
- data/lib/new_relic/agent/configuration/dotted_hash.rb +52 -0
- data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
- data/lib/new_relic/agent/configuration/manager.rb +101 -2
- data/lib/new_relic/agent/configuration/manual_source.rb +17 -0
- data/lib/new_relic/agent/configuration/server_source.rb +12 -4
- data/lib/new_relic/agent/configuration/yaml_source.rb +46 -22
- data/lib/new_relic/agent/cross_app_monitor.rb +1 -1
- data/lib/new_relic/agent/cross_app_tracing.rb +1 -1
- data/lib/new_relic/agent/database/obfuscation_helpers.rb +55 -14
- data/lib/new_relic/agent/database/obfuscator.rb +22 -7
- data/lib/new_relic/agent/database/postgres_explain_obfuscator.rb +6 -8
- data/lib/new_relic/agent/error_collector.rb +24 -16
- data/lib/new_relic/agent/event_loop.rb +189 -0
- data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +8 -17
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +17 -16
- data/lib/new_relic/agent/instrumentation/ignore_actions.rb +41 -0
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +0 -11
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +0 -8
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -9
- data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +0 -18
- data/lib/new_relic/agent/instrumentation/rubyprof.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sinatra.rb +12 -1
- data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +1 -1
- data/lib/new_relic/agent/method_tracer.rb +33 -39
- data/lib/new_relic/agent/new_relic_service.rb +35 -156
- data/lib/new_relic/agent/new_relic_service/encoders.rb +34 -0
- data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +50 -0
- data/lib/new_relic/agent/new_relic_service/marshaller.rb +52 -0
- data/lib/new_relic/agent/new_relic_service/pruby_marshaller.rb +52 -0
- data/lib/new_relic/agent/threading/backtrace_node.rb +1 -1
- data/lib/new_relic/agent/traced_method_stack.rb +16 -2
- data/lib/new_relic/agent/transaction.rb +0 -4
- data/lib/new_relic/collection_helper.rb +2 -2
- data/lib/new_relic/control/frameworks/rails.rb +3 -0
- data/lib/new_relic/control/instrumentation.rb +6 -2
- data/lib/new_relic/json_wrapper.rb +47 -25
- data/lib/new_relic/language_support.rb +0 -4
- data/lib/new_relic/latest_changes.rb +2 -2
- data/lib/new_relic/rack/developer_mode.rb +4 -3
- data/lib/new_relic/recipes/capistrano3.rb +2 -2
- data/lib/new_relic/recipes/capistrano_legacy.rb +1 -1
- data/lib/new_relic/timer_lib.rb +1 -1
- data/lib/new_relic/version.rb +2 -2
- data/lib/tasks/config.html.erb +28 -0
- data/lib/tasks/config.rake +134 -0
- data/lib/tasks/config.text.erb +7 -0
- data/lib/tasks/install.rake +0 -63
- data/newrelic.yml +7 -0
- data/test/active_record_fixtures.rb +4 -4
- data/test/agent_helper.rb +58 -18
- data/test/environments/lib/environments/runner.rb +1 -1
- data/test/environments/rails21/Gemfile +1 -1
- data/test/environments/rails21/config/boot.rb +1 -1
- data/test/environments/rails22/Gemfile +1 -1
- data/test/environments/rails22/config/boot.rb +1 -1
- data/test/environments/rails23/config/boot.rb +2 -2
- data/test/environments/rails30/Gemfile +1 -1
- data/test/environments/rails31/Gemfile +1 -1
- data/test/environments/rails32/Gemfile +1 -1
- data/test/environments/rails40/Gemfile +1 -1
- data/test/environments/rails41/Gemfile +1 -1
- data/test/fixtures/cross_agent_tests/labels.json +104 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/README.md +23 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.obfuscated +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comments_with_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comments_with_quotes.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.obfuscated +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_double_quoted_string.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_single_quoted_string.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_comments_and_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_comments_and_quotes.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_comments_and_newlines.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_comments_and_newlines.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_end_of_line_comments.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_end_of_line_comments.sql +3 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/quote_delimiters_in_comments.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/quote_delimiters_in_comments.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.sql +1 -0
- data/test/multiverse/lib/multiverse/output_collector.rb +1 -1
- data/test/multiverse/lib/multiverse/runner.rb +1 -1
- data/test/multiverse/lib/multiverse/suite.rb +19 -4
- data/test/multiverse/suites/agent_only/audit_log_test.rb +1 -38
- data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +25 -35
- data/test/multiverse/suites/agent_only/config/newrelic.yml +2 -0
- data/test/multiverse/suites/agent_only/encoding_handling_test.rb +1 -0
- data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +1 -1
- data/test/multiverse/suites/agent_only/keepalive_test.rb +29 -0
- data/test/multiverse/suites/agent_only/labels_test.rb +89 -0
- data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -3
- data/test/multiverse/suites/agent_only/service_timeout_test.rb +1 -1
- data/test/multiverse/suites/agent_only/start_up_test.rb +9 -1
- data/test/multiverse/suites/capistrano/config/deploy.rb +6 -2
- data/test/multiverse/suites/capistrano/deployment_test.rb +12 -4
- data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +29 -1
- data/test/multiverse/suites/curb/Envfile +6 -2
- data/test/multiverse/suites/datamapper/Envfile +0 -4
- data/test/multiverse/suites/deferred_instrumentation/Envfile +0 -4
- data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +1 -1
- data/test/multiverse/suites/excon/Envfile +5 -4
- data/test/multiverse/suites/excon/excon_test.rb +1 -1
- data/test/multiverse/suites/httpclient/Envfile +0 -4
- data/test/multiverse/suites/marshalling/Envfile +12 -0
- data/test/multiverse/suites/marshalling/config/newrelic.yml +20 -0
- data/test/multiverse/suites/marshalling/marshalling_test.rb +60 -0
- data/test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb +1 -1
- data/test/multiverse/suites/mongo/helpers/mongo_replica_set.rb +1 -1
- data/test/multiverse/suites/mongo/helpers/mongo_server.rb +4 -4
- data/test/multiverse/suites/padrino/Envfile +0 -5
- data/test/multiverse/suites/padrino/padrino_test.rb +1 -1
- data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +1 -1
- data/test/multiverse/suites/rails/gc_instrumentation_test.rb +2 -1
- data/test/multiverse/suites/rails/ignore_test.rb +22 -0
- data/test/multiverse/suites/rails/rails2_app/config/boot.rb +2 -2
- data/test/multiverse/suites/rails/rails2_app/config/routes.rb +1 -0
- data/test/multiverse/suites/resque/Envfile +0 -4
- data/test/multiverse/suites/sequel/Envfile +0 -5
- data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +1 -1
- data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +1 -1
- data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +22 -0
- data/test/multiverse/suites/typhoeus/Envfile +1 -4
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -13
- data/test/new_relic/agent/agent_logger_test.rb +11 -0
- data/test/new_relic/agent/agent_test.rb +43 -20
- data/test/new_relic/agent/audit_logger_test.rb +7 -3
- data/test/new_relic/agent/commands/thread_profiler_session_test.rb +0 -1
- data/test/new_relic/agent/commands/xray_session_collection_test.rb +1 -1
- data/test/new_relic/agent/configuration/dotted_hash_test.rb +53 -0
- data/test/new_relic/agent/configuration/manager_test.rb +99 -6
- data/test/new_relic/agent/configuration/manual_source_test.rb +18 -0
- data/test/new_relic/agent/configuration/orphan_configuration_test.rb +1 -1
- data/test/new_relic/agent/configuration/yaml_source_test.rb +8 -4
- data/test/new_relic/agent/database/sql_obfuscation_test.rb +76 -0
- data/test/new_relic/agent/database_test.rb +2 -38
- data/test/new_relic/agent/error_collector/notice_error_test.rb +21 -3
- data/test/new_relic/agent/error_collector_test.rb +15 -2
- data/test/new_relic/agent/event_loop_test.rb +202 -0
- data/test/new_relic/agent/instrumentation/active_record_helper_test.rb +4 -0
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +283 -182
- data/test/new_relic/agent/method_tracer_test.rb +1 -2
- data/test/new_relic/agent/new_relic_service_test.rb +83 -27
- data/test/new_relic/agent/pipe_channel_manager_test.rb +6 -6
- data/test/new_relic/agent/rpm_agent_test.rb +1 -8
- data/test/new_relic/agent/sql_sampler_test.rb +10 -8
- data/test/new_relic/agent/threading/backtrace_service_test.rb +1 -1
- data/test/new_relic/agent/traced_method_stack_test.rb +45 -13
- data/test/new_relic/agent/transaction_sample_builder_test.rb +1 -2
- data/test/new_relic/agent/transaction_test.rb +3 -3
- data/test/new_relic/agent_test.rb +47 -8
- data/test/new_relic/collection_helper_test.rb +5 -5
- data/test/new_relic/control/instrumentation_test.rb +56 -0
- data/test/new_relic/control_test.rb +4 -3
- data/test/new_relic/fake_collector.rb +7 -2
- data/test/new_relic/http_client_test_cases.rb +4 -4
- data/test/new_relic/latest_changes_test.rb +3 -3
- data/test/new_relic/transaction_sample/segment_test.rb +0 -1
- data/test/new_relic/transaction_sample_test.rb +19 -2
- data/test/performance/lib/performance/runner.rb +4 -4
- data/test/performance/suites/marshalling.rb +46 -30
- data/test/performance/suites/sql_obfuscation.rb +30 -0
- data/test/test_helper.rb +1 -1
- data/ui/helpers/developer_mode_helper.rb +2 -2
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +1 -1
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +1 -1
- metadata +84 -3
- metadata.gz.sig +0 -0
- data/test/environments/rails23/config/environments/development.rb +0 -11
@@ -11,13 +11,11 @@ module NewRelic
|
|
11
11
|
module PostgresExplainObfuscator
|
12
12
|
extend self
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
].join('|')).freeze
|
20
|
-
LABEL_LINE_REGEX = /^([^:\n]*:\s+).*$/.freeze
|
14
|
+
# Note that this regex can't be shared with the ones in the
|
15
|
+
# Database::Obfuscator class because here we don't look for
|
16
|
+
# backslash-escaped strings (and those regexes are backwards).
|
17
|
+
QUOTED_STRINGS_REGEX = /'(?:[^']|'')*'|"(?:[^"]|"")*"/
|
18
|
+
LABEL_LINE_REGEX = /^([^:\n]*:\s+).*$/.freeze
|
21
19
|
|
22
20
|
def obfuscate(explain)
|
23
21
|
# First, we replace all single-quoted strings.
|
@@ -32,7 +30,7 @@ module NewRelic
|
|
32
30
|
# Note also that we make no special provisions for backslash-escaped
|
33
31
|
# single quotes (\') because these are canonicalized to two single
|
34
32
|
# quotes ('') in the explain output.
|
35
|
-
explain.gsub!(
|
33
|
+
explain.gsub!(QUOTED_STRINGS_REGEX) do |match|
|
36
34
|
match.start_with?('"') ? match : '?'
|
37
35
|
end
|
38
36
|
|
@@ -55,24 +55,33 @@ module NewRelic
|
|
55
55
|
!enabled?
|
56
56
|
end
|
57
57
|
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
|
58
|
+
# We store the passed block in both an ivar on the class, and implicitly
|
59
|
+
# within the body of the ignore_filter_proc method intentionally here.
|
60
|
+
# The define_method trick is needed to get around the fact that users may
|
61
|
+
# call 'return' from within their filter blocks, which would otherwise
|
62
|
+
# result in a LocalJumpError.
|
63
|
+
#
|
64
|
+
# The raw block is also stored in an instance variable so that we can
|
65
|
+
# return it later in its original form.
|
66
|
+
#
|
67
|
+
# This is all done at the class level in order to avoid the case where
|
68
|
+
# the user sets up an ignore filter on one instance of the ErrorCollector,
|
69
|
+
# and then that instance subsequently gets discarded during agent startup.
|
70
|
+
# (For example, if the agent is initially disabled, and then gets enabled
|
71
|
+
# via a call to manual_start later on.)
|
72
|
+
#
|
73
|
+
def self.ignore_error_filter=(block)
|
74
|
+
@ignore_filter = block
|
64
75
|
if block
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
@ignore_filter
|
76
|
+
define_method(:ignore_filter_proc, &block)
|
77
|
+
elsif method_defined?(:ignore_filter_proc)
|
78
|
+
undef :ignore_filter_proc
|
69
79
|
end
|
80
|
+
@ignore_filter
|
70
81
|
end
|
71
82
|
|
72
|
-
|
73
|
-
|
74
|
-
def clear_ignore_error_filter
|
75
|
-
@ignore_filter = nil
|
83
|
+
def self.ignore_error_filter
|
84
|
+
@ignore_filter
|
76
85
|
end
|
77
86
|
|
78
87
|
# errors is an array of Exception Class Names
|
@@ -90,8 +99,7 @@ module NewRelic
|
|
90
99
|
# Checks the provided error against the error filter, if there
|
91
100
|
# is an error filter
|
92
101
|
def filtered_by_error_filter?(error)
|
93
|
-
|
94
|
-
!@ignore_filter.call(error)
|
102
|
+
respond_to?(:ignore_filter_proc) && !ignore_filter_proc(error)
|
95
103
|
end
|
96
104
|
|
97
105
|
# Checks the array of error names and the error filter against
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under New Relic's license terms.
|
3
|
+
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
+
|
5
|
+
require 'thread'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
class EventLoop
|
10
|
+
class Timer
|
11
|
+
attr_reader :next_fire_time, :event, :interval, :last_fired_at
|
12
|
+
|
13
|
+
def initialize(interval, event, repeat=false)
|
14
|
+
@interval = interval
|
15
|
+
@event = event
|
16
|
+
@repeat = repeat
|
17
|
+
@started_at = Time.now
|
18
|
+
@last_fired_at = nil
|
19
|
+
reschedule
|
20
|
+
end
|
21
|
+
|
22
|
+
def reschedule
|
23
|
+
@next_fire_time = calculate_next_fire_time
|
24
|
+
end
|
25
|
+
|
26
|
+
def advance(amount)
|
27
|
+
@next_fire_time -= amount
|
28
|
+
end
|
29
|
+
|
30
|
+
def last_interval_start
|
31
|
+
@last_fired_at || @started_at
|
32
|
+
end
|
33
|
+
|
34
|
+
def calculate_next_fire_time
|
35
|
+
now = Time.now
|
36
|
+
return now if @interval == 0
|
37
|
+
fire_time = @last_fired_at || now
|
38
|
+
while fire_time <= now
|
39
|
+
fire_time += @interval
|
40
|
+
end
|
41
|
+
fire_time
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_fired_time
|
45
|
+
@last_fired_at = Time.now
|
46
|
+
end
|
47
|
+
|
48
|
+
def due?(now=Time.now)
|
49
|
+
now >= @next_fire_time
|
50
|
+
end
|
51
|
+
|
52
|
+
def finished?
|
53
|
+
!@repeat && @last_fired_at
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@self_pipe_rd, @self_pipe_wr = IO.pipe
|
59
|
+
@event_queue = Queue.new
|
60
|
+
@stopped = false
|
61
|
+
@timers = {}
|
62
|
+
|
63
|
+
@subscriptions = Hash.new { |h,k| h[k] = [] }
|
64
|
+
@subscriptions[:__add_timer] << Proc.new { |t| set_timer(t) }
|
65
|
+
@subscriptions[:__add_event] << Proc.new { |e, blk| @subscriptions[e] << blk }
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_timer(timer)
|
69
|
+
existing_timer = @timers[timer.event]
|
70
|
+
|
71
|
+
if existing_timer
|
72
|
+
elapsed_interval = Time.now - existing_timer.last_interval_start
|
73
|
+
timer.advance(elapsed_interval)
|
74
|
+
end
|
75
|
+
|
76
|
+
@timers[timer.event] = timer
|
77
|
+
|
78
|
+
fire_timer(timer)
|
79
|
+
end
|
80
|
+
|
81
|
+
def next_timeout
|
82
|
+
return nil if @timers.empty?
|
83
|
+
timeout = @timers.values.map(&:next_fire_time).min - Time.now
|
84
|
+
timeout < 0 ? 0 : timeout
|
85
|
+
end
|
86
|
+
|
87
|
+
def stopped?
|
88
|
+
@stopped
|
89
|
+
end
|
90
|
+
|
91
|
+
def stop
|
92
|
+
@stopped = true
|
93
|
+
wakeup
|
94
|
+
end
|
95
|
+
|
96
|
+
def run
|
97
|
+
::NewRelic::Agent.logger.debug "Running event loop"
|
98
|
+
while !stopped?
|
99
|
+
run_once
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_once(nonblock=false)
|
104
|
+
wait_to_run(nonblock)
|
105
|
+
|
106
|
+
prune_timers
|
107
|
+
fire_timers
|
108
|
+
|
109
|
+
until @event_queue.empty?
|
110
|
+
evt, args = @event_queue.pop
|
111
|
+
dispatch_event(evt, args)
|
112
|
+
reschedule_timer_for_event(evt)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def wait_to_run(nonblock)
|
117
|
+
timeout = nonblock ? 0 : next_timeout
|
118
|
+
ready = select([@self_pipe_rd], nil, nil, timeout)
|
119
|
+
|
120
|
+
if ready && ready[0] && ready[0][0] && ready[0][0] == @self_pipe_rd
|
121
|
+
@self_pipe_rd.read(1)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def fire_timers
|
126
|
+
@timers.each do |event, timer|
|
127
|
+
fire_timer(timer)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def fire_timer(timer)
|
132
|
+
if timer.due?
|
133
|
+
@event_queue << [timer.event]
|
134
|
+
timer.set_fired_time
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def prune_timers
|
139
|
+
@timers.delete_if { |e, t| t.finished? }
|
140
|
+
end
|
141
|
+
|
142
|
+
def dispatch_event(event, args)
|
143
|
+
NewRelic::Agent.logger.debug("EventLoop: Dispatching event '#{event}' with #{@subscriptions[event].size} callback(s).")
|
144
|
+
|
145
|
+
errors = []
|
146
|
+
@subscriptions[event].each do |s|
|
147
|
+
begin
|
148
|
+
s.call(*args)
|
149
|
+
rescue NewRelic::Agent::ForceRestartException, NewRelic::Agent::ForceDisconnectException
|
150
|
+
raise
|
151
|
+
rescue => e
|
152
|
+
errors << e
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if !errors.empty?
|
157
|
+
::NewRelic::Agent.logger.error "#{errors.size} error(s) running task for event '#{event}' in Agent Event Loop:", *errors
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def reschedule_timer_for_event(e)
|
162
|
+
@timers[e].reschedule if @timers[e]
|
163
|
+
end
|
164
|
+
|
165
|
+
def on(event, &blk)
|
166
|
+
fire(:__add_event, event, blk)
|
167
|
+
end
|
168
|
+
|
169
|
+
def fire(event, *args)
|
170
|
+
@event_queue << [event, args]
|
171
|
+
wakeup
|
172
|
+
end
|
173
|
+
|
174
|
+
def fire_every(interval, event)
|
175
|
+
::NewRelic::Agent.logger.debug "Firing event #{event} every #{interval} seconds."
|
176
|
+
fire(:__add_timer, Timer.new(interval, event, true))
|
177
|
+
end
|
178
|
+
|
179
|
+
def fire_after(interval, event)
|
180
|
+
::NewRelic::Agent.logger.debug "Firing event #{event} after #{interval} seconds."
|
181
|
+
fire(:__add_timer, Timer.new(interval, event, false))
|
182
|
+
end
|
183
|
+
|
184
|
+
def wakeup
|
185
|
+
@self_pipe_wr << '.'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# This file is distributed under New Relic's license terms.
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
4
|
require 'new_relic/agent/instrumentation/evented_subscriber'
|
5
|
+
require 'new_relic/agent/instrumentation/ignore_actions'
|
5
6
|
|
6
7
|
module NewRelic
|
7
8
|
module Agent
|
@@ -92,32 +93,22 @@ module NewRelic
|
|
92
93
|
end
|
93
94
|
|
94
95
|
def ignored?
|
95
|
-
_is_filtered?(
|
96
|
+
_is_filtered?(ControllerInstrumentation::NR_DO_NOT_TRACE_KEY)
|
96
97
|
end
|
97
98
|
|
98
99
|
def apdex_ignored?
|
99
|
-
_is_filtered?(
|
100
|
+
_is_filtered?(ControllerInstrumentation::NR_IGNORE_APDEX_KEY)
|
100
101
|
end
|
101
102
|
|
102
103
|
def enduser_ignored?
|
103
|
-
_is_filtered?(
|
104
|
+
_is_filtered?(ControllerInstrumentation::NR_IGNORE_ENDUSER_KEY)
|
104
105
|
end
|
105
106
|
|
106
|
-
# FIXME: shamelessly ripped from ControllerInstrumentation
|
107
107
|
def _is_filtered?(key)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
case ignore_actions
|
113
|
-
when nil; false
|
114
|
-
when Hash
|
115
|
-
only_actions = Array(ignore_actions[:only])
|
116
|
-
except_actions = Array(ignore_actions[:except])
|
117
|
-
only_actions.include?(metric_action.to_sym) || (except_actions.any? && !except_actions.include?(metric_action.to_sym))
|
118
|
-
else
|
119
|
-
true
|
120
|
-
end
|
108
|
+
NewRelic::Agent::Instrumentation::IgnoreActions.is_filtered?(
|
109
|
+
key,
|
110
|
+
@controller_class,
|
111
|
+
metric_action)
|
121
112
|
end
|
122
113
|
|
123
114
|
def to_s
|
@@ -84,7 +84,7 @@ module NewRelic
|
|
84
84
|
return unless event.payload[:connection_id]
|
85
85
|
|
86
86
|
connections = ::ActiveRecord::Base.connection_handler.connection_pool_list.map { |handler| handler.connections }.flatten
|
87
|
-
connection = connections.detect { |
|
87
|
+
connection = connections.detect { |cnxn| cnxn.object_id == event.payload[:connection_id] }
|
88
88
|
|
89
89
|
connection.instance_variable_get(:@config) if connection
|
90
90
|
end
|
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
require 'new_relic/agent/transaction'
|
6
6
|
require 'new_relic/agent/instrumentation/queue_time'
|
7
|
+
require 'new_relic/agent/instrumentation/ignore_actions'
|
7
8
|
module NewRelic
|
8
9
|
module Agent
|
9
10
|
# @api public
|
@@ -45,10 +46,10 @@ module NewRelic
|
|
45
46
|
def perform_action_with_newrelic_trace(*args); yield; end
|
46
47
|
end
|
47
48
|
|
48
|
-
NR_DO_NOT_TRACE_KEY = 'do_not_trace'
|
49
|
-
NR_IGNORE_APDEX_KEY = 'ignore_apdex'
|
50
|
-
NR_IGNORE_ENDUSER_KEY = 'ignore_enduser'
|
51
|
-
NR_DEFAULT_OPTIONS = {}.freeze
|
49
|
+
NR_DO_NOT_TRACE_KEY = :'@do_not_trace' unless defined?(NR_DO_NOT_TRACE_KEY )
|
50
|
+
NR_IGNORE_APDEX_KEY = :'@ignore_apdex' unless defined?(NR_IGNORE_APDEX_KEY )
|
51
|
+
NR_IGNORE_ENDUSER_KEY = :'@ignore_enduser' unless defined?(NR_IGNORE_ENDUSER_KEY)
|
52
|
+
NR_DEFAULT_OPTIONS = {}.freeze unless defined?(NR_DEFAULT_OPTIONS )
|
52
53
|
|
53
54
|
# @api public
|
54
55
|
module ClassMethods
|
@@ -88,11 +89,11 @@ module NewRelic
|
|
88
89
|
# Should be monkey patched into the controller class implemented
|
89
90
|
# with the inheritable attribute mechanism.
|
90
91
|
def newrelic_write_attr(attr_name, value) # :nodoc:
|
91
|
-
instance_variable_set
|
92
|
+
instance_variable_set(attr_name, value)
|
92
93
|
end
|
93
94
|
|
94
95
|
def newrelic_read_attr(attr_name) # :nodoc:
|
95
|
-
instance_variable_get
|
96
|
+
instance_variable_get(attr_name)
|
96
97
|
end
|
97
98
|
|
98
99
|
# Add transaction tracing to the given method. This will treat
|
@@ -329,7 +330,7 @@ module NewRelic
|
|
329
330
|
state = NewRelic::Agent::TransactionState.tl_get
|
330
331
|
state.request = newrelic_request(args)
|
331
332
|
|
332
|
-
# Skip instrumentation based on the value of 'do_not_trace' and if
|
333
|
+
# Skip instrumentation based on the value of 'do_not_trace?' and if
|
333
334
|
# we aren't calling directly with a block.
|
334
335
|
if !block_given? && do_not_trace?
|
335
336
|
state.current_transaction.ignore! if state.current_transaction
|
@@ -439,18 +440,18 @@ module NewRelic
|
|
439
440
|
end
|
440
441
|
|
441
442
|
# Filter out a request if it matches one of our parameters for
|
442
|
-
# ignoring it - the key is either
|
443
|
+
# ignoring it - the key is either NR_DO_NOT_TRACE_KEY or NR_IGNORE_APDEX_KEY
|
443
444
|
def _is_filtered?(key)
|
444
|
-
|
445
|
-
|
446
|
-
when nil; false
|
447
|
-
when Hash
|
448
|
-
only_actions = Array(ignore_actions[:only])
|
449
|
-
except_actions = Array(ignore_actions[:except])
|
450
|
-
only_actions.include?(action_name.to_sym) || (except_actions.any? && !except_actions.include?(action_name.to_sym))
|
445
|
+
name = if respond_to?(:action_name)
|
446
|
+
action_name
|
451
447
|
else
|
452
|
-
|
448
|
+
:'[action_name_missing]'
|
453
449
|
end
|
450
|
+
|
451
|
+
NewRelic::Agent::Instrumentation::IgnoreActions.is_filtered?(
|
452
|
+
key,
|
453
|
+
self.class,
|
454
|
+
name)
|
454
455
|
end
|
455
456
|
|
456
457
|
def detect_queue_start_time(state)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under New Relic's license terms.
|
3
|
+
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
+
|
5
|
+
module NewRelic
|
6
|
+
module Agent
|
7
|
+
module Instrumentation
|
8
|
+
module IgnoreActions
|
9
|
+
def self.is_filtered?(key, klass, action_name)
|
10
|
+
# We'll walk the superclass chain and see if
|
11
|
+
# any class says 'yes, filter this one'.
|
12
|
+
|
13
|
+
while klass.respond_to? :newrelic_read_attr
|
14
|
+
ignore_actions = klass.newrelic_read_attr(key)
|
15
|
+
|
16
|
+
should_filter = case ignore_actions
|
17
|
+
when Hash
|
18
|
+
only_actions = Array(ignore_actions[:only])
|
19
|
+
except_actions = Array(ignore_actions[:except])
|
20
|
+
action_name = action_name.to_sym
|
21
|
+
|
22
|
+
only_actions.include?(action_name) || (!except_actions.empty? && !except_actions.include?(action_name))
|
23
|
+
else
|
24
|
+
!!ignore_actions
|
25
|
+
end
|
26
|
+
|
27
|
+
return true if should_filter
|
28
|
+
|
29
|
+
# Nothing so far says we should filter,
|
30
|
+
# so keep checking up the superclass chain.
|
31
|
+
klass = klass.superclass
|
32
|
+
end
|
33
|
+
|
34
|
+
# Getting here means that no class filtered this.
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|