newrelic_rpm 3.10.0.279 → 3.11.0.283
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +61 -0
- data/lib/new_relic/agent.rb +14 -8
- data/lib/new_relic/agent/agent.rb +43 -28
- data/lib/new_relic/agent/agent_logger.rb +21 -20
- data/lib/new_relic/agent/configuration/default_source.rb +31 -1
- data/lib/new_relic/agent/database.rb +2 -1
- data/lib/new_relic/agent/datastores.rb +177 -0
- data/lib/new_relic/agent/datastores/metric_helper.rb +85 -0
- data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +11 -20
- data/lib/new_relic/agent/deprecator.rb +18 -0
- data/lib/new_relic/agent/instrumentation/active_record.rb +20 -35
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +116 -57
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +11 -20
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +104 -172
- data/lib/new_relic/agent/instrumentation/memcache.rb +104 -52
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +9 -0
- data/lib/new_relic/agent/instrumentation/middleware_proxy.rb +15 -2
- data/lib/new_relic/agent/instrumentation/mongo.rb +5 -18
- data/lib/new_relic/agent/instrumentation/sequel_helper.rb +36 -0
- data/lib/new_relic/agent/new_relic_service.rb +4 -0
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +2 -17
- data/lib/new_relic/agent/threading/backtrace_service.rb +28 -5
- data/lib/new_relic/agent/transaction.rb +63 -34
- data/lib/new_relic/agent/transaction_event_aggregator.rb +0 -4
- data/lib/new_relic/agent/transaction_sampler.rb +11 -5
- data/lib/new_relic/rack/error_collector.rb +0 -1
- data/lib/new_relic/version.rb +1 -1
- data/lib/sequel/extensions/newrelic_instrumentation.rb +28 -56
- data/lib/sequel/plugins/newrelic_instrumentation.rb +28 -45
- data/newrelic_rpm.gemspec +0 -7
- data/test/agent_helper.rb +35 -16
- data/test/environments/rails31/Gemfile +1 -0
- data/test/environments/rails32/Gemfile +1 -0
- data/test/helpers/mongo_metric_builder.rb +2 -3
- data/test/multiverse/lib/multiverse/output_collector.rb +24 -9
- data/test/multiverse/lib/multiverse/suite.rb +5 -0
- data/test/multiverse/suites/active_record/Envfile +6 -4
- data/test/multiverse/suites/active_record/active_record_test.rb +32 -73
- data/test/multiverse/suites/active_record/ar_method_aliasing.rb +0 -1
- data/test/multiverse/suites/activemerchant/activemerchant_test.rb +0 -3
- data/test/multiverse/suites/agent_only/agent_run_id_handling_test.rb +0 -1
- data/test/multiverse/suites/agent_only/audit_log_test.rb +0 -1
- data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +0 -2
- data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +0 -1
- data/test/multiverse/suites/agent_only/custom_analytics_events_test.rb +0 -2
- data/test/multiverse/suites/agent_only/custom_queue_time_test.rb +0 -1
- data/test/multiverse/suites/agent_only/encoding_handling_test.rb +0 -2
- data/test/multiverse/suites/agent_only/exclusive_time_test.rb +0 -2
- data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +0 -1
- data/test/multiverse/suites/agent_only/http_response_code_test.rb +0 -1
- data/test/multiverse/suites/agent_only/keepalive_test.rb +0 -1
- data/test/multiverse/suites/agent_only/key_transactions_test.rb +54 -9
- data/test/multiverse/suites/agent_only/labels_test.rb +0 -2
- data/test/multiverse/suites/agent_only/logging_test.rb +0 -1
- data/test/multiverse/suites/agent_only/marshaling_test.rb +0 -1
- data/test/multiverse/suites/agent_only/pipe_manager_test.rb +0 -2
- data/test/multiverse/suites/agent_only/rename_rule_test.rb +5 -7
- data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +0 -1
- data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +0 -2
- data/test/multiverse/suites/agent_only/ssl_test.rb +0 -2
- data/test/multiverse/suites/agent_only/synthetics_test.rb +0 -1
- data/test/multiverse/suites/agent_only/testing_app.rb +21 -0
- data/test/multiverse/suites/agent_only/thread_profiling_test.rb +1 -2
- data/test/multiverse/suites/agent_only/transaction_ignoring_test.rb +0 -2
- data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +0 -1
- data/test/multiverse/suites/agent_only/xray_sessions_test.rb +69 -34
- data/test/multiverse/suites/capistrano/deployment_test.rb +0 -1
- data/test/multiverse/suites/capistrano2/deployment_test.rb +0 -1
- data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +0 -2
- data/test/multiverse/suites/curb/curb_test.rb +0 -2
- data/test/multiverse/suites/datamapper/Envfile +26 -3
- data/test/multiverse/suites/datamapper/config/newrelic.yml +1 -0
- data/test/multiverse/suites/datamapper/datamapper_test.rb +271 -37
- data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +0 -1
- data/test/multiverse/suites/delayed_job/Envfile +31 -8
- data/test/multiverse/suites/delayed_job/delayed_job_sampler_test.rb +0 -3
- data/test/multiverse/suites/delayed_job/unsupported_backend_test.rb +0 -3
- data/test/multiverse/suites/excon/excon_test.rb +0 -2
- data/test/multiverse/suites/grape/grape_test.rb +0 -3
- data/test/multiverse/suites/grape/grape_versioning_test.rb +0 -3
- data/test/multiverse/suites/grape/unsupported_version_test.rb +0 -3
- data/test/multiverse/suites/high_security/high_security_test.rb +0 -1
- data/test/multiverse/suites/httpclient/httpclient_test.rb +0 -2
- data/test/multiverse/suites/json/json_test.rb +0 -1
- data/test/multiverse/suites/marshalling/marshalling_test.rb +0 -1
- data/test/multiverse/suites/memcached/Envfile +52 -0
- data/test/multiverse/suites/memcached/dalli_test.rb +89 -0
- data/test/multiverse/suites/memcached/memcache_client_test.rb +25 -0
- data/test/multiverse/suites/memcached/memcache_test_cases.rb +302 -0
- data/test/multiverse/suites/memcached/memcached_test.rb +159 -0
- data/test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb +26 -17
- data/test/multiverse/suites/mongo/mongo_connection_test.rb +0 -1
- data/test/multiverse/suites/mongo/mongo_instrumentation_test.rb +0 -1
- data/test/multiverse/suites/mongo/mongo_unsupported_version_test.rb +0 -1
- data/test/multiverse/suites/net_http/net_http_test.rb +0 -2
- data/test/multiverse/suites/padrino/padrino_test.rb +0 -3
- data/test/multiverse/suites/rack/http_response_code_test.rb +0 -1
- data/test/multiverse/suites/rack/nested_non_rack_app_test.rb +1 -1
- data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +12 -12
- data/test/multiverse/suites/rack/rack_cascade_test.rb +0 -1
- data/test/multiverse/suites/rack/rack_env_mutation_test.rb +0 -1
- data/test/multiverse/suites/rack/rack_parameter_filtering_test.rb +0 -1
- data/test/multiverse/suites/rack/rack_unsupported_version_test.rb +0 -2
- data/test/multiverse/suites/rack/url_map_test.rb +3 -2
- data/test/multiverse/suites/rails/Envfile +3 -0
- data/test/multiverse/suites/rails/activejob_test.rb +0 -1
- data/test/multiverse/suites/rails/app.rb +0 -1
- data/test/multiverse/suites/rails/parameter_capture_test.rb +13 -0
- data/test/multiverse/suites/rails/rails3_app/app_rails3_plus.rb +5 -0
- data/test/multiverse/suites/rails/transaction_ignoring_test.rb +0 -2
- data/test/multiverse/suites/resque/instrumentation_test.rb +0 -2
- data/test/multiverse/suites/resque/resque_marshalling_test.rb +0 -1
- data/test/multiverse/suites/sequel/sequel_extension_test.rb +135 -0
- data/test/multiverse/suites/sequel/sequel_helpers.rb +62 -0
- data/test/multiverse/suites/sequel/sequel_plugin_test.rb +230 -0
- data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +0 -2
- data/test/multiverse/suites/sinatra/ignoring_test.rb +0 -2
- data/test/multiverse/suites/sinatra/nested_middleware_test.rb +0 -2
- data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +0 -1
- data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +0 -2
- data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +14 -12
- data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +0 -1
- data/test/multiverse/suites/sinatra/sinatra_routes_test.rb +0 -2
- data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +0 -2
- data/test/multiverse/suites/typhoeus/typhoeus_test.rb +0 -2
- data/test/multiverse/suites/yajl/yajl_test.rb +0 -1
- data/test/new_relic/agent/agent/start_test.rb +2 -2
- data/test/new_relic/agent/agent_logger_test.rb +6 -3
- data/test/new_relic/agent/datastores/metric_helper_test.rb +61 -0
- data/test/new_relic/agent/datastores/mongo/metric_translator_test.rb +20 -21
- data/test/new_relic/agent/datastores_test.rb +195 -0
- data/test/new_relic/agent/deprecator_test.rb +52 -0
- data/test/new_relic/agent/instrumentation/action_view_subscriber_test.rb +20 -26
- data/test/new_relic/agent/instrumentation/active_record_helper_test.rb +58 -53
- data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +7 -20
- data/test/new_relic/agent/instrumentation/middleware_proxy_test.rb +19 -0
- data/test/new_relic/agent/instrumentation/sequel_helper_test.rb +36 -0
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +1 -0
- data/test/new_relic/agent/method_tracer_test.rb +3 -4
- data/test/new_relic/agent/pipe_channel_manager_test.rb +1 -1
- data/test/new_relic/agent/threading/backtrace_service_test.rb +29 -4
- data/test/new_relic/agent/transaction_event_aggregator_test.rb +0 -4
- data/test/new_relic/agent/transaction_test.rb +100 -2
- data/test/new_relic/agent_test.rb +3 -3
- data/test/new_relic/http_client_test_cases.rb +0 -1
- data/test/new_relic/multiverse_helpers.rb +7 -0
- data/test/new_relic/transaction_ignoring_test_cases.rb +0 -2
- data/test/new_relic/transaction_sample_test.rb +11 -2
- data/test/performance/README.md +37 -17
- data/test/performance/lib/performance.rb +1 -0
- data/test/performance/lib/performance/baseline_compare_reporter.rb +11 -7
- data/test/performance/lib/performance/console_reporter.rb +29 -5
- data/test/performance/lib/performance/formatting_helpers.rb +22 -0
- data/test/performance/lib/performance/instrumentation/stackprof.rb +11 -1
- data/test/performance/lib/performance/result.rb +17 -6
- data/test/performance/lib/performance/runner.rb +7 -3
- data/test/performance/lib/performance/test_case.rb +89 -21
- data/test/performance/script/runner +13 -1
- data/test/performance/suites/active_record.rb +47 -0
- data/test/performance/suites/config.rb +4 -48
- data/test/performance/suites/marshalling.rb +20 -30
- data/test/performance/suites/queue_time.rb +1 -1
- data/test/performance/suites/rack_middleware.rb +1 -1
- data/test/performance/suites/rum_autoinsertion.rb +1 -1
- data/test/performance/suites/sql_obfuscation.rb +2 -2
- data/test/performance/suites/startup.rb +1 -1
- data/test/performance/suites/stats_hash.rb +7 -11
- data/test/performance/suites/thread_profiling.rb +20 -25
- data/test/performance/suites/trace_execution_scoped.rb +2 -2
- data/test/performance/suites/transaction_tracing.rb +4 -2
- data/test/test_helper.rb +5 -1
- metadata +53 -100
- data.tar.gz.sig +0 -0
- data/gem-public_cert.pem +0 -20
- data/lib/new_relic/agent/datastores/mongo/metric_generator.rb +0 -33
- data/test/multiverse/suites/sequel/sequel_instrumentation_test.rb +0 -289
- data/test/new_relic/agent/datastores/mongo/metric_generator_test.rb +0 -69
- data/test/new_relic/agent/memcache_instrumentation_test.rb +0 -155
- metadata.gz.sig +0 -2
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4556b4a30019cb741eba3e669f57af080c0189e3
|
4
|
+
data.tar.gz: cc3e6812a23b94c1e5ea69a6ccc442afb5c08ad7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d758439faefa78cb3673721f575f8cdf07caadcafd124e6d61f16676a3bd76874d8a92d0817e564bf8842ab19e1e494a0a80597a0872c6cc158b8db0dc7b1212
|
7
|
+
data.tar.gz: a14aa6eb45971e5b4f9ddc45376c3ef8d0b737cfb968bd07ffe48f77855abe80a9ce0091490f8927b37c988ad4df3b861257e46684b2c815e585f77207b1cbd6
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,66 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes #
|
2
2
|
|
3
|
+
## v3.11.0 ##
|
4
|
+
|
5
|
+
* Unified view for SQL database and NoSQL datastore products.
|
6
|
+
|
7
|
+
The response time charts in the application overview page will now include
|
8
|
+
NoSQL datastores, such as MongoDB, and also the product name of existing SQL
|
9
|
+
databases such as MySQL, Postgres, etc.
|
10
|
+
|
11
|
+
The Databases page will now enable the filtering of metrics and operations
|
12
|
+
by product, and includes a table listing all operations.
|
13
|
+
|
14
|
+
For existing SQL databases, in addition to the existing breakdown of SQL
|
15
|
+
statements and operations, the queries are now also associated with the
|
16
|
+
database product being used.
|
17
|
+
|
18
|
+
For NoSQL datastores, such as MongoDB, we have now added information about
|
19
|
+
operations performed against those products, similar to what is being done
|
20
|
+
for SQL databases.
|
21
|
+
|
22
|
+
Because this introduces a notable change to how SQL database metrics are
|
23
|
+
collected, it is important that you upgrade the agent version on all hosts.
|
24
|
+
If you are unable to transition to the latest agent version on all hosts at
|
25
|
+
the same time, you can still access old and new metric data for SQL
|
26
|
+
databases, but the information will be split across two separate views.
|
27
|
+
|
28
|
+
For more information see https://docs.newrelic.com/docs/apm/applications-menu/monitoring/databases-slow-queries-dashboard
|
29
|
+
|
30
|
+
* Track background transactions as Key Transactions
|
31
|
+
|
32
|
+
In prior versions of the Ruby agent, only web transactions could be tracked
|
33
|
+
as Key Transactions. This functionality is now available to all
|
34
|
+
transactions, including custom Apdex values and X-Ray sessions.
|
35
|
+
|
36
|
+
For more information see https://docs.newrelic.com/docs/apm/selected-transactions/key-transactions/key-transactions-tracking-important-transactions-or-events
|
37
|
+
|
38
|
+
* More support and documentation for third-party extensions
|
39
|
+
|
40
|
+
It's always been possible to write extension gems for the Ruby agent, but
|
41
|
+
now there's one location with best practices and recommendations to guide
|
42
|
+
you in writing extensions. Check out
|
43
|
+
https://docs.newrelic.com/docs/agents/ruby-agent/frameworks/third-party-instrumentation
|
44
|
+
|
45
|
+
We've also added simpler APIs for tracing datastores and testing your
|
46
|
+
extensions. It's our way of giving back to everyone who's helped build on
|
47
|
+
the agent over the years. <3
|
48
|
+
|
49
|
+
* Fix for anonymous class middleware naming
|
50
|
+
|
51
|
+
Metric names based off anonymous middlewares lacked a class name in the UI.
|
52
|
+
The Ruby agent will now look for a superclass, or default to AnonymousClass
|
53
|
+
in those cases.
|
54
|
+
|
55
|
+
* Improved exit behavior in the presence of Sinatra
|
56
|
+
|
57
|
+
The agent uses an `at_exit` hook to ensure data from the last < 60s before a
|
58
|
+
process exits is sent to New Relic. Previously, this hook was skipped if
|
59
|
+
Sinatra::Application was defined. This unfortunately missed data for
|
60
|
+
short-lived background processes that required, but didn't run, Sinatra. Now
|
61
|
+
the agent only skips its `at_exit` hook if Sinatra actually runs from
|
62
|
+
`at_exit`.
|
63
|
+
|
3
64
|
## v3.10.0 ##
|
4
65
|
|
5
66
|
* Support for the Grape framework
|
data/lib/new_relic/agent.rb
CHANGED
@@ -313,6 +313,14 @@ module NewRelic
|
|
313
313
|
agent.drop_buffered_data
|
314
314
|
end
|
315
315
|
|
316
|
+
# Require agent testing helper methods
|
317
|
+
#
|
318
|
+
# @api public
|
319
|
+
def require_test_helper
|
320
|
+
path = File.join(__FILE__, '..', '..', '..', 'test', 'agent_helper')
|
321
|
+
require File.expand_path(path)
|
322
|
+
end
|
323
|
+
|
316
324
|
# Deprecated in favor of drop_buffered_data
|
317
325
|
#
|
318
326
|
# @api public
|
@@ -608,16 +616,14 @@ module NewRelic
|
|
608
616
|
end
|
609
617
|
end
|
610
618
|
|
611
|
-
# Yield to a block that is run with a database metric name
|
612
|
-
#
|
613
|
-
#
|
614
|
-
# This is re-entrant.
|
619
|
+
# Yield to a block that is run with a database metric name context. This means
|
620
|
+
# the Database instrumentation will use this for the metric name if it does not
|
621
|
+
# otherwise know about a model. This is re-entrant.
|
615
622
|
#
|
616
|
-
#
|
617
|
-
# * <tt>method</tt> is the name of the finder method or other
|
618
|
-
# method to identify the operation with.
|
623
|
+
# @param [String,Class,#to_s] model the DB model class
|
619
624
|
#
|
620
|
-
# @
|
625
|
+
# @param [String] method the name of the finder method or other method to
|
626
|
+
# identify the operation with.
|
621
627
|
#
|
622
628
|
def with_database_metric_name(model, method, &block) #THREAD_LOCAL_ACCESS
|
623
629
|
if txn = Transaction.tl_current
|
@@ -337,37 +337,52 @@ module NewRelic
|
|
337
337
|
NewRelic::Agent.disable_all_tracing { connect(:keep_retrying => false) }
|
338
338
|
end
|
339
339
|
|
340
|
-
#
|
341
|
-
#
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
#
|
347
|
-
#
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
340
|
+
# This matters when the following three criteria are met:
|
341
|
+
#
|
342
|
+
# 1. A Sinatra 'classic' application is being run
|
343
|
+
# 2. The app is being run by executing the main file directly, rather
|
344
|
+
# than via a config.ru file.
|
345
|
+
# 3. newrelic_rpm is required *after* sinatra
|
346
|
+
#
|
347
|
+
# In this case, the entire application runs from an at_exit handler in
|
348
|
+
# Sinatra, and if we were to install ours, it would be executed before
|
349
|
+
# the one in Sinatra, meaning that we'd shutdown the agent too early
|
350
|
+
# and never collect any data.
|
351
|
+
def sinatra_classic_app?
|
352
|
+
(
|
353
|
+
defined?(Sinatra::Application) &&
|
354
|
+
Sinatra::Application.respond_to?(:run) &&
|
355
|
+
Sinatra::Application.run?
|
356
|
+
)
|
357
|
+
end
|
358
|
+
|
359
|
+
def should_install_exit_handler?
|
360
|
+
(
|
361
|
+
Agent.config[:send_data_on_exit] &&
|
362
|
+
!NewRelic::LanguageSupport.using_engine?('rbx') &&
|
363
|
+
!NewRelic::LanguageSupport.using_engine?('jruby') &&
|
364
|
+
!sinatra_classic_app?
|
365
|
+
)
|
366
|
+
end
|
367
|
+
|
368
|
+
# There's an MRI 1.9 bug that loses exit codes in at_exit blocks.
|
369
|
+
# A workaround is necessary to get correct exit codes for the agent's
|
370
|
+
# test suites.
|
371
|
+
# http://bugs.ruby-lang.org/issues/5218
|
372
|
+
def need_exit_code_workaround?
|
373
|
+
defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/)
|
352
374
|
end
|
353
375
|
|
354
|
-
# Installs our exit handler, which exploits the weird
|
355
|
-
# behavior of at_exit blocks to make sure it runs last, by
|
356
|
-
# doing an at_exit within an at_exit block.
|
357
376
|
def install_exit_handler
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
exit exit_status if exit_status
|
368
|
-
else
|
369
|
-
shutdown
|
370
|
-
end
|
377
|
+
return unless should_install_exit_handler?
|
378
|
+
NewRelic::Agent.logger.debug("Installing at_exit handler")
|
379
|
+
at_exit do
|
380
|
+
if need_exit_code_workaround?
|
381
|
+
exit_status = $!.status if $!.is_a?(SystemExit)
|
382
|
+
shutdown
|
383
|
+
exit exit_status if exit_status
|
384
|
+
else
|
385
|
+
shutdown
|
371
386
|
end
|
372
387
|
end
|
373
388
|
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
|
|
5
|
+
require 'thread'
|
5
6
|
require 'logger'
|
6
7
|
require 'new_relic/agent/hostname'
|
7
8
|
|
@@ -9,9 +10,8 @@ module NewRelic
|
|
9
10
|
module Agent
|
10
11
|
class AgentLogger
|
11
12
|
|
12
|
-
attr_reader :already_logged
|
13
|
-
|
14
13
|
def initialize(root = "", override_logger=nil)
|
14
|
+
@already_logged_lock = Mutex.new
|
15
15
|
clear_already_logged
|
16
16
|
create_log(root, override_logger)
|
17
17
|
set_log_level!
|
@@ -43,25 +43,24 @@ module NewRelic
|
|
43
43
|
NUM_LOG_ONCE_KEYS = 1000
|
44
44
|
|
45
45
|
def log_once(level, key, *msgs)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
46
|
+
@already_logged_lock.synchronize do
|
47
|
+
return if @already_logged.include?(key)
|
48
|
+
|
49
|
+
if @already_logged.size >= NUM_LOG_ONCE_KEYS && key.kind_of?(String)
|
50
|
+
# The reason for preventing too many keys in `logged` is for
|
51
|
+
# memory concerns.
|
52
|
+
# The reason for checking the type of the key is that we always want
|
53
|
+
# to allow symbols to log, since there are very few of them.
|
54
|
+
# The assumption here is that you would NEVER pass dynamically-created
|
55
|
+
# symbols, because you would never create symbols dynamically in the
|
56
|
+
# first place, as that would already be a memory leak in most Rubies,
|
57
|
+
# even if we didn't hang on to them all here.
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
@already_logged[key] = true
|
62
62
|
end
|
63
63
|
|
64
|
-
logged[key] = true
|
65
64
|
self.send(level, *msgs)
|
66
65
|
end
|
67
66
|
|
@@ -148,7 +147,9 @@ module NewRelic
|
|
148
147
|
end
|
149
148
|
|
150
149
|
def clear_already_logged
|
151
|
-
@
|
150
|
+
@already_logged_lock.synchronize do
|
151
|
+
@already_logged = {}
|
152
|
+
end
|
152
153
|
end
|
153
154
|
|
154
155
|
def wants_stdout?
|
@@ -306,7 +306,7 @@ module NewRelic
|
|
306
306
|
:description => 'Defines a host for communicating with New Relic via a proxy server.'
|
307
307
|
},
|
308
308
|
:proxy_port => {
|
309
|
-
:default =>
|
309
|
+
:default => 8080,
|
310
310
|
:allow_nil => true,
|
311
311
|
:public => true,
|
312
312
|
:type => Fixnum,
|
@@ -595,6 +595,12 @@ module NewRelic
|
|
595
595
|
:type => Boolean,
|
596
596
|
:description => 'Enable or disable active record instrumentation.'
|
597
597
|
},
|
598
|
+
:disable_data_mapper => {
|
599
|
+
:default => false,
|
600
|
+
:public => true,
|
601
|
+
:type => Boolean,
|
602
|
+
:description => 'Enable or disable DataMapper instrumentation.'
|
603
|
+
},
|
598
604
|
:disable_activejob => {
|
599
605
|
:default => false,
|
600
606
|
:public => true,
|
@@ -602,6 +608,30 @@ module NewRelic
|
|
602
608
|
:dynamic_name => true,
|
603
609
|
:description => 'Enable or disable ActiveJob instrumentation.'
|
604
610
|
},
|
611
|
+
:disable_memcached => {
|
612
|
+
:default => value_of(:disable_memcache_instrumentation),
|
613
|
+
:public => true,
|
614
|
+
:type => Boolean,
|
615
|
+
:description => 'Enable or disable instrumentation for the memcached gem.'
|
616
|
+
},
|
617
|
+
:disable_memcache_client => {
|
618
|
+
:default => value_of(:disable_memcache_instrumentation),
|
619
|
+
:public => true,
|
620
|
+
:type => Boolean,
|
621
|
+
:description => 'Enable or disable instrumenation for the memcache-client gem.'
|
622
|
+
},
|
623
|
+
:disable_dalli => {
|
624
|
+
:default => value_of(:disable_memcache_instrumentation),
|
625
|
+
:public => true,
|
626
|
+
:type => Boolean,
|
627
|
+
:description => 'Enable or disable instrumentation for the dalli gem.'
|
628
|
+
},
|
629
|
+
:disable_dalli_cas_client => {
|
630
|
+
:default => value_of(:disable_memcache_instrumentation),
|
631
|
+
:public => true,
|
632
|
+
:type => Boolean,
|
633
|
+
:description => "Enable or disable instrumentation for the dalli gem's additional CAS client support."
|
634
|
+
},
|
605
635
|
:disable_memcache_instrumentation => {
|
606
636
|
:default => false,
|
607
637
|
:public => true,
|
@@ -250,9 +250,10 @@ module NewRelic
|
|
250
250
|
]
|
251
251
|
|
252
252
|
SQL_COMMENT_REGEX = Regexp.new('/\*.*?\*/', Regexp::MULTILINE).freeze
|
253
|
+
EMPTY_STRING = ''.freeze
|
253
254
|
|
254
255
|
def parse_operation_from_query(sql)
|
255
|
-
sql = sql.gsub(SQL_COMMENT_REGEX,
|
256
|
+
sql = sql.gsub(SQL_COMMENT_REGEX, EMPTY_STRING)
|
256
257
|
if sql =~ /(\w+)/
|
257
258
|
op = $1.downcase
|
258
259
|
return op if KNOWN_OPERATIONS.include?(op)
|
@@ -0,0 +1,177 @@
|
|
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 'new_relic/agent/datastores/metric_helper'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Datastores
|
10
|
+
|
11
|
+
# Add Datastore tracing to a method. This properly generates the metrics
|
12
|
+
# for New Relic's Datastore features. It does not capture the actual
|
13
|
+
# query content into Transaction Traces. Use wrap if you want to provide
|
14
|
+
# that functionality.
|
15
|
+
#
|
16
|
+
# @param [Class] clazz the class to instrument
|
17
|
+
#
|
18
|
+
# @param [String, Symbol] method_name the name of instance method to
|
19
|
+
# instrument
|
20
|
+
#
|
21
|
+
# @param [String] product name of your datastore for use in metric naming, e.g. "Redis"
|
22
|
+
#
|
23
|
+
# @param [optional,String] operation the name of operation if different
|
24
|
+
# than the instrumented method name
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
#
|
28
|
+
def self.trace(clazz, method_name, product, operation = method_name)
|
29
|
+
clazz.class_eval do
|
30
|
+
method_name_without_newrelic = "#{method_name}_without_newrelic"
|
31
|
+
|
32
|
+
if NewRelic::Helper.instance_methods_include?(clazz, method_name) &&
|
33
|
+
!NewRelic::Helper.instance_methods_include?(clazz, method_name_without_newrelic)
|
34
|
+
|
35
|
+
visibility = NewRelic::Helper.instance_method_visibility(clazz, method_name)
|
36
|
+
|
37
|
+
alias_method method_name_without_newrelic, method_name
|
38
|
+
|
39
|
+
define_method(method_name) do |*args, &blk|
|
40
|
+
metrics = MetricHelper.metrics_for(product, operation)
|
41
|
+
NewRelic::Agent::MethodTracer.trace_execution_scoped(metrics) do
|
42
|
+
send(method_name_without_newrelic, *args, &blk)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
send visibility, method_name
|
47
|
+
send visibility, method_name_without_newrelic
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Wrap a call to a datastore and record New Relic Datastore metrics. This
|
53
|
+
# method can be used when a collection (i.e. table or model name) is
|
54
|
+
# known at runtime to be included in the metric naming. It is intended
|
55
|
+
# for situations that the simpler NewRelic::Agent::Datastores.trace can't
|
56
|
+
# properly handle.
|
57
|
+
#
|
58
|
+
# To use this, wrap the datastore operation in the block passed to wrap.
|
59
|
+
#
|
60
|
+
# NewRelic::Agent::Datastores.wrap("FauxDB", "find", "items") do
|
61
|
+
# FauxDB.find(query)
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# @param [String] product the datastore name for use in metric naming,
|
65
|
+
# e.g. "FauxDB"
|
66
|
+
#
|
67
|
+
# @param [String,Symbol] operation the name of operation (e.g. "select"),
|
68
|
+
# often named after the method that's being instrumented.
|
69
|
+
#
|
70
|
+
# @param [optional, String] collection the collection name for use in
|
71
|
+
# statement-level metrics (i.e. table or model name)
|
72
|
+
#
|
73
|
+
# @param [Proc,#call] callback proc or other callable to invoke after
|
74
|
+
# running the datastore block. Receives three arguments: result of the
|
75
|
+
# yield, the most specific (scoped) metric name, and elapsed time of the
|
76
|
+
# call. An example use is attaching SQL to Transaction Traces at the end
|
77
|
+
# of a wrapped datastore call.
|
78
|
+
#
|
79
|
+
# callback = Proc.new do |result, metrics, elapsed|
|
80
|
+
# NewRelic::Agent::Datastores.notice_sql(query, metrics, elapsed)
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# NewRelic::Agent::Datastores.wrap("FauxDB", "find", "items", callback) do
|
84
|
+
# FauxDB.find(query)
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# **NOTE: THERE ARE SECURITY CONCERNS WHEN CAPTURING SQL!**
|
88
|
+
# New Relic's Transaction Tracing and Slow SQL features will
|
89
|
+
# attempt to apply obfuscation to the passed queries, but it is possible
|
90
|
+
# for a query format to be unsupported and result in exposing user
|
91
|
+
# information embedded within captured queries.
|
92
|
+
#
|
93
|
+
# @api public
|
94
|
+
#
|
95
|
+
def self.wrap(product, operation, collection = nil, callback = nil)
|
96
|
+
return yield unless operation
|
97
|
+
|
98
|
+
metrics = MetricHelper.metrics_for(product, operation, collection)
|
99
|
+
scoped_metric = metrics.first
|
100
|
+
NewRelic::Agent::MethodTracer.trace_execution_scoped(metrics) do
|
101
|
+
t0 = Time.now
|
102
|
+
begin
|
103
|
+
result = yield
|
104
|
+
ensure
|
105
|
+
if callback
|
106
|
+
elapsed_time = (Time.now - t0).to_f
|
107
|
+
callback.call(result, scoped_metric, elapsed_time)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Wrapper for simplifying attaching SQL queries during a transaction.
|
114
|
+
#
|
115
|
+
# If you are recording non-SQL data, please use the notice_statement
|
116
|
+
# method instead.
|
117
|
+
#
|
118
|
+
# NewRelic::Agent::Datastores.notice_sql(query, metrics, elapsed)
|
119
|
+
#
|
120
|
+
# @param [String] query the SQL text to be captured. Note that depending
|
121
|
+
# on user settings, this string will be run through obfuscation, but
|
122
|
+
# some dialects of SQL (or non-SQL queries) are not guaranteed to be
|
123
|
+
# properly obfuscated by these routines!
|
124
|
+
#
|
125
|
+
# @param [String] scoped_metric The most specific metric relating to this
|
126
|
+
# query. Typically the result of
|
127
|
+
# NewRelic::Agent::Datastores::MetricHelper#metrics_for
|
128
|
+
#
|
129
|
+
# @param [Float] elapsed the elapsed time during query execution
|
130
|
+
#
|
131
|
+
# **NOTE: THERE ARE SECURITY CONCERNS WHEN CAPTURING SQL!**
|
132
|
+
# New Relic's Transaction Tracing and Slow SQL features will
|
133
|
+
# attempt to apply obfuscation to the passed queries, but it is possible
|
134
|
+
# for a query format to be unsupported and result in exposing user
|
135
|
+
# information embedded within captured queries.
|
136
|
+
#
|
137
|
+
def self.notice_sql(query, scoped_metric, elapsed)
|
138
|
+
agent = NewRelic::Agent.instance
|
139
|
+
agent.transaction_sampler.notice_sql(query, nil, elapsed)
|
140
|
+
agent.sql_sampler.notice_sql(query, scoped_metric, nil, elapsed)
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
|
144
|
+
# Wrapper for simplifying attaching non-SQL data statements to a
|
145
|
+
# transaction. For instance, Mongo or CQL queries, Memcached or Redis
|
146
|
+
# keys would all be appropriate data to attach as statements.
|
147
|
+
#
|
148
|
+
# Data passed to this method is NOT obfuscated by New Relic, so please
|
149
|
+
# ensure that user information is obfuscated if the agent setting
|
150
|
+
# `transaction_tracer.record_sql` is set to `obfuscated`
|
151
|
+
#
|
152
|
+
# NewRelic::Agent::Datastores.notice_statement("key", elapsed)
|
153
|
+
#
|
154
|
+
# @param [String] statement text of the statement to capture.
|
155
|
+
#
|
156
|
+
# @param [Float] elapsed the elapsed time during query execution
|
157
|
+
#
|
158
|
+
# **NOTE: THERE ARE SECURITY CONCERNS WHEN CAPTURING STATEMENTS!**
|
159
|
+
# This method will properly ignore statements when the user has turned
|
160
|
+
# off capturing queries, but it is not able to obfuscate arbitrary data!
|
161
|
+
# To prevent exposing user information embedded in captured queries,
|
162
|
+
# please ensure all data passed to this method is safe to transmit to
|
163
|
+
# New Relic.
|
164
|
+
#
|
165
|
+
def self.notice_statement(statement, elapsed)
|
166
|
+
# Settings may change eventually, but for now we follow the same
|
167
|
+
# capture rules as SQL for non-SQL statements.
|
168
|
+
return unless NewRelic::Agent::Database.should_record_sql?
|
169
|
+
|
170
|
+
agent = NewRelic::Agent.instance
|
171
|
+
agent.transaction_sampler.notice_nosql_statement(statement, elapsed)
|
172
|
+
nil
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|