newrelic_rpm 3.11.2.286 → 3.12.0.288
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/.yardopts +2 -0
- data/CHANGELOG +39 -4
- data/README.md +4 -2
- data/lib/new_relic/agent.rb +229 -214
- data/lib/new_relic/agent/agent.rb +23 -12
- data/lib/new_relic/agent/attribute_filter.rb +242 -0
- data/lib/new_relic/agent/attribute_processing.rb +62 -0
- data/lib/new_relic/agent/commands/xray_session_collection.rb +4 -1
- data/lib/new_relic/agent/configuration/default_source.rb +284 -30
- data/lib/new_relic/agent/configuration/high_security_source.rb +0 -8
- data/lib/new_relic/agent/configuration/manager.rb +1 -1
- data/lib/new_relic/agent/configuration/server_source.rb +86 -31
- data/lib/new_relic/agent/configuration/yaml_source.rb +1 -1
- data/lib/new_relic/agent/cross_app_monitor.rb +8 -13
- data/lib/new_relic/agent/cross_app_tracing.rb +15 -15
- data/lib/new_relic/agent/custom_event_aggregator.rb +6 -2
- data/lib/new_relic/agent/database.rb +15 -2
- data/lib/new_relic/agent/datastores.rb +52 -38
- data/lib/new_relic/agent/datastores/metric_helper.rb +2 -1
- data/lib/new_relic/agent/encoding_normalizer.rb +82 -0
- data/lib/new_relic/agent/error_collector.rb +125 -169
- data/lib/new_relic/agent/hash_extensions.rb +26 -0
- data/lib/new_relic/agent/http_clients/excon_wrappers.rb +13 -11
- data/lib/new_relic/agent/http_clients/uri_util.rb +9 -0
- data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +1 -3
- data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +12 -5
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +6 -7
- data/lib/new_relic/agent/instrumentation/curb.rb +6 -6
- data/lib/new_relic/agent/instrumentation/excon/middleware.rb +4 -4
- data/lib/new_relic/agent/instrumentation/grape.rb +4 -3
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -3
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +9 -3
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +6 -1
- data/lib/new_relic/agent/instrumentation/rails3/errors.rb +9 -7
- data/lib/new_relic/agent/instrumentation/rails4/errors.rb +8 -6
- data/lib/new_relic/agent/instrumentation/resque.rb +2 -3
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +3 -3
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +2 -2
- data/lib/new_relic/agent/javascript_instrumentor.rb +24 -16
- data/lib/new_relic/agent/parameter_filtering.rb +8 -1
- data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +2 -2
- data/lib/new_relic/agent/sql_sampler.rb +1 -0
- data/lib/new_relic/agent/stats.rb +0 -4
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +5 -3
- data/lib/new_relic/agent/stats_engine/stats_hash.rb +4 -0
- data/lib/new_relic/agent/supported_versions.rb +2 -2
- data/lib/new_relic/agent/traced_method_stack.rb +3 -3
- data/lib/new_relic/agent/transaction.rb +141 -118
- data/lib/new_relic/agent/transaction/attributes.rb +161 -0
- data/lib/new_relic/agent/transaction/developer_mode_sample_buffer.rb +4 -4
- data/lib/new_relic/agent/transaction/trace.rb +150 -0
- data/lib/new_relic/agent/transaction/trace_node.rb +190 -0
- data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +2 -2
- data/lib/new_relic/agent/transaction_event_aggregator.rb +23 -7
- data/lib/new_relic/agent/transaction_sample_builder.rb +37 -62
- data/lib/new_relic/agent/transaction_sampler.rb +29 -66
- data/lib/new_relic/cli/commands/install.rb +2 -2
- data/lib/new_relic/coerce.rb +15 -28
- data/lib/new_relic/json_wrapper.rb +14 -73
- data/lib/new_relic/noticed_error.rb +81 -5
- data/lib/new_relic/rack/browser_monitoring.rb +14 -19
- data/lib/new_relic/rack/developer_mode.rb +68 -14
- data/lib/new_relic/rack/developer_mode/segment_summary.rb +56 -0
- data/lib/new_relic/version.rb +2 -2
- data/newrelic.yml +19 -196
- data/test/agent_helper.rb +42 -36
- data/test/config/newrelic.yml +0 -1
- data/test/environments/rails40/Gemfile +1 -1
- data/test/environments/rails41/Gemfile +1 -1
- data/test/environments/rails42/Gemfile +1 -1
- data/test/fixtures/cross_agent_tests/attribute_configuration.json +35 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/README.md +19 -12
- data/test/fixtures/cross_agent_tests/sql_obfuscation/sql_obfuscation.json +365 -0
- data/test/multiverse/lib/multiverse/suite.rb +5 -1
- data/test/multiverse/suites/active_record/active_record_test.rb +8 -8
- data/test/multiverse/suites/agent_only/agent_attributes_test.rb +145 -0
- data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +8 -0
- data/test/multiverse/suites/agent_only/custom_queue_time_test.rb +5 -1
- data/test/multiverse/suites/agent_only/encoding_handling_test.rb +6 -6
- data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -1
- data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +2 -3
- data/test/multiverse/suites/agent_only/synthetics_test.rb +3 -3
- data/test/multiverse/suites/agent_only/testing_app.rb +4 -0
- data/test/multiverse/suites/agent_only/thread_profiling_test.rb +1 -1
- data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +9 -7
- data/test/multiverse/suites/curb/Envfile +5 -6
- data/test/multiverse/suites/curb/curb_test.rb +4 -5
- data/test/multiverse/suites/datamapper/datamapper_test.rb +2 -2
- data/test/multiverse/suites/excon/Envfile +11 -4
- data/test/multiverse/suites/excon/excon_test.rb +5 -5
- data/test/multiverse/suites/grape/config/newrelic.yml +1 -0
- data/test/multiverse/suites/grape/grape_test.rb +76 -12
- data/test/multiverse/suites/grape/grape_test_api.rb +16 -0
- data/test/multiverse/suites/high_security/config/newrelic.yml +43 -3
- data/test/multiverse/suites/high_security/high_security_test.rb +165 -9
- data/test/multiverse/suites/httpclient/Envfile +5 -1
- data/test/multiverse/suites/httpclient/httpclient_test.rb +2 -2
- data/test/multiverse/suites/memcached/Envfile +1 -1
- data/test/multiverse/suites/mongo/Envfile +8 -1
- data/test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb +29 -29
- data/test/multiverse/suites/mongo/mongo_unsupported_version_test.rb +43 -8
- data/test/multiverse/suites/rack/rack_parameter_filtering_test.rb +13 -3
- data/test/multiverse/suites/rails/Envfile +3 -3
- data/test/multiverse/suites/rails/error_tracing_test.rb +52 -31
- data/test/multiverse/suites/rails/gc_instrumentation_test.rb +1 -1
- data/test/multiverse/suites/rails/ignore_test.rb +1 -1
- data/test/multiverse/suites/rails/parameter_capture_test.rb +108 -40
- data/test/multiverse/suites/rails/request_statistics_test.rb +10 -4
- data/test/multiverse/suites/rails/view_instrumentation_test.rb +24 -24
- data/test/multiverse/suites/resque/instrumentation_test.rb +46 -12
- data/test/multiverse/suites/sequel/sequel_extension_test.rb +8 -8
- data/test/multiverse/suites/sequel/sequel_helpers.rb +11 -11
- data/test/multiverse/suites/sequel/sequel_plugin_test.rb +11 -11
- data/test/multiverse/suites/sidekiq/Envfile +1 -4
- data/test/multiverse/suites/sidekiq/after_suite.rb +9 -0
- data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +49 -16
- data/test/multiverse/suites/sidekiq/test_worker.rb +1 -2
- data/test/multiverse/suites/sinatra/Envfile +1 -1
- data/test/multiverse/suites/sinatra/config/newrelic.yml +1 -0
- data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +0 -4
- data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +0 -4
- data/test/multiverse/suites/sinatra/sinatra_parameter_capture_test.rb +65 -0
- data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +0 -11
- data/test/multiverse/suites/typhoeus/Envfile +8 -2
- data/test/multiverse/suites/typhoeus/typhoeus_test.rb +4 -4
- data/test/new_relic/agent/agent/connect_test.rb +13 -9
- data/test/new_relic/agent/agent_test.rb +34 -24
- data/test/new_relic/agent/attribute_filter_test.rb +218 -0
- data/test/new_relic/agent/attribute_processing_test.rb +160 -0
- data/test/new_relic/agent/configuration/default_source_test.rb +88 -0
- data/test/new_relic/agent/configuration/manager_test.rb +3 -4
- data/test/new_relic/agent/configuration/orphan_configuration_test.rb +3 -1
- data/test/new_relic/agent/configuration/server_source_test.rb +39 -0
- data/test/new_relic/agent/cross_app_monitor_test.rb +6 -30
- data/test/new_relic/agent/cross_app_tracing_test.rb +12 -12
- data/test/new_relic/agent/database/sql_obfuscation_test.rb +39 -65
- data/test/new_relic/agent/datastores/metric_helper_test.rb +36 -0
- data/test/new_relic/agent/encoding_normalizer_test.rb +66 -0
- data/test/new_relic/agent/error_collector_test.rb +181 -34
- data/test/new_relic/agent/hash_extensions_test.rb +34 -0
- data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +20 -23
- data/test/new_relic/agent/instrumentation/action_view_subscriber_test.rb +12 -12
- data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +5 -5
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +4 -4
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +21 -11
- data/test/new_relic/agent/javascript_instrumentor_test.rb +69 -45
- data/test/new_relic/agent/pipe_service_test.rb +2 -2
- data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +1 -1
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +8 -7
- data/test/new_relic/agent/stats_engine/stats_hash_test.rb +2 -2
- data/test/new_relic/agent/threading/backtrace_node_test.rb +2 -2
- data/test/new_relic/agent/transaction/attributes_test.rb +276 -0
- data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +10 -10
- data/test/new_relic/agent/transaction/trace_node_test.rb +361 -0
- data/test/new_relic/agent/transaction/trace_test.rb +394 -0
- data/test/new_relic/agent/transaction/xray_sample_buffer_test.rb +1 -1
- data/test/new_relic/agent/transaction_event_aggregator_test.rb +127 -57
- data/test/new_relic/agent/transaction_sample_builder_test.rb +70 -78
- data/test/new_relic/agent/transaction_sampler_test.rb +76 -185
- data/test/new_relic/agent/transaction_test.rb +283 -135
- data/test/new_relic/agent_test.rb +27 -12
- data/test/new_relic/cli/commands/install_test.rb +27 -0
- data/test/new_relic/coerce_test.rb +0 -59
- data/test/new_relic/data_container_tests.rb +5 -5
- data/test/new_relic/fake_collector.rb +27 -9
- data/test/new_relic/filtering_test_app.rb +2 -1
- data/test/new_relic/http_client_test_cases.rb +16 -16
- data/test/new_relic/json_wrapper_test.rb +0 -54
- data/test/new_relic/marshalling_test_cases.rb +1 -0
- data/test/new_relic/multiverse_helpers.rb +144 -0
- data/test/new_relic/noticed_error_test.rb +112 -9
- data/test/new_relic/rack/browser_monitoring_test.rb +12 -7
- data/test/new_relic/{transaction_analysis → rack/developer_mode}/segment_summary_test.rb +5 -4
- data/test/new_relic/rack/developer_mode_test.rb +17 -3
- data/test/new_relic/rack/error_collector_test.rb +1 -1
- data/test/performance/lib/performance/instrumentation/stackprof.rb +1 -1
- data/test/performance/script/runner +2 -2
- data/test/performance/suites/active_record.rb +3 -3
- data/test/performance/suites/agent_attributes.rb +62 -0
- data/test/performance/suites/rack_middleware.rb +78 -28
- data/test/performance/suites/transaction_tracing.rb +35 -0
- data/test/test_helper.rb +9 -1
- data/ui/helpers/developer_mode_helper.rb +16 -23
- data/ui/views/newrelic/_sample.rhtml +3 -3
- data/ui/views/newrelic/_segment.rhtml +1 -1
- data/ui/views/newrelic/_show_sample_summary.rhtml +1 -1
- data/ui/views/newrelic/show_sample.rhtml +5 -4
- metadata +23 -80
- data/lib/new_relic/agent/transaction/force_persist_sample_buffer.rb +0 -25
- data/lib/new_relic/transaction_analysis.rb +0 -80
- data/lib/new_relic/transaction_analysis/segment_summary.rb +0 -53
- data/lib/new_relic/transaction_sample.rb +0 -207
- data/lib/new_relic/transaction_sample/composite_segment.rb +0 -31
- data/lib/new_relic/transaction_sample/fake_segment.rb +0 -13
- data/lib/new_relic/transaction_sample/segment.rb +0 -197
- data/lib/new_relic/transaction_sample/summary_segment.rb +0 -25
- data/lib/new_relic/url_rule.rb +0 -18
- data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.obfuscated +0 -2
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.sql +0 -2
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.obfuscated +0 -2
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.sql +0 -2
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.sql +0 -4
- data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_double_quoted_string.mysql.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_single_quoted_string.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/README.md +0 -4
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/end_of_line_comments_with_quotes.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/end_of_line_comments_with_quotes.sql +0 -2
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_comments_and_quotes.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_comments_and_quotes.sql +0 -2
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_comments_and_newlines.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_comments_and_newlines.sql +0 -4
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_end_of_line_comments.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_end_of_line_comments.sql +0 -3
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/quote_delimiters_in_comments.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/quote_delimiters_in_comments.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.sql +0 -4
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.sql +0 -2
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.sql +0 -4
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.sql +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.obfuscated +0 -1
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.sql +0 -1
- data/test/new_relic/agent/error_collector/notice_error_test.rb +0 -261
- data/test/new_relic/agent/transaction/force_persist_sample_buffer_test.rb +0 -52
- data/test/new_relic/transaction_analysis_test.rb +0 -125
- data/test/new_relic/transaction_sample/composite_segment_test.rb +0 -38
- data/test/new_relic/transaction_sample/fake_segment_test.rb +0 -18
- data/test/new_relic/transaction_sample/segment_test.rb +0 -361
- data/test/new_relic/transaction_sample/summary_segment_test.rb +0 -34
- data/test/new_relic/transaction_sample_subtest_test.rb +0 -41
- data/test/new_relic/transaction_sample_test.rb +0 -361
@@ -46,7 +46,8 @@ module NewRelic
|
|
46
46
|
|
47
47
|
def self.metrics_for(product, operation, collection = nil)
|
48
48
|
if overrides = overridden_operation_and_collection
|
49
|
-
operation
|
49
|
+
operation = overrides[0] || operation
|
50
|
+
collection = overrides[1] || collection
|
50
51
|
end
|
51
52
|
|
52
53
|
suffix = all_suffix
|
@@ -0,0 +1,82 @@
|
|
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
|
+
# This module was extracted from NewRelic::JSONWrapper
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module EncodingNormalizer
|
10
|
+
def self.normalize_string(raw_string)
|
11
|
+
@normalizer ||= choose_normalizer
|
12
|
+
@normalizer.normalize(raw_string)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.normalize_object(object)
|
16
|
+
case object
|
17
|
+
when String
|
18
|
+
normalize_string(object)
|
19
|
+
when Symbol
|
20
|
+
normalize_string(object.to_s)
|
21
|
+
when Array
|
22
|
+
return object if object.empty?
|
23
|
+
object.map { |x| normalize_object(x) }
|
24
|
+
when Hash
|
25
|
+
return object if object.empty?
|
26
|
+
hash = {}
|
27
|
+
object.each_pair do |k, v|
|
28
|
+
k = normalize_string(k) if k.is_a?(String)
|
29
|
+
k = normalize_string(k.to_s) if k.is_a?(Symbol)
|
30
|
+
hash[k] = normalize_object(v)
|
31
|
+
end
|
32
|
+
hash
|
33
|
+
else
|
34
|
+
object
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.choose_normalizer
|
39
|
+
if NewRelic::LanguageSupport.supports_string_encodings?
|
40
|
+
EncodingNormalizer
|
41
|
+
else
|
42
|
+
IconvNormalizer
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module EncodingNormalizer
|
47
|
+
def self.normalize(raw_string)
|
48
|
+
encoding = raw_string.encoding
|
49
|
+
if (encoding == Encoding::UTF_8 || encoding == Encoding::ISO_8859_1) && raw_string.valid_encoding?
|
50
|
+
return raw_string
|
51
|
+
end
|
52
|
+
|
53
|
+
# If the encoding is not valid, or it's ASCII-8BIT, we know conversion to
|
54
|
+
# UTF-8 is likely to fail, so treat it as ISO-8859-1 (byte-preserving).
|
55
|
+
normalized = raw_string.dup
|
56
|
+
if encoding == Encoding::ASCII_8BIT || !raw_string.valid_encoding?
|
57
|
+
normalized.force_encoding(Encoding::ISO_8859_1)
|
58
|
+
else
|
59
|
+
# Encoding is valid and non-binary, so it might be cleanly convertible
|
60
|
+
# to UTF-8. Give it a try and fall back to ISO-8859-1 if it fails.
|
61
|
+
begin
|
62
|
+
normalized.encode!(Encoding::UTF_8)
|
63
|
+
rescue
|
64
|
+
normalized.force_encoding(Encoding::ISO_8859_1)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
normalized
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module IconvNormalizer
|
72
|
+
def self.normalize(raw_string)
|
73
|
+
if @iconv.nil?
|
74
|
+
require 'iconv'
|
75
|
+
@iconv = Iconv.new('utf-8', 'iso-8859-1')
|
76
|
+
end
|
77
|
+
@iconv.iconv(raw_string)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -93,208 +93,165 @@ module NewRelic
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
#
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
def filtered_by_error_filter?(error)
|
102
|
-
respond_to?(:ignore_filter_proc) && !ignore_filter_proc(error)
|
103
|
-
end
|
104
|
-
|
105
|
-
# Checks the array of error names and the error filter against
|
106
|
-
# the provided error
|
107
|
-
def filtered_error?(error)
|
108
|
-
@ignore[error.class.name] || filtered_by_error_filter?(error)
|
109
|
-
end
|
110
|
-
|
111
|
-
# an error is ignored if it is nil or if it is filtered
|
112
|
-
def error_is_ignored?(error)
|
113
|
-
error && filtered_error?(error)
|
114
|
-
rescue => e
|
115
|
-
NewRelic::Agent.logger.error("Error '#{error}' will NOT be ignored. Exception '#{e}' while determining whether to ignore or not.", e)
|
116
|
-
false
|
117
|
-
end
|
118
|
-
|
119
|
-
def seen?(txn, exception)
|
120
|
-
error_ids = txn.nil? ? [] : txn.noticed_error_ids
|
121
|
-
error_ids.include?(exception.object_id)
|
122
|
-
end
|
123
|
-
|
124
|
-
def tag_as_seen(state, exception)
|
125
|
-
txn = state.current_transaction
|
126
|
-
txn.noticed_error_ids << exception.object_id if txn
|
127
|
-
end
|
128
|
-
|
129
|
-
def blamed_metric_name(txn, options)
|
130
|
-
if options[:metric] && options[:metric] != ::NewRelic::Agent::UNKNOWN_METRIC
|
131
|
-
"Errors/#{options[:metric]}"
|
132
|
-
else
|
133
|
-
"Errors/#{txn.best_name}" if txn
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def aggregated_metric_names(txn)
|
138
|
-
metric_names = ["Errors/all"]
|
139
|
-
return metric_names unless txn
|
96
|
+
# Checks the provided error against the error filter, if there
|
97
|
+
# is an error filter
|
98
|
+
def filtered_by_error_filter?(error)
|
99
|
+
respond_to?(:ignore_filter_proc) && !ignore_filter_proc(error)
|
100
|
+
end
|
140
101
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
102
|
+
# Checks the array of error names and the error filter against
|
103
|
+
# the provided error
|
104
|
+
def filtered_error?(error)
|
105
|
+
@ignore[error.class.name] || filtered_by_error_filter?(error)
|
106
|
+
end
|
146
107
|
|
147
|
-
|
148
|
-
|
108
|
+
# an error is ignored if it is nil or if it is filtered
|
109
|
+
def error_is_ignored?(error)
|
110
|
+
error && filtered_error?(error)
|
111
|
+
rescue => e
|
112
|
+
NewRelic::Agent.logger.error("Error '#{error}' will NOT be ignored. Exception '#{e}' while determining whether to ignore or not.", e)
|
113
|
+
false
|
114
|
+
end
|
149
115
|
|
150
|
-
|
151
|
-
|
152
|
-
|
116
|
+
def seen?(txn, exception)
|
117
|
+
error_ids = txn.nil? ? [] : txn.noticed_error_ids
|
118
|
+
error_ids.include?(exception.object_id)
|
119
|
+
end
|
153
120
|
|
154
|
-
|
155
|
-
|
156
|
-
|
121
|
+
def tag_as_seen(state, exception)
|
122
|
+
txn = state.current_transaction
|
123
|
+
txn.noticed_error_ids << exception.object_id if txn
|
124
|
+
end
|
157
125
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
126
|
+
def blamed_metric_name(txn, options)
|
127
|
+
if options[:metric] && options[:metric] != ::NewRelic::Agent::UNKNOWN_METRIC
|
128
|
+
"Errors/#{options[:metric]}"
|
129
|
+
else
|
130
|
+
"Errors/#{txn.best_name}" if txn
|
162
131
|
end
|
132
|
+
end
|
163
133
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
exception.nil? ||
|
168
|
-
seen?(state.current_transaction, exception)
|
169
|
-
end
|
134
|
+
def aggregated_metric_names(txn)
|
135
|
+
metric_names = ["Errors/all"]
|
136
|
+
return metric_names unless txn
|
170
137
|
|
171
|
-
|
172
|
-
|
173
|
-
|
138
|
+
if txn.recording_web_transaction?
|
139
|
+
metric_names << "Errors/allWeb"
|
140
|
+
else
|
141
|
+
metric_names << "Errors/allOther"
|
174
142
|
end
|
175
143
|
|
176
|
-
|
177
|
-
|
178
|
-
def uri_ref_and_root(options)
|
179
|
-
{
|
180
|
-
:request_uri => fetch_from_options(options, :uri, ''),
|
181
|
-
:request_referer => fetch_from_options(options, :referer, ''),
|
182
|
-
:rails_root => NewRelic::Control.instance.root
|
183
|
-
}
|
184
|
-
end
|
144
|
+
metric_names
|
145
|
+
end
|
185
146
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
if Agent.config[:'error_collector.capture_attributes']
|
190
|
-
fetch_from_options(options, :custom_params, {}).merge(options)
|
191
|
-
else
|
192
|
-
{}
|
193
|
-
end
|
194
|
-
end
|
147
|
+
# Increments a statistic that tracks total error rate
|
148
|
+
def increment_error_count!(state, exception, options={})
|
149
|
+
txn = state.current_transaction
|
195
150
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
def request_params_from_opts(options)
|
200
|
-
value = options.delete(:request_params)
|
201
|
-
if Agent.config[:capture_params]
|
202
|
-
value
|
203
|
-
else
|
204
|
-
nil
|
205
|
-
end
|
206
|
-
end
|
151
|
+
metric_names = aggregated_metric_names(txn)
|
152
|
+
blamed_metric = blamed_metric_name(txn, options)
|
153
|
+
metric_names << blamed_metric if blamed_metric
|
207
154
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
{
|
212
|
-
:request_params => normalize_params(request_params_from_opts(options)),
|
213
|
-
:custom_params => normalize_params(custom_params_from_opts(options))
|
214
|
-
}
|
215
|
-
end
|
216
|
-
|
217
|
-
# Merges together many of the options into something that can
|
218
|
-
# actually be attached to the error
|
219
|
-
def error_params_from_options(options)
|
220
|
-
uri_ref_and_root(options).merge(normalized_request_and_custom_params(options))
|
155
|
+
stats_engine = NewRelic::Agent.agent.stats_engine
|
156
|
+
stats_engine.record_unscoped_metrics(state, metric_names) do |stats|
|
157
|
+
stats.increment_count
|
221
158
|
end
|
159
|
+
end
|
222
160
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
161
|
+
def skip_notice_error?(state, exception)
|
162
|
+
disabled? ||
|
163
|
+
error_is_ignored?(exception) ||
|
164
|
+
exception.nil? ||
|
165
|
+
seen?(state.current_transaction, exception)
|
166
|
+
end
|
229
167
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
168
|
+
# calls a method on an object, if it responds to it - used for
|
169
|
+
# detection and soft fail-safe. Returns nil if the method does
|
170
|
+
# not exist
|
171
|
+
def sense_method(object, method)
|
172
|
+
object.send(method) if object.respond_to?(method)
|
173
|
+
end
|
235
174
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
:file_name => sense_method(exception, 'file_name'),
|
242
|
-
:line_number => sense_method(exception, 'line_number'),
|
243
|
-
:stack_trace => extract_stack_trace(exception)
|
244
|
-
}
|
245
|
-
end
|
175
|
+
# extracts a stack trace from the exception for debugging purposes
|
176
|
+
def extract_stack_trace(exception)
|
177
|
+
actual_exception = sense_method(exception, 'original_exception') || exception
|
178
|
+
sense_method(actual_exception, 'backtrace') || '<no stack trace>'
|
179
|
+
end
|
246
180
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
181
|
+
# checks the size of the error queue to make sure we are under
|
182
|
+
# the maximum limit, and logs a warning if we are over the limit.
|
183
|
+
def over_queue_limit?(message)
|
184
|
+
over_limit = (@errors.reject{|err| err.is_internal}.length >= MAX_ERROR_QUEUE_LENGTH)
|
185
|
+
::NewRelic::Agent.logger.warn("The error reporting queue has reached #{MAX_ERROR_QUEUE_LENGTH}. The error detail for this and subsequent errors will not be transmitted to New Relic until the queued errors have been sent: #{message}") if over_limit
|
186
|
+
over_limit
|
187
|
+
end
|
254
188
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
end
|
189
|
+
# Synchronizes adding an error to the error queue, and checks if
|
190
|
+
# the error queue is too long - if so, we drop the error on the
|
191
|
+
# floor after logging a warning.
|
192
|
+
def add_to_error_queue(noticed_error)
|
193
|
+
@lock.synchronize do
|
194
|
+
if !over_queue_limit?(noticed_error.message) && !@errors.include?(noticed_error)
|
195
|
+
@errors << noticed_error
|
263
196
|
end
|
264
197
|
end
|
265
198
|
end
|
266
199
|
|
267
|
-
|
268
|
-
|
200
|
+
# See NewRelic::Agent.notice_error for options and commentary
|
269
201
|
|
270
|
-
# Notice the error with the given available options:
|
271
|
-
#
|
272
|
-
# * <tt>:uri</tt> => The request path, minus any request params or query string.
|
273
|
-
# * <tt>:referer</tt> => The URI of the referer
|
274
|
-
# * <tt>:metric</tt> => The metric name associated with the transaction
|
275
|
-
# * <tt>:request_params</tt> => Request parameters, already filtered if necessary
|
276
|
-
# * <tt>:custom_params</tt> => Custom parameters
|
277
|
-
#
|
278
|
-
# If anything is left over, it's added to custom params
|
279
|
-
# If exception is nil, the error count is bumped and no traced error is recorded
|
280
202
|
def notice_error(exception, options={}) #THREAD_LOCAL_ACCESS
|
281
203
|
state = ::NewRelic::Agent::TransactionState.tl_get
|
282
204
|
|
283
205
|
return if skip_notice_error?(state, exception)
|
284
|
-
tag_as_seen(state, exception)
|
285
206
|
|
207
|
+
tag_as_seen(state, exception)
|
286
208
|
increment_error_count!(state, exception, options)
|
287
|
-
|
288
|
-
|
289
|
-
action_path = fetch_from_options(options, :metric, "")
|
290
|
-
exception_options = error_params_from_options(options).merge(exception_info(exception))
|
291
|
-
add_to_error_queue(NewRelic::NoticedError.new(action_path, exception_options, exception))
|
209
|
+
add_to_error_queue(create_noticed_error(exception, options))
|
292
210
|
|
293
211
|
exception
|
294
212
|
rescue => e
|
295
213
|
::NewRelic::Agent.logger.warn("Failure when capturing error '#{exception}':", e)
|
296
214
|
end
|
297
215
|
|
216
|
+
EMPTY_STRING = ''.freeze
|
217
|
+
|
218
|
+
def create_noticed_error(exception, options)
|
219
|
+
error_metric = options.delete(:metric) || EMPTY_STRING
|
220
|
+
|
221
|
+
noticed_error = NewRelic::NoticedError.new(error_metric, exception)
|
222
|
+
noticed_error.request_uri = options.delete(:uri) || EMPTY_STRING
|
223
|
+
noticed_error.attributes = options.delete(:attributes)
|
224
|
+
|
225
|
+
noticed_error.file_name = sense_method(exception, :file_name)
|
226
|
+
noticed_error.line_number = sense_method(exception, :line_number)
|
227
|
+
noticed_error.stack_trace = extract_stack_trace(exception)
|
228
|
+
|
229
|
+
handle_deprecated_options(options)
|
230
|
+
|
231
|
+
noticed_error.attributes_from_notice_error = options.delete(:custom_params) || {}
|
232
|
+
|
233
|
+
# Any options that are passed to notice_error which aren't known keys
|
234
|
+
# get treated as custom attributes, so merge them into that hash.
|
235
|
+
noticed_error.attributes_from_notice_error.merge!(options)
|
236
|
+
|
237
|
+
noticed_error
|
238
|
+
end
|
239
|
+
|
240
|
+
DEPRECATED_OPTIONS_MSG = "Passing %s to notice_error is no longer supported. Set values on the enclosing transaction or record them as custom attributes instead.".freeze
|
241
|
+
DEPRECATED_OPTIONS = [:request_params, :request, :referer].freeze
|
242
|
+
|
243
|
+
# Old options no longer used by notice_error can still be passed. If they
|
244
|
+
# are, they shouldn't get merged into custom attributes. Delete and
|
245
|
+
# warn callers so they can fix their calls to notice_error.
|
246
|
+
def handle_deprecated_options(options)
|
247
|
+
DEPRECATED_OPTIONS.each do |deprecated|
|
248
|
+
if options.include?(deprecated)
|
249
|
+
NewRelic::Agent.logger.warn(DEPRECATED_OPTIONS_MSG % deprecated)
|
250
|
+
options.delete(deprecated)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
298
255
|
# *Use sparingly for difficult to track bugs.*
|
299
256
|
#
|
300
257
|
# Track internal agent errors for communication back to New Relic.
|
@@ -315,9 +272,8 @@ module NewRelic
|
|
315
272
|
return if @errors.any? { |err| err.exception_class_name == exception.class.name }
|
316
273
|
|
317
274
|
trace = exception.backtrace || caller.dup
|
318
|
-
noticed_error = NewRelic::NoticedError.new("NewRelic/AgentError",
|
319
|
-
|
320
|
-
exception)
|
275
|
+
noticed_error = NewRelic::NoticedError.new("NewRelic/AgentError", exception)
|
276
|
+
noticed_error.stack_trace = trace
|
321
277
|
@errors << noticed_error
|
322
278
|
end
|
323
279
|
rescue => e
|
@@ -0,0 +1,26 @@
|
|
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 HashExtensions
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# recurses through hashes and arrays and stringifies keys
|
11
|
+
def stringify_keys_in_object(object)
|
12
|
+
case object
|
13
|
+
when Hash
|
14
|
+
object.inject({}) do |memo, (k, v)|
|
15
|
+
memo[k.to_s] = stringify_keys_in_object(v)
|
16
|
+
memo
|
17
|
+
end
|
18
|
+
when Array
|
19
|
+
object.map {|o| stringify_keys_in_object(o)}
|
20
|
+
else
|
21
|
+
object
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|