dolores_rpm 3.2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +559 -0
- data/LICENSE +64 -0
- data/README.rdoc +179 -0
- data/bin/mongrel_rpm +33 -0
- data/bin/newrelic +13 -0
- data/bin/newrelic_cmd +5 -0
- data/cert/cacert.pem +118 -0
- data/cert/oldsite.pem +28 -0
- data/cert/site.pem +27 -0
- data/dolores_rpm-3.3.4.fork.gem +0 -0
- data/install.rb +9 -0
- data/lib/conditional_vendored_dependency_detection.rb +3 -0
- data/lib/conditional_vendored_metric_parser.rb +5 -0
- data/lib/new_relic/agent/agent.rb +1311 -0
- data/lib/new_relic/agent/beacon_configuration.rb +110 -0
- data/lib/new_relic/agent/browser_monitoring.rb +102 -0
- data/lib/new_relic/agent/busy_calculator.rb +99 -0
- data/lib/new_relic/agent/chained_call.rb +13 -0
- data/lib/new_relic/agent/database.rb +203 -0
- data/lib/new_relic/agent/error_collector.rb +251 -0
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +27 -0
- data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +68 -0
- data/lib/new_relic/agent/instrumentation/authlogic.rb +19 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +424 -0
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +57 -0
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +52 -0
- data/lib/new_relic/agent/instrumentation/memcache.rb +80 -0
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +41 -0
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +29 -0
- data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +80 -0
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +332 -0
- data/lib/new_relic/agent/instrumentation/net.rb +29 -0
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +36 -0
- data/lib/new_relic/agent/instrumentation/queue_time.rb +210 -0
- data/lib/new_relic/agent/instrumentation/rack.rb +98 -0
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +114 -0
- data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +42 -0
- data/lib/new_relic/agent/instrumentation/rails/active_record_instrumentation.rb +115 -0
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +42 -0
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +118 -0
- data/lib/new_relic/agent/instrumentation/rails3/active_record_instrumentation.rb +122 -0
- data/lib/new_relic/agent/instrumentation/rails3/errors.rb +37 -0
- data/lib/new_relic/agent/instrumentation/sinatra.rb +58 -0
- data/lib/new_relic/agent/instrumentation/sunspot.rb +29 -0
- data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +21 -0
- data/lib/new_relic/agent/instrumentation.rb +9 -0
- data/lib/new_relic/agent/method_tracer.rb +528 -0
- data/lib/new_relic/agent/sampler.rb +50 -0
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +58 -0
- data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +40 -0
- data/lib/new_relic/agent/samplers/memory_sampler.rb +144 -0
- data/lib/new_relic/agent/samplers/object_sampler.rb +26 -0
- data/lib/new_relic/agent/shim_agent.rb +29 -0
- data/lib/new_relic/agent/sql_sampler.rb +267 -0
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +187 -0
- data/lib/new_relic/agent/stats_engine/samplers.rb +95 -0
- data/lib/new_relic/agent/stats_engine/transactions.rb +208 -0
- data/lib/new_relic/agent/stats_engine.rb +25 -0
- data/lib/new_relic/agent/transaction_sample_builder.rb +101 -0
- data/lib/new_relic/agent/transaction_sampler.rb +397 -0
- data/lib/new_relic/agent/worker_loop.rb +89 -0
- data/lib/new_relic/agent.rb +454 -0
- data/lib/new_relic/collection_helper.rb +75 -0
- data/lib/new_relic/command.rb +85 -0
- data/lib/new_relic/commands/deployments.rb +105 -0
- data/lib/new_relic/commands/install.rb +80 -0
- data/lib/new_relic/control/class_methods.rb +53 -0
- data/lib/new_relic/control/configuration.rb +202 -0
- data/lib/new_relic/control/frameworks/external.rb +16 -0
- data/lib/new_relic/control/frameworks/merb.rb +31 -0
- data/lib/new_relic/control/frameworks/rails.rb +164 -0
- data/lib/new_relic/control/frameworks/rails3.rb +75 -0
- data/lib/new_relic/control/frameworks/ruby.rb +42 -0
- data/lib/new_relic/control/frameworks/sinatra.rb +20 -0
- data/lib/new_relic/control/frameworks.rb +10 -0
- data/lib/new_relic/control/instance_methods.rb +179 -0
- data/lib/new_relic/control/instrumentation.rb +100 -0
- data/lib/new_relic/control/logging_methods.rb +143 -0
- data/lib/new_relic/control/profiling.rb +25 -0
- data/lib/new_relic/control/server_methods.rb +114 -0
- data/lib/new_relic/control.rb +46 -0
- data/lib/new_relic/data_serialization.rb +157 -0
- data/lib/new_relic/delayed_job_injection.rb +46 -0
- data/lib/new_relic/language_support.rb +69 -0
- data/lib/new_relic/local_environment.rb +414 -0
- data/lib/new_relic/merbtasks.rb +6 -0
- data/lib/new_relic/metric_data.rb +51 -0
- data/lib/new_relic/metric_spec.rb +75 -0
- data/lib/new_relic/metrics.rb +9 -0
- data/lib/new_relic/noticed_error.rb +24 -0
- data/lib/new_relic/rack/browser_monitoring.rb +68 -0
- data/lib/new_relic/rack/developer_mode.rb +268 -0
- data/lib/new_relic/recipes.rb +73 -0
- data/lib/new_relic/stats.rb +388 -0
- data/lib/new_relic/timer_lib.rb +27 -0
- data/lib/new_relic/transaction_analysis/segment_summary.rb +49 -0
- data/lib/new_relic/transaction_analysis.rb +77 -0
- data/lib/new_relic/transaction_sample/composite_segment.rb +27 -0
- data/lib/new_relic/transaction_sample/fake_segment.rb +9 -0
- data/lib/new_relic/transaction_sample/segment.rb +201 -0
- data/lib/new_relic/transaction_sample/summary_segment.rb +21 -0
- data/lib/new_relic/transaction_sample.rb +245 -0
- data/lib/new_relic/url_rule.rb +14 -0
- data/lib/new_relic/version.rb +55 -0
- data/lib/newrelic_rpm.rb +49 -0
- data/lib/tasks/all.rb +4 -0
- data/lib/tasks/install.rake +7 -0
- data/lib/tasks/tests.rake +19 -0
- data/newrelic.yml +265 -0
- data/recipes/newrelic.rb +6 -0
- data/test/active_record_fixtures.rb +77 -0
- data/test/config/newrelic.yml +48 -0
- data/test/config/test_control.rb +48 -0
- data/test/new_relic/agent/agent/connect_test.rb +410 -0
- data/test/new_relic/agent/agent/start_test.rb +255 -0
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +153 -0
- data/test/new_relic/agent/agent_test.rb +139 -0
- data/test/new_relic/agent/agent_test_controller.rb +77 -0
- data/test/new_relic/agent/agent_test_controller_test.rb +363 -0
- data/test/new_relic/agent/apdex_from_server_test.rb +9 -0
- data/test/new_relic/agent/beacon_configuration_test.rb +108 -0
- data/test/new_relic/agent/browser_monitoring_test.rb +278 -0
- data/test/new_relic/agent/busy_calculator_test.rb +81 -0
- data/test/new_relic/agent/database_test.rb +162 -0
- data/test/new_relic/agent/error_collector/notice_error_test.rb +257 -0
- data/test/new_relic/agent/error_collector_test.rb +175 -0
- data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +538 -0
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +36 -0
- data/test/new_relic/agent/instrumentation/instrumentation_test.rb +11 -0
- data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +172 -0
- data/test/new_relic/agent/instrumentation/metric_frame_test.rb +50 -0
- data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +84 -0
- data/test/new_relic/agent/instrumentation/queue_time_test.rb +387 -0
- data/test/new_relic/agent/instrumentation/rack_test.rb +35 -0
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +184 -0
- data/test/new_relic/agent/memcache_instrumentation_test.rb +143 -0
- data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +164 -0
- data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +234 -0
- data/test/new_relic/agent/method_tracer_test.rb +386 -0
- data/test/new_relic/agent/mock_scope_listener.rb +23 -0
- data/test/new_relic/agent/rpm_agent_test.rb +149 -0
- data/test/new_relic/agent/sampler_test.rb +19 -0
- data/test/new_relic/agent/shim_agent_test.rb +20 -0
- data/test/new_relic/agent/sql_sampler_test.rb +160 -0
- data/test/new_relic/agent/stats_engine/metric_stats/harvest_test.rb +150 -0
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +82 -0
- data/test/new_relic/agent/stats_engine/samplers_test.rb +99 -0
- data/test/new_relic/agent/stats_engine_test.rb +185 -0
- data/test/new_relic/agent/transaction_sample_builder_test.rb +195 -0
- data/test/new_relic/agent/transaction_sampler_test.rb +955 -0
- data/test/new_relic/agent/worker_loop_test.rb +66 -0
- data/test/new_relic/agent_test.rb +175 -0
- data/test/new_relic/collection_helper_test.rb +149 -0
- data/test/new_relic/command/deployments_test.rb +68 -0
- data/test/new_relic/control/class_methods_test.rb +62 -0
- data/test/new_relic/control/configuration_test.rb +72 -0
- data/test/new_relic/control/logging_methods_test.rb +185 -0
- data/test/new_relic/control_test.rb +254 -0
- data/test/new_relic/data_serialization_test.rb +208 -0
- data/test/new_relic/delayed_job_injection_test.rb +16 -0
- data/test/new_relic/local_environment_test.rb +72 -0
- data/test/new_relic/metric_data_test.rb +125 -0
- data/test/new_relic/metric_spec_test.rb +95 -0
- data/test/new_relic/rack/all_test.rb +11 -0
- data/test/new_relic/rack/browser_monitoring_test.rb +84 -0
- data/test/new_relic/rack/developer_mode_helper_test.rb +141 -0
- data/test/new_relic/rack/developer_mode_test.rb +43 -0
- data/test/new_relic/stats_test.rb +426 -0
- data/test/new_relic/transaction_analysis/segment_summary_test.rb +91 -0
- data/test/new_relic/transaction_analysis_test.rb +121 -0
- data/test/new_relic/transaction_sample/composite_segment_test.rb +35 -0
- data/test/new_relic/transaction_sample/fake_segment_test.rb +17 -0
- data/test/new_relic/transaction_sample/segment_test.rb +389 -0
- data/test/new_relic/transaction_sample/summary_segment_test.rb +31 -0
- data/test/new_relic/transaction_sample_subtest_test.rb +56 -0
- data/test/new_relic/transaction_sample_test.rb +164 -0
- data/test/new_relic/version_number_test.rb +89 -0
- data/test/test_contexts.rb +29 -0
- data/test/test_helper.rb +154 -0
- data/ui/helpers/developer_mode_helper.rb +357 -0
- data/ui/helpers/google_pie_chart.rb +48 -0
- data/ui/views/layouts/newrelic_default.rhtml +47 -0
- data/ui/views/newrelic/_explain_plans.rhtml +27 -0
- data/ui/views/newrelic/_sample.rhtml +20 -0
- data/ui/views/newrelic/_segment.rhtml +28 -0
- data/ui/views/newrelic/_segment_limit_message.rhtml +1 -0
- data/ui/views/newrelic/_segment_row.rhtml +12 -0
- data/ui/views/newrelic/_show_sample_detail.rhtml +24 -0
- data/ui/views/newrelic/_show_sample_sql.rhtml +24 -0
- data/ui/views/newrelic/_show_sample_summary.rhtml +3 -0
- data/ui/views/newrelic/_sql_row.rhtml +16 -0
- data/ui/views/newrelic/_stack_trace.rhtml +15 -0
- data/ui/views/newrelic/_table.rhtml +12 -0
- data/ui/views/newrelic/explain_sql.rhtml +43 -0
- data/ui/views/newrelic/file/images/arrow-close.png +0 -0
- data/ui/views/newrelic/file/images/arrow-open.png +0 -0
- data/ui/views/newrelic/file/images/blue_bar.gif +0 -0
- data/ui/views/newrelic/file/images/file_icon.png +0 -0
- data/ui/views/newrelic/file/images/gray_bar.gif +0 -0
- data/ui/views/newrelic/file/images/new-relic-rpm-desktop.gif +0 -0
- data/ui/views/newrelic/file/images/new_relic_rpm_desktop.gif +0 -0
- data/ui/views/newrelic/file/images/textmate.png +0 -0
- data/ui/views/newrelic/file/javascript/jquery-1.4.2.js +6240 -0
- data/ui/views/newrelic/file/javascript/transaction_sample.js +120 -0
- data/ui/views/newrelic/file/stylesheets/style.css +490 -0
- data/ui/views/newrelic/index.rhtml +71 -0
- data/ui/views/newrelic/sample_not_found.rhtml +2 -0
- data/ui/views/newrelic/show_sample.rhtml +80 -0
- data/ui/views/newrelic/show_source.rhtml +3 -0
- data/ui/views/newrelic/threads.rhtml +53 -0
- data/vendor/gems/dependency_detection-0.0.1.build/LICENSE +5 -0
- data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection/version.rb +3 -0
- data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +62 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/metric_parser.rb +1 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/action_mailer.rb +14 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_merchant.rb +31 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_record.rb +33 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/apdex.rb +89 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/background_transaction.rb +7 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/client.rb +46 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller.rb +67 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_cpu.rb +43 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_ext.rb +17 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database.rb +48 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database_pool.rb +24 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net.rb +28 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net_parser.rb +17 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/errors.rb +11 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/external.rb +55 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/frontend.rb +40 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/gc.rb +20 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/hibernate_session.rb +7 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +31 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java_parser.rb +17 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp.rb +34 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp_tag.rb +7 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/mem_cache.rb +55 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/metric_parser.rb +122 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/orm.rb +27 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/other_transaction.rb +40 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet.rb +7 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_context_listener.rb +7 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_filter.rb +7 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr.rb +27 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr_request_handler.rb +15 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring.rb +54 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_controller.rb +6 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_view.rb +6 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_action.rb +20 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_result.rb +20 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/version.rb +5 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +70 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_frontend.rb +18 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_service.rb +14 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_transaction.rb +133 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser.rb +64 -0
- metadata +398 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
require 'new_relic/agent/instrumentation/metric_frame'
|
|
2
|
+
require 'new_relic/agent/instrumentation/queue_time'
|
|
3
|
+
module NewRelic
|
|
4
|
+
module Agent
|
|
5
|
+
module Instrumentation
|
|
6
|
+
# == NewRelic instrumentation for controller actions and tasks
|
|
7
|
+
#
|
|
8
|
+
# This instrumentation is applied to the action controller to collect
|
|
9
|
+
# metrics for every web request.
|
|
10
|
+
#
|
|
11
|
+
# It can also be used to capture performance information for
|
|
12
|
+
# background tasks and other non-web transactions, including
|
|
13
|
+
# detailed transaction traces and traced errors.
|
|
14
|
+
#
|
|
15
|
+
# For details on how to instrument background tasks see
|
|
16
|
+
# ClassMethods#add_transaction_tracer and
|
|
17
|
+
# #perform_action_with_newrelic_trace
|
|
18
|
+
#
|
|
19
|
+
module ControllerInstrumentation
|
|
20
|
+
|
|
21
|
+
def self.included(clazz) # :nodoc:
|
|
22
|
+
clazz.extend(ClassMethods)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# This module is for importing stubs when the agent is disabled
|
|
26
|
+
module ClassMethodsShim # :nodoc:
|
|
27
|
+
def newrelic_ignore(*args); end
|
|
28
|
+
def newrelic_ignore_apdex(*args); end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
module Shim # :nodoc:
|
|
32
|
+
def self.included(clazz)
|
|
33
|
+
clazz.extend(ClassMethodsShim)
|
|
34
|
+
end
|
|
35
|
+
def newrelic_notice_error(*args); end
|
|
36
|
+
def new_relic_trace_controller_action(*args); yield; end
|
|
37
|
+
def newrelic_metric_path; end
|
|
38
|
+
def perform_action_with_newrelic_trace(*args); yield; end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module ClassMethods
|
|
42
|
+
# Have NewRelic ignore actions in this controller. Specify the actions as hash options
|
|
43
|
+
# using :except and :only. If no actions are specified, all actions are ignored.
|
|
44
|
+
def newrelic_ignore(specifiers={})
|
|
45
|
+
newrelic_ignore_aspect('do_not_trace', specifiers)
|
|
46
|
+
end
|
|
47
|
+
# Have NewRelic omit apdex measurements on the given actions. Typically used for
|
|
48
|
+
# actions that are not user facing or that skew your overall apdex measurement.
|
|
49
|
+
# Accepts :except and :only options, as with #newrelic_ignore.
|
|
50
|
+
def newrelic_ignore_apdex(specifiers={})
|
|
51
|
+
newrelic_ignore_aspect('ignore_apdex', specifiers)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def newrelic_ignore_aspect(property, specifiers={}) # :nodoc:
|
|
55
|
+
if specifiers.empty?
|
|
56
|
+
self.newrelic_write_attr property, true
|
|
57
|
+
elsif ! (Hash === specifiers)
|
|
58
|
+
logger.error "newrelic_#{property} takes an optional hash with :only and :except lists of actions (illegal argument type '#{specifiers.class}')"
|
|
59
|
+
else
|
|
60
|
+
self.newrelic_write_attr property, specifiers
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Should be monkey patched into the controller class implemented
|
|
65
|
+
# with the inheritable attribute mechanism.
|
|
66
|
+
def newrelic_write_attr(attr_name, value) # :nodoc:
|
|
67
|
+
instance_variable_set "@#{attr_name}", value
|
|
68
|
+
end
|
|
69
|
+
def newrelic_read_attr(attr_name) # :nodoc:
|
|
70
|
+
instance_variable_get "@#{attr_name}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Add transaction tracing to the given method. This will treat
|
|
74
|
+
# the given method as a main entrypoint for instrumentation, just
|
|
75
|
+
# like controller actions are treated by default. Useful especially
|
|
76
|
+
# for background tasks.
|
|
77
|
+
#
|
|
78
|
+
# Example for background job:
|
|
79
|
+
# class Job
|
|
80
|
+
# include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
|
81
|
+
# def run(task)
|
|
82
|
+
# ...
|
|
83
|
+
# end
|
|
84
|
+
# # Instrument run so tasks show up under task.name. Note single
|
|
85
|
+
# # quoting to defer eval to runtime.
|
|
86
|
+
# add_transaction_tracer :run, :name => '#{args[0].name}'
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# Here's an example of a controller that uses a dispatcher
|
|
90
|
+
# action to invoke operations which you want treated as top
|
|
91
|
+
# level actions, so they aren't all lumped into the invoker
|
|
92
|
+
# action.
|
|
93
|
+
#
|
|
94
|
+
# MyController < ActionController::Base
|
|
95
|
+
# include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
|
96
|
+
# # dispatch the given op to the method given by the service parameter.
|
|
97
|
+
# def invoke_operation
|
|
98
|
+
# op = params['operation']
|
|
99
|
+
# send op
|
|
100
|
+
# end
|
|
101
|
+
# # Ignore the invoker to avoid double counting
|
|
102
|
+
# newrelic_ignore :only => 'invoke_operation'
|
|
103
|
+
# # Instrument the operations:
|
|
104
|
+
# add_transaction_tracer :print
|
|
105
|
+
# add_transaction_tracer :show
|
|
106
|
+
# add_transaction_tracer :forward
|
|
107
|
+
# end
|
|
108
|
+
#
|
|
109
|
+
# Here's an example of how to pass contextual information into the transaction
|
|
110
|
+
# so it will appear in transaction traces:
|
|
111
|
+
#
|
|
112
|
+
# class Job
|
|
113
|
+
# include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
|
114
|
+
# def process(account)
|
|
115
|
+
# ...
|
|
116
|
+
# end
|
|
117
|
+
# # Include the account name in the transaction details. Note the single
|
|
118
|
+
# # quotes to defer eval until call time.
|
|
119
|
+
# add_transaction_tracer :process, :params => '{ :account_name => args[0].name }'
|
|
120
|
+
# end
|
|
121
|
+
#
|
|
122
|
+
# See NewRelic::Agent::Instrumentation::ControllerInstrumentation#perform_action_with_newrelic_trace
|
|
123
|
+
# for the full list of available options.
|
|
124
|
+
#
|
|
125
|
+
def add_transaction_tracer(method, options={})
|
|
126
|
+
# The metric path:
|
|
127
|
+
options[:name] ||= method.to_s
|
|
128
|
+
# create the argument list:
|
|
129
|
+
options_arg = []
|
|
130
|
+
options.each do |key, value|
|
|
131
|
+
valuestr = case
|
|
132
|
+
when value.is_a?(Symbol)
|
|
133
|
+
value.inspect
|
|
134
|
+
when key == :params
|
|
135
|
+
value.to_s
|
|
136
|
+
else
|
|
137
|
+
%Q["#{value.to_s}"]
|
|
138
|
+
end
|
|
139
|
+
options_arg << %Q[:#{key} => #{valuestr}]
|
|
140
|
+
end
|
|
141
|
+
class_eval <<-EOC
|
|
142
|
+
def #{method.to_s}_with_newrelic_transaction_trace(*args, &block)
|
|
143
|
+
perform_action_with_newrelic_trace(#{options_arg.join(',')}) do
|
|
144
|
+
#{method.to_s}_without_newrelic_transaction_trace(*args, &block)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
EOC
|
|
148
|
+
alias_method "#{method.to_s}_without_newrelic_transaction_trace", method.to_s
|
|
149
|
+
alias_method method.to_s, "#{method.to_s}_with_newrelic_transaction_trace"
|
|
150
|
+
NewRelic::Control.instance.log.debug("Traced transaction: class = #{self.name}, method = #{method.to_s}, options = #{options.inspect}")
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Must be implemented in the controller class:
|
|
155
|
+
# Determine the path that is used in the metric name for
|
|
156
|
+
# the called controller action. Of the form controller_path/action_name
|
|
157
|
+
#
|
|
158
|
+
def newrelic_metric_path(action_name_override = nil) # :nodoc:
|
|
159
|
+
raise "Not implemented!"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Yield to the given block with NewRelic tracing. Used by
|
|
163
|
+
# default instrumentation on controller actions in Rails and Merb.
|
|
164
|
+
# But it can also be used in custom instrumentation of controller
|
|
165
|
+
# methods and background tasks.
|
|
166
|
+
#
|
|
167
|
+
# This is the method invoked by instrumentation added by the
|
|
168
|
+
# <tt>ClassMethods#add_transaction_tracer</tt>.
|
|
169
|
+
#
|
|
170
|
+
# Here's a more verbose version of the example shown in
|
|
171
|
+
# <tt>ClassMethods#add_transaction_tracer</tt> using this method instead of
|
|
172
|
+
# #add_transaction_tracer.
|
|
173
|
+
#
|
|
174
|
+
# Below is a controller with an +invoke_operation+ action which
|
|
175
|
+
# dispatches to more specific operation methods based on a
|
|
176
|
+
# parameter (very dangerous, btw!). With this instrumentation,
|
|
177
|
+
# the +invoke_operation+ action is ignored but the operation
|
|
178
|
+
# methods show up in New Relic as if they were first class controller
|
|
179
|
+
# actions
|
|
180
|
+
#
|
|
181
|
+
# MyController < ActionController::Base
|
|
182
|
+
# include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
|
183
|
+
# # dispatch the given op to the method given by the service parameter.
|
|
184
|
+
# def invoke_operation
|
|
185
|
+
# op = params['operation']
|
|
186
|
+
# perform_action_with_newrelic_trace(:name => op) do
|
|
187
|
+
# send op, params['message']
|
|
188
|
+
# end
|
|
189
|
+
# end
|
|
190
|
+
# # Ignore the invoker to avoid double counting
|
|
191
|
+
# newrelic_ignore :only => 'invoke_operation'
|
|
192
|
+
# end
|
|
193
|
+
#
|
|
194
|
+
#
|
|
195
|
+
# When invoking this method explicitly as in the example above, pass in a
|
|
196
|
+
# block to measure with some combination of options:
|
|
197
|
+
#
|
|
198
|
+
# * <tt>:category => :controller</tt> indicates that this is a
|
|
199
|
+
# controller action and will appear with all the other actions. This
|
|
200
|
+
# is the default.
|
|
201
|
+
# * <tt>:category => :task</tt> indicates that this is a
|
|
202
|
+
# background task and will show up in New Relic with other background
|
|
203
|
+
# tasks instead of in the controllers list
|
|
204
|
+
# * <tt>:category => :rack</tt> if you are instrumenting a rack
|
|
205
|
+
# middleware call. The <tt>:name</tt> is optional, useful if you
|
|
206
|
+
# have more than one potential transaction in the #call.
|
|
207
|
+
# * <tt>:category => :uri</tt> indicates that this is a
|
|
208
|
+
# web transaction whose name is a normalized URI, where 'normalized'
|
|
209
|
+
# means the URI does not have any elements with data in them such
|
|
210
|
+
# as in many REST URIs.
|
|
211
|
+
# * <tt>:name => action_name</tt> is used to specify the action
|
|
212
|
+
# name used as part of the metric name
|
|
213
|
+
# * <tt>:params => {...}</tt> to provide information about the context
|
|
214
|
+
# of the call, used in transaction trace display, for example:
|
|
215
|
+
# <tt>:params => { :account => @account.name, :file => file.name }</tt>
|
|
216
|
+
# These are treated similarly to request parameters in web transactions.
|
|
217
|
+
#
|
|
218
|
+
# Seldomly used options:
|
|
219
|
+
#
|
|
220
|
+
# * <tt>:force => true</tt> indicates you should capture all
|
|
221
|
+
# metrics even if the #newrelic_ignore directive was specified
|
|
222
|
+
# * <tt>:class_name => aClass.name</tt> is used to override the name
|
|
223
|
+
# of the class when used inside the metric name. Default is the
|
|
224
|
+
# current class.
|
|
225
|
+
# * <tt>:path => metric_path</tt> is *deprecated* in the public API. It
|
|
226
|
+
# allows you to set the entire metric after the category part. Overrides
|
|
227
|
+
# all the other options.
|
|
228
|
+
# * <tt>:request => Rack::Request#new(env)</tt> is used to pass in a
|
|
229
|
+
# request object that may respond to uri and referer.
|
|
230
|
+
#
|
|
231
|
+
# If a single argument is passed in, it is treated as a metric
|
|
232
|
+
# path. This form is deprecated.
|
|
233
|
+
def perform_action_with_newrelic_trace(*args, &block)
|
|
234
|
+
|
|
235
|
+
# Skip instrumentation based on the value of 'do_not_trace' and if
|
|
236
|
+
# we aren't calling directly with a block.
|
|
237
|
+
if !block_given? && do_not_trace?
|
|
238
|
+
# Also ignore all instrumentation in the call sequence
|
|
239
|
+
NewRelic::Agent.disable_all_tracing do
|
|
240
|
+
return perform_action_without_newrelic_trace(*args)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
return perform_action_with_newrelic_profile(args, &block) if NewRelic::Control.instance.profiling?
|
|
245
|
+
|
|
246
|
+
frame_data = _push_metric_frame(block_given? ? args : [])
|
|
247
|
+
begin
|
|
248
|
+
NewRelic::Agent.trace_execution_scoped frame_data.recorded_metrics, :force => frame_data.force_flag do
|
|
249
|
+
frame_data.start_transaction
|
|
250
|
+
begin
|
|
251
|
+
NewRelic::Agent::BusyCalculator.dispatcher_start frame_data.start
|
|
252
|
+
if block_given?
|
|
253
|
+
yield
|
|
254
|
+
else
|
|
255
|
+
perform_action_without_newrelic_trace(*args)
|
|
256
|
+
end
|
|
257
|
+
rescue Exception => e
|
|
258
|
+
frame_data.notice_error(e)
|
|
259
|
+
raise
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
ensure
|
|
263
|
+
NewRelic::Agent::BusyCalculator.dispatcher_finish
|
|
264
|
+
# Look for a metric frame in the thread local and process it.
|
|
265
|
+
# Clear the thread local when finished to ensure it only gets called once.
|
|
266
|
+
frame_data.record_apdex unless ignore_apdex?
|
|
267
|
+
|
|
268
|
+
frame_data.pop
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
protected
|
|
273
|
+
# Should be implemented in the dispatcher class
|
|
274
|
+
def newrelic_response_code; end
|
|
275
|
+
|
|
276
|
+
def newrelic_request_headers
|
|
277
|
+
self.respond_to?(:request) && self.request.respond_to?(:headers) && self.request.headers
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# overrideable method to determine whether to trace an action
|
|
281
|
+
# or not - you may override this in your controller and supply
|
|
282
|
+
# your own logic for ignoring transactions.
|
|
283
|
+
def do_not_trace?
|
|
284
|
+
_is_filtered?('do_not_trace')
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# overrideable method to determine whether to trace an action
|
|
288
|
+
# for purposes of apdex measurement - you can use this to
|
|
289
|
+
# ignore things like api calls or other fast non-user-facing
|
|
290
|
+
# actions
|
|
291
|
+
def ignore_apdex?
|
|
292
|
+
_is_filtered?('ignore_apdex')
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
private
|
|
296
|
+
|
|
297
|
+
# Profile the instrumented call. Dev mode only. Experimental
|
|
298
|
+
# - should definitely not be used on production applications
|
|
299
|
+
def perform_action_with_newrelic_profile(args)
|
|
300
|
+
frame_data = _push_metric_frame(block_given? ? args : [])
|
|
301
|
+
val = nil
|
|
302
|
+
NewRelic::Agent.trace_execution_scoped frame_data.metric_name do
|
|
303
|
+
MetricFrame.current(true).start_transaction
|
|
304
|
+
NewRelic::Agent.disable_all_tracing do
|
|
305
|
+
# turn on profiling
|
|
306
|
+
profile = RubyProf.profile do
|
|
307
|
+
if block_given?
|
|
308
|
+
val = yield
|
|
309
|
+
else
|
|
310
|
+
val = perform_action_without_newrelic_trace(*args)
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
NewRelic::Agent.instance.transaction_sampler.notice_profile profile
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
return val
|
|
317
|
+
ensure
|
|
318
|
+
frame_data.pop
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Write a metric frame onto a thread local if there isn't already one there.
|
|
322
|
+
# If there is one, just update it.
|
|
323
|
+
def _push_metric_frame(args) # :nodoc:
|
|
324
|
+
frame_data = NewRelic::Agent::Instrumentation::MetricFrame.current(true)
|
|
325
|
+
|
|
326
|
+
frame_data.apdex_start ||= _detect_upstream_wait(frame_data.start)
|
|
327
|
+
_record_queue_length
|
|
328
|
+
# If a block was passed in, then the arguments represent options for the instrumentation,
|
|
329
|
+
# not app method arguments.
|
|
330
|
+
if args.any?
|
|
331
|
+
if args.last.is_a?(Hash)
|
|
332
|
+
options = args.last
|
|
333
|
+
frame_data.force_flag = options[:force]
|
|
334
|
+
frame_data.request = options[:request] if options[:request]
|
|
335
|
+
end
|
|
336
|
+
category, path, available_params = _convert_args_to_path(args)
|
|
337
|
+
else
|
|
338
|
+
category = 'Controller'
|
|
339
|
+
path = newrelic_metric_path
|
|
340
|
+
available_params = self.respond_to?(:params) ? self.params : {}
|
|
341
|
+
end
|
|
342
|
+
frame_data.request ||= self.request if self.respond_to? :request
|
|
343
|
+
frame_data.push(category + '/'+ path)
|
|
344
|
+
frame_data.filtered_params = (respond_to? :filter_parameters) ? filter_parameters(available_params) : available_params
|
|
345
|
+
frame_data
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def _convert_args_to_path(args)
|
|
349
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
350
|
+
params = options[:params] || {}
|
|
351
|
+
category = case options[:category]
|
|
352
|
+
when :controller, nil then 'Controller'
|
|
353
|
+
when :task then 'OtherTransaction/Background' # 'Task'
|
|
354
|
+
when :rack then 'Controller/Rack' #'WebTransaction/Rack'
|
|
355
|
+
when :uri then 'Controller' #'WebTransaction/Uri'
|
|
356
|
+
when :sinatra then 'Controller/Sinatra' #'WebTransaction/Uri'
|
|
357
|
+
# for internal use only
|
|
358
|
+
else options[:category].to_s
|
|
359
|
+
end
|
|
360
|
+
unless path = options[:path]
|
|
361
|
+
action = options[:name] || args.first
|
|
362
|
+
metric_class = options[:class_name] || (self.is_a?(Class) ? self.name : self.class.name)
|
|
363
|
+
path = metric_class
|
|
364
|
+
path += ('/' + action) if action
|
|
365
|
+
end
|
|
366
|
+
[category, path, params]
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# Filter out a request if it matches one of our parameters for
|
|
370
|
+
# ignoring it - the key is either 'do_not_trace' or 'ignore_apdex'
|
|
371
|
+
def _is_filtered?(key)
|
|
372
|
+
ignore_actions = self.class.newrelic_read_attr(key) if self.class.respond_to? :newrelic_read_attr
|
|
373
|
+
case ignore_actions
|
|
374
|
+
when nil; false
|
|
375
|
+
when Hash
|
|
376
|
+
only_actions = Array(ignore_actions[:only])
|
|
377
|
+
except_actions = Array(ignore_actions[:except])
|
|
378
|
+
only_actions.include?(action_name.to_sym) || (except_actions.any? && !except_actions.include?(action_name.to_sym))
|
|
379
|
+
else
|
|
380
|
+
true
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
# Take a guess at a measure representing the number of requests waiting in mongrel
|
|
384
|
+
# or heroku.
|
|
385
|
+
def _record_queue_length
|
|
386
|
+
if newrelic_request_headers
|
|
387
|
+
if queue_depth = newrelic_request_headers['HTTP_X_HEROKU_QUEUE_DEPTH']
|
|
388
|
+
queue_depth = queue_depth.to_i rescue nil
|
|
389
|
+
elsif mongrel = NewRelic::Control.instance.local_env.mongrel
|
|
390
|
+
# Always subtrace 1 for the active mongrel
|
|
391
|
+
queue_depth = [mongrel.workers.list.length.to_i - 1, 0].max rescue nil
|
|
392
|
+
end
|
|
393
|
+
NewRelic::Agent.agent.stats_engine.get_stats_no_scope('Mongrel/Queue Length').trace_call(queue_depth) if queue_depth
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
include NewRelic::Agent::Instrumentation::QueueTime
|
|
398
|
+
|
|
399
|
+
# Return a Time instance representing the upstream start time.
|
|
400
|
+
# now is a Time instance to fall back on if no other candidate
|
|
401
|
+
# for the start time is found.
|
|
402
|
+
def _detect_upstream_wait(now)
|
|
403
|
+
queue_start = nil
|
|
404
|
+
if newrelic_request_headers
|
|
405
|
+
queue_start = parse_frontend_headers(newrelic_request_headers)
|
|
406
|
+
Thread.current[:newrelic_queue_time] = (now.to_f - queue_start.to_f) if queue_start
|
|
407
|
+
end
|
|
408
|
+
queue_start || now
|
|
409
|
+
rescue Exception => e
|
|
410
|
+
NewRelic::Control.instance.log.error("Error detecting upstream wait time: #{e}")
|
|
411
|
+
NewRelic::Control.instance.log.debug("#{e.backtrace[0..20]}")
|
|
412
|
+
now
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
# returns the NewRelic::MethodTraceStats object associated
|
|
416
|
+
# with the dispatcher time measurement
|
|
417
|
+
def _dispatch_stat
|
|
418
|
+
NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'HttpDispatcher'
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# NewRelic instrumentation for DataMapper
|
|
2
|
+
# For now, we have to refer to all db metrics as "ActiveRecord"
|
|
3
|
+
if defined? DataMapper
|
|
4
|
+
|
|
5
|
+
DataMapper::Model.class_eval do
|
|
6
|
+
add_method_tracer :get, 'ActiveRecord/#{self.name}/find'
|
|
7
|
+
add_method_tracer :first, 'ActiveRecord/#{self.name}/find'
|
|
8
|
+
add_method_tracer :first_or_create, 'ActiveRecord/#{self.name}/find'
|
|
9
|
+
add_method_tracer :all, 'ActiveRecord/#{self.name}/find_all'
|
|
10
|
+
end
|
|
11
|
+
DataMapper::Resource.class_eval do
|
|
12
|
+
|
|
13
|
+
@@my_sql_defined = defined? ActiveRecord::ConnectionAdapters::MysqlAdapter
|
|
14
|
+
@@postgres_defined = defined? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
|
15
|
+
|
|
16
|
+
for method in [:query] do
|
|
17
|
+
add_method_tracer method, 'ActiveRecord/#{self.class.name[/[^:]*$/]}/execute'
|
|
18
|
+
add_method_tracer method, 'ActiveRecord/all', :push_scope => false
|
|
19
|
+
end
|
|
20
|
+
for method in [:update, :save] do
|
|
21
|
+
add_method_tracer method, 'ActiveRecord/#{self.class.name[/[^:]*$/]}/save'
|
|
22
|
+
add_method_tracer method, 'ActiveRecord/save', :push_scope => false
|
|
23
|
+
end
|
|
24
|
+
add_method_tracer :destroy, 'ActiveRecord/#{self.class.name[/[^:]*$/]}/destroy'
|
|
25
|
+
add_method_tracer :destroy, 'ActiveRecord/destroy', :push_scope => false
|
|
26
|
+
|
|
27
|
+
def log_with_newrelic_instrumentation(sql, name, &block)
|
|
28
|
+
# if we aren't in a blamed context, then add one so that we can
|
|
29
|
+
# see that controllers are calling SQL directly we check
|
|
30
|
+
# scope_depth vs 2 since the controller is 1
|
|
31
|
+
if NewRelic::Agent.instance.transaction_sampler.scope_depth < 2
|
|
32
|
+
self.class.trace_method_execution "Database/DirectSQL", true, true do
|
|
33
|
+
log_with_capture_sql(sql, name, &block)
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
log_with_capture_sql(sql, name, &block)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def log_with_capture_sql(sql, name, &block)
|
|
41
|
+
if @@my_sql_defined && self.is_a?(ActiveRecord::ConnectionAdapters::MysqlAdapter)
|
|
42
|
+
config = @config
|
|
43
|
+
elsif @@postgres_defined && self.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
|
44
|
+
config = @config
|
|
45
|
+
else
|
|
46
|
+
config = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
t0 = Time.now
|
|
50
|
+
result = log_without_newrelic_instrumentation(sql, name, &block)
|
|
51
|
+
|
|
52
|
+
NewRelic::Agent.instance.transaction_sampler.notice_sql(sql, config, (Time.now - t0).to_f)
|
|
53
|
+
|
|
54
|
+
result
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'new_relic/agent/instrumentation/controller_instrumentation'
|
|
2
|
+
|
|
3
|
+
DependencyDetection.defer do
|
|
4
|
+
@name = :delayed_job
|
|
5
|
+
|
|
6
|
+
depends_on do
|
|
7
|
+
!NewRelic::Control.instance['disable_dj']
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
depends_on do
|
|
11
|
+
# double check because of old JRuby bug
|
|
12
|
+
defined?(::Delayed) && defined?(::Delayed::Job) &&
|
|
13
|
+
Delayed::Job.method_defined?(:invoke_job)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
executes do
|
|
17
|
+
NewRelic::Agent.logger.debug 'Installing DelayedJob instrumentation'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
executes do
|
|
21
|
+
Delayed::Job.class_eval do
|
|
22
|
+
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
|
23
|
+
if self.instance_methods.include?('name') || self.instance_methods.include?(:name)
|
|
24
|
+
add_transaction_tracer "invoke_job", :category => 'OtherTransaction/DelayedJob', :path => '#{self.name}'
|
|
25
|
+
else
|
|
26
|
+
add_transaction_tracer "invoke_job", :category => 'OtherTransaction/DelayedJob'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
executes do
|
|
32
|
+
Delayed::Job.instance_eval do
|
|
33
|
+
if self.respond_to?('after_fork')
|
|
34
|
+
if method_defined?(:after_fork)
|
|
35
|
+
def after_fork_with_newrelic
|
|
36
|
+
NewRelic::Agent.after_fork(:force_reconnect => true)
|
|
37
|
+
after_fork_without_newrelic
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
alias_method :after_fork_without_newrelic, :after_fork
|
|
41
|
+
alias_method :after_fork, :after_fork_with_newrelic
|
|
42
|
+
else
|
|
43
|
+
def after_fork
|
|
44
|
+
NewRelic::Agent.after_fork(:force_reconnect => true)
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# NOTE there are multiple implementations of the MemCache client in Ruby,
|
|
2
|
+
# each with slightly different API's and semantics.
|
|
3
|
+
# See:
|
|
4
|
+
# http://www.deveiate.org/code/Ruby-MemCache/ (Gem: Ruby-MemCache)
|
|
5
|
+
# http://seattlerb.rubyforge.org/memcache-client/ (Gem: memcache-client)
|
|
6
|
+
# http://github.com/mperham/dalli (Gem: dalli)
|
|
7
|
+
|
|
8
|
+
module NewRelic
|
|
9
|
+
module Agent
|
|
10
|
+
module Instrumentation
|
|
11
|
+
module Memcache
|
|
12
|
+
module_function
|
|
13
|
+
def instrument_methods(the_class, method_names)
|
|
14
|
+
method_names.each do |method_name|
|
|
15
|
+
next unless the_class.method_defined? method_name.to_sym
|
|
16
|
+
the_class.class_eval <<-EOD
|
|
17
|
+
def #{method_name}_with_newrelic_trace(*args, &block)
|
|
18
|
+
metrics = ["Memcache/#{method_name}",
|
|
19
|
+
(NewRelic::Agent::Instrumentation::MetricFrame.recording_web_transaction? ? 'Memcache/allWeb' : 'Memcache/allOther')]
|
|
20
|
+
self.class.trace_execution_scoped(metrics) do
|
|
21
|
+
t0 = Time.now
|
|
22
|
+
begin
|
|
23
|
+
#{method_name}_without_newrelic_trace(*args, &block)
|
|
24
|
+
ensure
|
|
25
|
+
#{memcache_key_snippet(method_name)}
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
alias #{method_name}_without_newrelic_trace #{method_name}
|
|
30
|
+
alias #{method_name} #{method_name}_with_newrelic_trace
|
|
31
|
+
EOD
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
def memcache_key_snippet(method_name)
|
|
35
|
+
return "" unless NewRelic::Control.instance['capture_memcache_keys']
|
|
36
|
+
"NewRelic::Agent.instance.transaction_sampler.notice_nosql(args.first.inspect, (Time.now - t0).to_f) rescue nil"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
DependencyDetection.defer do
|
|
44
|
+
@name = :memcache
|
|
45
|
+
|
|
46
|
+
depends_on do
|
|
47
|
+
!NewRelic::Control.instance['disable_memcache_instrumentation']
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
depends_on do
|
|
51
|
+
defined?(::MemCache) || defined?(::Memcached) ||
|
|
52
|
+
defined?(::Dalli::Client) || defined?(::Spymemcached)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
executes do
|
|
56
|
+
commands = %w[get get_multi set add incr decr delete replace append prepend]
|
|
57
|
+
if defined? ::MemCache
|
|
58
|
+
NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::MemCache,
|
|
59
|
+
commands)
|
|
60
|
+
NewRelic::Agent.logger.debug 'Installing MemCache instrumentation'
|
|
61
|
+
end
|
|
62
|
+
if defined? ::Memcached
|
|
63
|
+
commands << 'cas'
|
|
64
|
+
NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Memcached,
|
|
65
|
+
commands)
|
|
66
|
+
NewRelic::Agent.logger.debug 'Installing Memcached instrumentation'
|
|
67
|
+
end
|
|
68
|
+
if defined? ::Dalli::Client
|
|
69
|
+
NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Dalli::Client,
|
|
70
|
+
commands)
|
|
71
|
+
NewRelic::Agent.logger.debug 'Installing Dalli Memcache instrumentation'
|
|
72
|
+
end
|
|
73
|
+
if defined? ::Spymemcached
|
|
74
|
+
commands << 'multiget'
|
|
75
|
+
NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Spymemcached,
|
|
76
|
+
commands)
|
|
77
|
+
NewRelic::Agent.logger.debug 'Installing Spymemcached instrumentation'
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
DependencyDetection.defer do
|
|
4
|
+
@name = :merb_controller
|
|
5
|
+
|
|
6
|
+
depends_on do
|
|
7
|
+
defined?(Merb) && defined?(Merb::Controller)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
executes do
|
|
11
|
+
NewRelic::Agent.logger.debug 'Installing Merb Controller instrumentation'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
executes do
|
|
15
|
+
require 'merb-core/controller/merb_controller'
|
|
16
|
+
|
|
17
|
+
Merb::Controller.class_eval do
|
|
18
|
+
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
|
19
|
+
|
|
20
|
+
class_inheritable_accessor :do_not_trace
|
|
21
|
+
class_inheritable_accessor :ignore_apdex
|
|
22
|
+
|
|
23
|
+
def self.newrelic_write_attr(attr_name, value) # :nodoc:
|
|
24
|
+
self.send "#{attr_name}=", attr_name, value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.newrelic_read_attr(attr_name) # :nodoc:
|
|
28
|
+
self.send attr_name
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
protected
|
|
32
|
+
# determine the path that is used in the metric name for
|
|
33
|
+
# the called controller action
|
|
34
|
+
def newrelic_metric_path
|
|
35
|
+
"#{controller_name}/#{action_name}"
|
|
36
|
+
end
|
|
37
|
+
alias_method :perform_action_without_newrelic_trace, :_dispatch
|
|
38
|
+
alias_method :_dispatch, :perform_action_with_newrelic_trace
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
DependencyDetection.defer do
|
|
2
|
+
@name = :merb_error
|
|
3
|
+
|
|
4
|
+
depends_on do
|
|
5
|
+
defined?(Merb) && defined?(Merb::Dispatcher) && defined?(Merb::Dispatcher::DefaultException)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
depends_on do
|
|
9
|
+
Merb::Dispatcher::DefaultException.respond_to?(:before)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
executes do
|
|
13
|
+
NewRelic::Agent.logger.debug 'Installing Merb Errors instrumentation'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
executes do
|
|
17
|
+
|
|
18
|
+
# Hook in the notification to merb
|
|
19
|
+
error_notifier = Proc.new {
|
|
20
|
+
if request.exceptions #check that there's actually an exception
|
|
21
|
+
# Note, this assumes we have already captured the other information such as uri and params in the MetricFrame.
|
|
22
|
+
NewRelic::Agent::Instrumentation::MetricFrame.notice_error(request.exceptions.first)
|
|
23
|
+
end
|
|
24
|
+
}
|
|
25
|
+
Merb::Dispatcher::DefaultException.before error_notifier
|
|
26
|
+
Exceptions.before error_notifier
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|