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,397 @@
|
|
|
1
|
+
require 'new_relic/agent'
|
|
2
|
+
require 'new_relic/control'
|
|
3
|
+
require 'new_relic/agent/transaction_sample_builder'
|
|
4
|
+
module NewRelic
|
|
5
|
+
module Agent
|
|
6
|
+
|
|
7
|
+
# This class contains the logic of sampling a transaction -
|
|
8
|
+
# creation and modification of transaction samples
|
|
9
|
+
class TransactionSampler
|
|
10
|
+
|
|
11
|
+
# Module defining methods stubbed out when the agent is disabled
|
|
12
|
+
module Shim #:nodoc:
|
|
13
|
+
def notice_first_scope_push(*args); end
|
|
14
|
+
def notice_push_scope(*args); end
|
|
15
|
+
def notice_pop_scope(*args); end
|
|
16
|
+
def notice_scope_empty(*args); end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
BUILDER_KEY = :transaction_sample_builder
|
|
20
|
+
|
|
21
|
+
attr_accessor :stack_trace_threshold, :random_sampling, :sampling_rate
|
|
22
|
+
attr_accessor :explain_threshold, :explain_enabled, :transaction_threshold
|
|
23
|
+
attr_reader :samples, :last_sample, :disabled
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
# @samples is an array of recent samples up to @max_samples in
|
|
27
|
+
# size - it's only used by developer mode
|
|
28
|
+
@samples = []
|
|
29
|
+
@max_samples = 100
|
|
30
|
+
|
|
31
|
+
# @harvest_count is a count of harvests used for random
|
|
32
|
+
# sampling - we pull 1 @random_sample in every @sampling_rate harvests
|
|
33
|
+
@harvest_count = 0
|
|
34
|
+
@random_sample = nil
|
|
35
|
+
@sampling_rate = 10
|
|
36
|
+
configure!
|
|
37
|
+
|
|
38
|
+
# This lock is used to synchronize access to the @last_sample
|
|
39
|
+
# and related variables. It can become necessary on JRuby or
|
|
40
|
+
# any 'honest-to-god'-multithreaded system
|
|
41
|
+
@samples_lock = Mutex.new
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def configure!
|
|
45
|
+
# @segment_limit and @stack_trace_threshold come from the
|
|
46
|
+
# configuration file, with built-in defaults that should
|
|
47
|
+
# suffice for most customers
|
|
48
|
+
|
|
49
|
+
# enable if config.fetch('enabled', true)
|
|
50
|
+
|
|
51
|
+
@segment_limit = config.fetch('limit_segments', 4000)
|
|
52
|
+
@stack_trace_threshold = config.fetch('stack_trace_threshold', 0.500).to_f
|
|
53
|
+
@explain_threshold = config.fetch('explain_threshold', 0.5).to_f
|
|
54
|
+
@explain_enabled = config.fetch('explain_enabled', true)
|
|
55
|
+
@transaction_threshold = config.fetch('transation_threshold', 2.0)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def config
|
|
59
|
+
NewRelic::Control.instance.fetch('transaction_tracer', {})
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Returns the current sample id, delegated from `builder`
|
|
63
|
+
def current_sample_id
|
|
64
|
+
b=builder
|
|
65
|
+
b and b.sample_id
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Enable the transaction sampler - this also registers it with
|
|
69
|
+
# the statistics engine.
|
|
70
|
+
def enable
|
|
71
|
+
@disabled = false
|
|
72
|
+
NewRelic::Agent.instance.stats_engine.transaction_sampler = self
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Disable the transaction sampler - this also deregisters it
|
|
76
|
+
# with the statistics engine.
|
|
77
|
+
def disable
|
|
78
|
+
@disabled = true
|
|
79
|
+
NewRelic::Agent.instance.stats_engine.remove_transaction_sampler(self)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def enabled?
|
|
83
|
+
!@disabled
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Set with an integer value n, this takes one in every n
|
|
87
|
+
# harvested samples. It also resets the harvest count to a
|
|
88
|
+
# random integer between 0 and (n-1)
|
|
89
|
+
def sampling_rate=(val)
|
|
90
|
+
@sampling_rate = val.to_i
|
|
91
|
+
@harvest_count = rand(val.to_i).to_i
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# Creates a new transaction sample builder, unless the
|
|
96
|
+
# transaction sampler is disabled. Takes a time parameter for
|
|
97
|
+
# the start of the transaction sample
|
|
98
|
+
def notice_first_scope_push(time)
|
|
99
|
+
start_builder(time.to_f) unless disabled
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# This delegates to the builder to create a new open transaction
|
|
103
|
+
# segment for the specified scope, beginning at the optionally
|
|
104
|
+
# specified time.
|
|
105
|
+
#
|
|
106
|
+
# Note that in developer mode, this captures a stacktrace for
|
|
107
|
+
# the beginning of each segment, which can be fairly slow
|
|
108
|
+
def notice_push_scope(scope, time=Time.now)
|
|
109
|
+
return unless builder
|
|
110
|
+
|
|
111
|
+
builder.trace_entry(scope, time.to_f)
|
|
112
|
+
|
|
113
|
+
capture_segment_trace if NewRelic::Control.instance.developer_mode?
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# in developer mode, capture the stack trace with the segment.
|
|
117
|
+
# this is cpu and memory expensive and therefore should not be
|
|
118
|
+
# turned on in production mode
|
|
119
|
+
def capture_segment_trace
|
|
120
|
+
return unless NewRelic::Control.instance.developer_mode?
|
|
121
|
+
segment = builder.current_segment
|
|
122
|
+
if segment
|
|
123
|
+
# Strip stack frames off the top that match /new_relic/agent/
|
|
124
|
+
trace = caller
|
|
125
|
+
while trace.first =~/\/lib\/new_relic\/agent\//
|
|
126
|
+
trace.shift
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
trace = trace[0..39] if trace.length > 40
|
|
130
|
+
segment[:backtrace] = trace
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Defaults to zero, otherwise delegated to the transaction
|
|
135
|
+
# sample builder
|
|
136
|
+
def scope_depth
|
|
137
|
+
return 0 unless builder
|
|
138
|
+
|
|
139
|
+
builder.scope_depth
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Informs the transaction sample builder about the end of a
|
|
143
|
+
# traced scope
|
|
144
|
+
def notice_pop_scope(scope, time = Time.now)
|
|
145
|
+
return unless builder
|
|
146
|
+
raise "frozen already???" if builder.sample.frozen?
|
|
147
|
+
builder.trace_exit(scope, time.to_f)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# This is called when we are done with the transaction. We've
|
|
151
|
+
# unwound the stack to the top level. It also clears the
|
|
152
|
+
# transaction sample builder so that it won't continue to have
|
|
153
|
+
# scopes appended to it.
|
|
154
|
+
#
|
|
155
|
+
# It sets various instance variables to the finished sample,
|
|
156
|
+
# depending on which settings are active. See `store_sample`
|
|
157
|
+
def notice_scope_empty(time=Time.now)
|
|
158
|
+
|
|
159
|
+
last_builder = builder
|
|
160
|
+
return unless last_builder
|
|
161
|
+
|
|
162
|
+
last_builder.finish_trace(time.to_f)
|
|
163
|
+
clear_builder
|
|
164
|
+
return if last_builder.ignored?
|
|
165
|
+
|
|
166
|
+
@samples_lock.synchronize do
|
|
167
|
+
# NB this instance variable may be used elsewhere, it's not
|
|
168
|
+
# just a side effect
|
|
169
|
+
@last_sample = last_builder.sample
|
|
170
|
+
store_sample(@last_sample)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Samples can be stored in three places: the random sample
|
|
175
|
+
# variable, when random sampling is active, the developer mode
|
|
176
|
+
# @samples array, and the @slowest_sample variable if it is
|
|
177
|
+
# slower than the current occupant of that slot
|
|
178
|
+
def store_sample(sample)
|
|
179
|
+
store_random_sample(sample)
|
|
180
|
+
store_sample_for_developer_mode(sample)
|
|
181
|
+
store_slowest_sample(sample)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Only active when random sampling is true - this is very rarely
|
|
185
|
+
# used. Always store the most recent sample so that random
|
|
186
|
+
# sampling can pick a few of the samples to store, upon harvest
|
|
187
|
+
def store_random_sample(sample)
|
|
188
|
+
if @random_sampling
|
|
189
|
+
@random_sample = sample
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Samples take up a ton of memory, so we only store a lot of
|
|
194
|
+
# them in developer mode - we truncate to @max_samples
|
|
195
|
+
def store_sample_for_developer_mode(sample)
|
|
196
|
+
return unless NewRelic::Control.instance.developer_mode?
|
|
197
|
+
@samples = [] unless @samples
|
|
198
|
+
@samples << sample
|
|
199
|
+
truncate_samples
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Sets @slowest_sample to the passed in sample if it is slower
|
|
203
|
+
# than the current sample in @slowest_sample
|
|
204
|
+
def store_slowest_sample(sample)
|
|
205
|
+
@slowest_sample = sample if slowest_sample?(@slowest_sample, sample)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Checks to see if the old sample exists, or if it's duration is
|
|
209
|
+
# less than the new sample
|
|
210
|
+
def slowest_sample?(old_sample, new_sample)
|
|
211
|
+
old_sample.nil? || (new_sample.duration > old_sample.duration)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Smashes the @samples array down to the length of @max_samples
|
|
215
|
+
# by taking the last @max_samples elements of the array
|
|
216
|
+
def truncate_samples
|
|
217
|
+
if @samples.length > @max_samples
|
|
218
|
+
@samples = @samples[-@max_samples..-1]
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Delegates to the builder to store the path, uri, and
|
|
223
|
+
# parameters if the sampler is active
|
|
224
|
+
def notice_transaction(path, uri=nil, params={})
|
|
225
|
+
builder.set_transaction_info(path, uri, params) if !disabled && builder
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Tells the builder to ignore a transaction, if we are currently
|
|
229
|
+
# creating one. Only causes the sample to be ignored upon end of
|
|
230
|
+
# the transaction, and does not change the metrics gathered
|
|
231
|
+
# outside of the sampler
|
|
232
|
+
def ignore_transaction
|
|
233
|
+
builder.ignore_transaction if builder
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# For developer mode profiling support - delegates to the builder
|
|
237
|
+
def notice_profile(profile)
|
|
238
|
+
builder.set_profile(profile) if builder
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Sets the CPU time used by a transaction, delegates to the builder
|
|
242
|
+
def notice_transaction_cpu_time(cpu_time)
|
|
243
|
+
builder.set_transaction_cpu_time(cpu_time) if builder
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
MAX_DATA_LENGTH = 16384
|
|
247
|
+
# This method is used to record metadata into the currently
|
|
248
|
+
# active segment like a sql query, memcache key, or Net::HTTP uri
|
|
249
|
+
#
|
|
250
|
+
# duration is seconds, float value.
|
|
251
|
+
def notice_extra_data(message, duration, key, config=nil, config_key=nil)
|
|
252
|
+
return unless builder
|
|
253
|
+
segment = builder.current_segment
|
|
254
|
+
if segment
|
|
255
|
+
segment[key] = truncate_message(append_new_message(segment[key],
|
|
256
|
+
message))
|
|
257
|
+
segment[config_key] = config if config_key
|
|
258
|
+
append_backtrace(segment, duration)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
private :notice_extra_data
|
|
263
|
+
|
|
264
|
+
# Truncates the message to `MAX_DATA_LENGTH` if needed, and
|
|
265
|
+
# appends an ellipsis because it makes the trucation clearer in
|
|
266
|
+
# the UI
|
|
267
|
+
def truncate_message(message)
|
|
268
|
+
if message.length > (MAX_DATA_LENGTH - 4)
|
|
269
|
+
message[0..MAX_DATA_LENGTH - 4] + '...'
|
|
270
|
+
else
|
|
271
|
+
message
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Allows the addition of multiple pieces of metadata to one
|
|
276
|
+
# segment - i.e. traced method calls multiple sql queries
|
|
277
|
+
def append_new_message(old_message, message)
|
|
278
|
+
if old_message
|
|
279
|
+
old_message + ";\n" + message
|
|
280
|
+
else
|
|
281
|
+
message
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# Appends a backtrace to a segment if that segment took longer
|
|
286
|
+
# than the specified duration
|
|
287
|
+
def append_backtrace(segment, duration)
|
|
288
|
+
segment[:backtrace] = caller.join("\n") if duration >= @stack_trace_threshold
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# some statements (particularly INSERTS with large BLOBS
|
|
292
|
+
# may be very large; we should trim them to a maximum usable length
|
|
293
|
+
# config is the driver configuration for the connection
|
|
294
|
+
# duration is seconds, float value.
|
|
295
|
+
def notice_sql(sql, config, duration)
|
|
296
|
+
if NewRelic::Agent.is_sql_recorded?
|
|
297
|
+
notice_extra_data(sql, duration, :sql, config, :connection_config)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Adds non-sql metadata to a segment - generally the memcached
|
|
302
|
+
# key
|
|
303
|
+
#
|
|
304
|
+
# duration is seconds, float value.
|
|
305
|
+
def notice_nosql(key, duration)
|
|
306
|
+
notice_extra_data(key, duration, :key)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# Every 1/n harvests, adds the most recent sample to the harvest
|
|
310
|
+
# array if it exists. Makes sure that the random sample is not
|
|
311
|
+
# also the slowest sample for this harvest by `uniq!`ing the
|
|
312
|
+
# result array
|
|
313
|
+
#
|
|
314
|
+
# random sampling is very, very seldom used
|
|
315
|
+
def add_random_sample_to(result)
|
|
316
|
+
return unless @random_sampling && @sampling_rate && @sampling_rate.to_i > 0
|
|
317
|
+
@harvest_count += 1
|
|
318
|
+
if (@harvest_count.to_i % @sampling_rate.to_i) == 0
|
|
319
|
+
result << @random_sample if @random_sample
|
|
320
|
+
end
|
|
321
|
+
result.uniq!
|
|
322
|
+
nil # don't assume this method returns anything
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Returns an array of slow samples, with either one or two
|
|
326
|
+
# elements - one element unless random sampling is enabled. The
|
|
327
|
+
# sample returned will be the slowest sample among those
|
|
328
|
+
# available during this harvest
|
|
329
|
+
def add_samples_to(result, slow_threshold)
|
|
330
|
+
if @slowest_sample && @slowest_sample.duration >= slow_threshold
|
|
331
|
+
result << @slowest_sample
|
|
332
|
+
end
|
|
333
|
+
result.compact!
|
|
334
|
+
result = result.sort_by { |x| x.duration }
|
|
335
|
+
result = result[-1..-1] || []
|
|
336
|
+
add_random_sample_to(result)
|
|
337
|
+
result
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# get the set of collected samples, merging into previous samples,
|
|
341
|
+
# and clear the collected sample list. Truncates samples to a
|
|
342
|
+
# specified @segment_limit to save memory and bandwith
|
|
343
|
+
# transmitting samples to the server.
|
|
344
|
+
def harvest(previous = [], slow_threshold = 2.0)
|
|
345
|
+
return [] if disabled
|
|
346
|
+
result = Array(previous)
|
|
347
|
+
@samples_lock.synchronize do
|
|
348
|
+
result = add_samples_to(result, slow_threshold)
|
|
349
|
+
# clear previous transaction samples
|
|
350
|
+
@slowest_sample = nil
|
|
351
|
+
@random_sample = nil
|
|
352
|
+
@last_sample = nil
|
|
353
|
+
end
|
|
354
|
+
# Truncate the samples at 2100 segments. The UI will clamp them at 2000 segments anyway.
|
|
355
|
+
# This will save us memory and bandwidth.
|
|
356
|
+
result.each { |sample| sample.truncate(@segment_limit) }
|
|
357
|
+
result
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# reset samples without rebooting the web server
|
|
361
|
+
def reset!
|
|
362
|
+
@samples = []
|
|
363
|
+
@last_sample = nil
|
|
364
|
+
@random_sample = nil
|
|
365
|
+
@slowest_sample = nil
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
private
|
|
369
|
+
|
|
370
|
+
# Checks to see if the transaction sampler is disabled, if
|
|
371
|
+
# transaction trace recording is disabled by a thread local, or
|
|
372
|
+
# if execution is untraced - if so it clears the transaction
|
|
373
|
+
# sample builder from the thread local, otherwise it generates a
|
|
374
|
+
# new transaction sample builder with the stated time as a
|
|
375
|
+
# starting point and saves it in the thread local variable
|
|
376
|
+
def start_builder(time=nil)
|
|
377
|
+
if disabled || !NewRelic::Agent.is_transaction_traced? || !NewRelic::Agent.is_execution_traced?
|
|
378
|
+
clear_builder
|
|
379
|
+
else
|
|
380
|
+
Thread::current[BUILDER_KEY] ||= TransactionSampleBuilder.new(time)
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# The current thread-local transaction sample builder
|
|
385
|
+
def builder
|
|
386
|
+
Thread::current[BUILDER_KEY]
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# Sets the thread local variable storing the transaction sample
|
|
390
|
+
# builder to nil to clear it
|
|
391
|
+
def clear_builder
|
|
392
|
+
Thread::current[BUILDER_KEY] = nil
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
module NewRelic
|
|
3
|
+
module Agent
|
|
4
|
+
|
|
5
|
+
# A worker loop executes a set of registered tasks on a single thread.
|
|
6
|
+
# A task is a proc or block with a specified call period in seconds.
|
|
7
|
+
class WorkerLoop
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@log = log
|
|
11
|
+
@should_run = true
|
|
12
|
+
@next_invocation_time = Time.now
|
|
13
|
+
@period = 60.0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# returns a class-level memoized mutex to make sure we don't run overlapping
|
|
17
|
+
def lock
|
|
18
|
+
@@lock ||= Mutex.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# a helper to access the NewRelic::Control.instance.log
|
|
22
|
+
def log
|
|
23
|
+
NewRelic::Control.instance.log
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Run infinitely, calling the registered tasks at their specified
|
|
27
|
+
# call periods. The caller is responsible for creating the thread
|
|
28
|
+
# that runs this worker loop. This will run the task immediately.
|
|
29
|
+
def run(period=nil, &block)
|
|
30
|
+
@period = period if period
|
|
31
|
+
@next_invocation_time = (Time.now + @period)
|
|
32
|
+
@task = block
|
|
33
|
+
while keep_running do
|
|
34
|
+
now = Time.now
|
|
35
|
+
while now < @next_invocation_time
|
|
36
|
+
# sleep until this next task's scheduled invocation time
|
|
37
|
+
sleep_time = @next_invocation_time - now
|
|
38
|
+
sleep sleep_time if sleep_time > 0
|
|
39
|
+
now = Time.now
|
|
40
|
+
end
|
|
41
|
+
run_task if keep_running
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# a simple accessor for @should_run
|
|
46
|
+
def keep_running
|
|
47
|
+
@should_run
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Sets @should_run to false. Returns false
|
|
51
|
+
def stop
|
|
52
|
+
@should_run = false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Executes the block given to the worker loop, and handles many
|
|
56
|
+
# possible errors. Also updates the execution time so that the
|
|
57
|
+
# next run occurs on schedule, even if we execute at some odd time
|
|
58
|
+
def run_task
|
|
59
|
+
begin
|
|
60
|
+
lock.synchronize do
|
|
61
|
+
@task.call
|
|
62
|
+
end
|
|
63
|
+
rescue ServerError => e
|
|
64
|
+
log.debug "Server Error: #{e}"
|
|
65
|
+
rescue NewRelic::Agent::ForceRestartException, NewRelic::Agent::ForceDisconnectException
|
|
66
|
+
# blow out the loop
|
|
67
|
+
raise
|
|
68
|
+
rescue RuntimeError => e
|
|
69
|
+
# This is probably a server error which has been logged in the server along
|
|
70
|
+
# with your account name.
|
|
71
|
+
log.error "Error running task in worker loop, likely a server error (#{e})"
|
|
72
|
+
log.debug e.backtrace.join("\n")
|
|
73
|
+
rescue Timeout::Error, NewRelic::Agent::ServerConnectionException
|
|
74
|
+
# Want to ignore these because they are handled already
|
|
75
|
+
rescue SystemExit, NoMemoryError, SignalException
|
|
76
|
+
raise
|
|
77
|
+
rescue Exception => e
|
|
78
|
+
# Don't blow out the stack for anything that hasn't already propagated
|
|
79
|
+
log.error "Error running task in Agent Worker Loop '#{e}': #{e.backtrace.first}"
|
|
80
|
+
log.debug e.backtrace.join("\n")
|
|
81
|
+
end
|
|
82
|
+
now = Time.now
|
|
83
|
+
while @next_invocation_time <= now && @period > 0
|
|
84
|
+
@next_invocation_time += @period
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|