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,187 @@
|
|
|
1
|
+
require 'new_relic/language_support'
|
|
2
|
+
|
|
3
|
+
module NewRelic
|
|
4
|
+
module Agent
|
|
5
|
+
class StatsEngine
|
|
6
|
+
# Handles methods related to actual Metric collection
|
|
7
|
+
module MetricStats
|
|
8
|
+
# A simple mutex-synchronized hash to make sure our statistics
|
|
9
|
+
# are internally consistent even in truly-threaded rubies like JRuby
|
|
10
|
+
class SynchronizedHash < ::Hash
|
|
11
|
+
include NewRelic::LanguageSupport::SynchronizedHash
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@lock = Mutex.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def []=(*args)
|
|
18
|
+
@lock.synchronize { super }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def clear(*args)
|
|
22
|
+
@lock.synchronize { super }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def delete(*args)
|
|
26
|
+
@lock.synchronize { super }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def delete_if(*args)
|
|
30
|
+
@lock.synchronize { super }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns all of the metric names of all the stats in the engine
|
|
35
|
+
def metrics
|
|
36
|
+
stats_hash.keys.map(&:to_s)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# a simple accessor for looking up a stat with no scope -
|
|
40
|
+
# returns a new stats object if no stats object for that
|
|
41
|
+
# metric exists yet
|
|
42
|
+
def get_stats_no_scope(metric_name)
|
|
43
|
+
stats_hash[NewRelic::MetricSpec.new(metric_name, '')] ||= NewRelic::MethodTraceStats.new
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# This version allows a caller to pass a stat class to use
|
|
47
|
+
def get_custom_stats(metric_name, stat_class)
|
|
48
|
+
stats_hash[NewRelic::MetricSpec.new(metric_name)] ||= stat_class.new
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# If use_scope is true, two chained metrics are created, one with scope and one without
|
|
52
|
+
# If scoped_metric_only is true, only a scoped metric is created (used by rendering metrics which by definition are per controller only)
|
|
53
|
+
def get_stats(metric_name, use_scope = true, scoped_metric_only = false, scope = nil)
|
|
54
|
+
scope ||= scope_name if use_scope
|
|
55
|
+
if scoped_metric_only
|
|
56
|
+
spec = NewRelic::MetricSpec.new metric_name, scope
|
|
57
|
+
stats = stats_hash[spec] ||= NewRelic::MethodTraceStats.new
|
|
58
|
+
else
|
|
59
|
+
stats = stats_hash[NewRelic::MetricSpec.new(metric_name)] ||= NewRelic::MethodTraceStats.new
|
|
60
|
+
if scope && scope != metric_name
|
|
61
|
+
spec = NewRelic::MetricSpec.new metric_name, scope
|
|
62
|
+
stats = stats_hash[spec] ||= NewRelic::ScopedMethodTraceStats.new(stats)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
stats
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns a stat if one exists, otherwise returns nil. If you
|
|
69
|
+
# want auto-initialization, use one of get_stats or get_stats_no_scope
|
|
70
|
+
def lookup_stats(metric_name, scope_name = '')
|
|
71
|
+
stats_hash[NewRelic::MetricSpec.new(metric_name, scope_name)]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# This module was extracted from the harvest method and should
|
|
75
|
+
# be refactored
|
|
76
|
+
module Harvest
|
|
77
|
+
|
|
78
|
+
# merge data from previous harvests into this stats engine -
|
|
79
|
+
# takes into account the case where there are new stats for
|
|
80
|
+
# that metric, and the case where there is no current data
|
|
81
|
+
# for that metric
|
|
82
|
+
def merge_data(metric_data_hash)
|
|
83
|
+
metric_data_hash.each do |metric_spec, metric_data|
|
|
84
|
+
new_data = lookup_stats(metric_spec.name, metric_spec.scope)
|
|
85
|
+
if new_data
|
|
86
|
+
new_data.merge!(metric_data.stats)
|
|
87
|
+
else
|
|
88
|
+
stats_hash[metric_spec] = metric_data.stats
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
def get_stats_hash_from(engine_or_hash)
|
|
95
|
+
if engine_or_hash.is_a?(StatsEngine)
|
|
96
|
+
engine_or_hash.stats_hash
|
|
97
|
+
else
|
|
98
|
+
engine_or_hash
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def coerce_to_metric_spec(metric_spec)
|
|
103
|
+
if metric_spec.is_a?(NewRelic::MetricSpec)
|
|
104
|
+
metric_spec
|
|
105
|
+
else
|
|
106
|
+
NewRelic::MetricSpec.new(metric_spec)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def clone_and_reset_stats(metric_spec, stats)
|
|
111
|
+
if stats.nil?
|
|
112
|
+
raise "Nil stats for #{metric_spec.name} (#{metric_spec.scope})"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
stats_copy = stats.clone
|
|
116
|
+
stats.reset
|
|
117
|
+
stats_copy
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# if the previous timeslice data has not been reported (due to an error of some sort)
|
|
121
|
+
# then we need to merge this timeslice with the previously accumulated - but not sent
|
|
122
|
+
# data
|
|
123
|
+
def merge_old_data!(metric_spec, stats, old_data)
|
|
124
|
+
metric_data = old_data[metric_spec]
|
|
125
|
+
stats.merge!(metric_data.stats) unless metric_data.nil?
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def add_data_to_send_unless_empty(data, stats, metric_spec, id)
|
|
129
|
+
# don't bother collecting and reporting stats that have
|
|
130
|
+
# zero-values for this timeslice. significant
|
|
131
|
+
# performance boost and storage savings.
|
|
132
|
+
return if stats.is_reset?
|
|
133
|
+
data[metric_spec] = NewRelic::MetricData.new((id ? nil : metric_spec), stats, id)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def merge_stats(other_engine_or_hash, metric_ids)
|
|
137
|
+
old_data = get_stats_hash_from(other_engine_or_hash)
|
|
138
|
+
|
|
139
|
+
timeslice_data = {}
|
|
140
|
+
stats_hash.each do | metric_spec, stats |
|
|
141
|
+
|
|
142
|
+
metric_spec = coerce_to_metric_spec(metric_spec)
|
|
143
|
+
stats_copy = clone_and_reset_stats(metric_spec, stats)
|
|
144
|
+
merge_old_data!(metric_spec, stats_copy, old_data)
|
|
145
|
+
add_data_to_send_unless_empty(timeslice_data, stats_copy, metric_spec, metric_ids[metric_spec])
|
|
146
|
+
end
|
|
147
|
+
timeslice_data
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
include Harvest
|
|
152
|
+
|
|
153
|
+
# Harvest the timeslice data. First recombine current statss
|
|
154
|
+
# with any previously
|
|
155
|
+
# unsent metrics, clear out stats cache, and return the current
|
|
156
|
+
# stats.
|
|
157
|
+
# ---
|
|
158
|
+
# Note: this is not synchronized. There is still some risk in this and
|
|
159
|
+
# we will revisit later to see if we can make this more robust without
|
|
160
|
+
# sacrificing efficiency.
|
|
161
|
+
# +++
|
|
162
|
+
def harvest_timeslice_data(previous_timeslice_data, metric_ids)
|
|
163
|
+
|
|
164
|
+
poll harvest_samplers
|
|
165
|
+
merge_stats(previous_timeslice_data, metric_ids)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Remove all stats. For test code only.
|
|
169
|
+
def clear_stats
|
|
170
|
+
@stats_hash = SynchronizedHash.new
|
|
171
|
+
NewRelic::Agent::BusyCalculator.reset
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Reset each of the stats, such as when a new passenger instance starts up.
|
|
175
|
+
def reset_stats
|
|
176
|
+
stats_hash.values.each { |s| s.reset }
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# returns a memoized SynchronizedHash that holds the actual
|
|
180
|
+
# instances of Stats keyed off their MetricName
|
|
181
|
+
def stats_hash
|
|
182
|
+
@stats_hash ||= SynchronizedHash.new
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module NewRelic
|
|
2
|
+
module Agent
|
|
3
|
+
class StatsEngine
|
|
4
|
+
module Shim # :nodoc:
|
|
5
|
+
def add_sampler(*args); end
|
|
6
|
+
def add_harvest_sampler(*args); end
|
|
7
|
+
def start_sampler_thread(*args); end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Contains statistics engine extensions to support the concept of samplers
|
|
11
|
+
module Samplers
|
|
12
|
+
|
|
13
|
+
# By default a sampler polls on harvest time, once a minute. However you can
|
|
14
|
+
# override #use_harvest_sampler? to return false and it will sample
|
|
15
|
+
# every POLL_PERIOD seconds on a background thread.
|
|
16
|
+
POLL_PERIOD = 20
|
|
17
|
+
|
|
18
|
+
# starts the sampler thread which runs periodically, rather than
|
|
19
|
+
# at harvest time. This is deprecated, and should not actually
|
|
20
|
+
# be used - mo threads mo problems
|
|
21
|
+
#
|
|
22
|
+
# returns unless there are actually periodic samplers to run
|
|
23
|
+
def start_sampler_thread
|
|
24
|
+
|
|
25
|
+
return if @sampler_thread && @sampler_thread.alive?
|
|
26
|
+
|
|
27
|
+
# start up a thread that will periodically poll for metric samples
|
|
28
|
+
return if periodic_samplers.empty?
|
|
29
|
+
|
|
30
|
+
@sampler_thread = Thread.new do
|
|
31
|
+
while true do
|
|
32
|
+
begin
|
|
33
|
+
sleep POLL_PERIOD
|
|
34
|
+
poll periodic_samplers
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
@sampler_thread['newrelic_label'] = 'Sampler Tasks'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def add_sampler_to(sampler_array, sampler)
|
|
44
|
+
raise "Sampler #{sampler.inspect} is already registered. Don't call add_sampler directly anymore." if sampler_array.include?(sampler)
|
|
45
|
+
sampler_array << sampler
|
|
46
|
+
sampler.stats_engine = self
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def log_added_sampler(type, sampler)
|
|
50
|
+
log.debug "Adding #{type} sampler: #{sampler.inspect}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
public
|
|
54
|
+
|
|
55
|
+
# Add an instance of Sampler to be invoked about every 10 seconds on a background
|
|
56
|
+
# thread.
|
|
57
|
+
def add_sampler(sampler)
|
|
58
|
+
add_sampler_to(periodic_samplers, sampler)
|
|
59
|
+
log_added_sampler('periodic', sampler)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Add a sampler to be invoked just before each harvest.
|
|
63
|
+
def add_harvest_sampler(sampler)
|
|
64
|
+
add_sampler_to(harvest_samplers, sampler)
|
|
65
|
+
log_added_sampler('harvest-time', sampler)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
# Call poll on each of the samplers. Remove
|
|
71
|
+
# the sampler if it raises.
|
|
72
|
+
def poll(samplers)
|
|
73
|
+
samplers.delete_if do |sampled_item|
|
|
74
|
+
begin
|
|
75
|
+
sampled_item.poll
|
|
76
|
+
false # it's okay. don't delete it.
|
|
77
|
+
rescue Exception => e
|
|
78
|
+
log.error "Removing #{sampled_item} from list"
|
|
79
|
+
log.error e
|
|
80
|
+
log.debug e.backtrace.to_s
|
|
81
|
+
true # remove the sampler
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def harvest_samplers
|
|
87
|
+
@harvest_samplers ||= []
|
|
88
|
+
end
|
|
89
|
+
def periodic_samplers
|
|
90
|
+
@periodic_samplers ||= []
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module NewRelic
|
|
3
|
+
module Agent
|
|
4
|
+
class StatsEngine
|
|
5
|
+
# A simple stack element that tracks the current name and length
|
|
6
|
+
# of the executing stack
|
|
7
|
+
class ScopeStackElement
|
|
8
|
+
attr_reader :name, :deduct_call_time_from_parent
|
|
9
|
+
attr_accessor :children_time
|
|
10
|
+
def initialize(name, deduct_call_time)
|
|
11
|
+
@name = name
|
|
12
|
+
@deduct_call_time_from_parent = deduct_call_time
|
|
13
|
+
@children_time = 0
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Handles pushing and popping elements onto an internal stack that
|
|
18
|
+
# tracks where time should be allocated in Transaction Traces
|
|
19
|
+
module Transactions
|
|
20
|
+
|
|
21
|
+
# Defines methods that stub out the stats engine methods
|
|
22
|
+
# when the agent is disabled
|
|
23
|
+
module Shim # :nodoc:
|
|
24
|
+
def start_transaction(*args); end
|
|
25
|
+
def end_transaction; end
|
|
26
|
+
def push_scope(*args); end
|
|
27
|
+
def transaction_sampler=(*args); end
|
|
28
|
+
def sql_sampler=(*args); end
|
|
29
|
+
def scope_name=(*args); end
|
|
30
|
+
def scope_name; end
|
|
31
|
+
def pop_scope(*args); end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# add a new transaction sampler, unless we're currently in a
|
|
35
|
+
# transaction (then we fail)
|
|
36
|
+
def transaction_sampler= sampler
|
|
37
|
+
fail "Can't add a scope listener midflight in a transaction" if scope_stack.any?
|
|
38
|
+
@transaction_sampler = sampler
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# removes a transaction sampler
|
|
42
|
+
def remove_transaction_sampler(l)
|
|
43
|
+
@transaction_sampler = nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def sql_sampler= sampler
|
|
47
|
+
fail "Can't add a scope listener midflight in a transaction" if scope_stack.any?
|
|
48
|
+
@sql_sampler = sampler
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def remove_sql_sampler(l)
|
|
52
|
+
@sql_sampler = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Pushes a scope onto the transaction stack - this generates a
|
|
56
|
+
# TransactionSample::Segment at the end of transaction execution
|
|
57
|
+
def push_scope(metric, time = Time.now.to_f, deduct_call_time_from_parent = true)
|
|
58
|
+
|
|
59
|
+
stack = scope_stack
|
|
60
|
+
if collecting_gc?
|
|
61
|
+
if stack.empty?
|
|
62
|
+
# reset the gc time so we only include gc time spent during this call
|
|
63
|
+
@last_gc_timestamp = gc_time
|
|
64
|
+
@last_gc_count = gc_collections
|
|
65
|
+
else
|
|
66
|
+
capture_gc_time
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
@transaction_sampler.notice_push_scope metric, time if @transaction_sampler
|
|
70
|
+
scope = ScopeStackElement.new(metric, deduct_call_time_from_parent)
|
|
71
|
+
stack.push scope
|
|
72
|
+
scope
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Pops a scope off the transaction stack - this updates the
|
|
76
|
+
# transaction sampler that we've finished execution of a traced method
|
|
77
|
+
def pop_scope(expected_scope, duration, time=Time.now.to_f)
|
|
78
|
+
capture_gc_time if collecting_gc?
|
|
79
|
+
stack = scope_stack
|
|
80
|
+
scope = stack.pop
|
|
81
|
+
fail "unbalanced pop from blame stack, got #{scope ? scope.name : 'nil'}, expected #{expected_scope ? expected_scope.name : 'nil'}" if scope != expected_scope
|
|
82
|
+
|
|
83
|
+
if !stack.empty?
|
|
84
|
+
if scope.deduct_call_time_from_parent
|
|
85
|
+
stack.last.children_time += duration
|
|
86
|
+
else
|
|
87
|
+
stack.last.children_time += scope.children_time
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
@transaction_sampler.notice_pop_scope(scope.name, time) if @transaction_sampler
|
|
91
|
+
scope
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Returns the latest ScopeStackElement
|
|
95
|
+
def peek_scope
|
|
96
|
+
scope_stack.last
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# set the name of the transaction for the current thread, which will be used
|
|
100
|
+
# to define the scope of all traced methods called on this thread until the
|
|
101
|
+
# scope stack is empty.
|
|
102
|
+
#
|
|
103
|
+
# currently the transaction name is the name of the controller action that
|
|
104
|
+
# is invoked via the dispatcher, but conceivably we could use other transaction
|
|
105
|
+
# names in the future if the traced application does more than service http request
|
|
106
|
+
# via controller actions
|
|
107
|
+
def scope_name=(transaction)
|
|
108
|
+
Thread::current[:newrelic_scope_name] = transaction
|
|
109
|
+
Thread::current[:newrelic_most_recent_transaction] = transaction
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns the current scope name from the thread local
|
|
113
|
+
def scope_name
|
|
114
|
+
Thread::current[:newrelic_scope_name]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Start a new transaction, unless one is already in progress
|
|
118
|
+
def start_transaction(name = nil)
|
|
119
|
+
Thread::current[:newrelic_scope_stack] ||= []
|
|
120
|
+
self.scope_name = name if name
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Try to clean up gracefully, otherwise we leave things hanging around on thread locals.
|
|
124
|
+
# If it looks like a transaction is still in progress, then maybe this is an inner transaction
|
|
125
|
+
# and is ignored.
|
|
126
|
+
#
|
|
127
|
+
def end_transaction
|
|
128
|
+
stack = scope_stack
|
|
129
|
+
|
|
130
|
+
if stack && stack.empty?
|
|
131
|
+
Thread::current[:newrelic_scope_stack] = nil
|
|
132
|
+
Thread::current[:newrelic_scope_name] = nil
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
# Make sure we don't do this in a multi-threaded environment
|
|
139
|
+
def collecting_gc?
|
|
140
|
+
if !defined?(@@collecting_gc)
|
|
141
|
+
@@collecting_gc = false
|
|
142
|
+
if !NewRelic::Control.instance.multi_threaded?
|
|
143
|
+
@@collecting_gc = true if GC.respond_to?(:time) && GC.respond_to?(:collections) # 1.8.x
|
|
144
|
+
@@collecting_gc = true if defined?(GC::Profiler) && GC::Profiler.enabled? # 1.9.2
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
@@collecting_gc
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# The total number of times the garbage collector has run since
|
|
151
|
+
# profiling was enabled
|
|
152
|
+
def gc_collections
|
|
153
|
+
if GC.respond_to?(:count)
|
|
154
|
+
GC.count
|
|
155
|
+
elsif GC.respond_to?(:collections)
|
|
156
|
+
GC.collections
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# The total amount of time taken by garbage collection since
|
|
161
|
+
# profiling was enabled
|
|
162
|
+
def gc_time
|
|
163
|
+
if GC.respond_to?(:time)
|
|
164
|
+
GC.time
|
|
165
|
+
elsif defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time)
|
|
166
|
+
# The 1.9 profiler returns a time in usec
|
|
167
|
+
GC::Profiler.total_time * 1000000.0
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Assumes collecting_gc?
|
|
172
|
+
def capture_gc_time
|
|
173
|
+
# Skip this if we are already in this segment
|
|
174
|
+
return if !scope_stack.empty? && scope_stack.last.name == "GC/cumulative"
|
|
175
|
+
num_calls = gc_collections - @last_gc_count
|
|
176
|
+
elapsed = (gc_time - @last_gc_timestamp).to_f
|
|
177
|
+
@last_gc_timestamp = gc_time
|
|
178
|
+
@last_gc_count = gc_collections
|
|
179
|
+
|
|
180
|
+
if defined?(GC::Profiler)
|
|
181
|
+
GC::Profiler.clear
|
|
182
|
+
@last_gc_timestamp = 0
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
if num_calls > 0
|
|
186
|
+
# µs to seconds
|
|
187
|
+
elapsed = elapsed / 1000000.0
|
|
188
|
+
# Allocate the GC time to a scope as if the GC just ended
|
|
189
|
+
# right now.
|
|
190
|
+
time = Time.now.to_f
|
|
191
|
+
gc_scope = push_scope("GC/cumulative", time - elapsed)
|
|
192
|
+
# GC stats are collected into a blamed metric which allows
|
|
193
|
+
# us to show the stats controller by controller
|
|
194
|
+
gc_stats = NewRelic::Agent.get_stats(gc_scope.name, true)
|
|
195
|
+
gc_stats.record_multiple_data_points(elapsed, num_calls)
|
|
196
|
+
pop_scope(gc_scope, elapsed, time)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Returns the current scope stack, memoized to a thread local variable
|
|
201
|
+
def scope_stack
|
|
202
|
+
Thread::current[:newrelic_scope_stack] ||= []
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'new_relic/agent/stats_engine/metric_stats'
|
|
2
|
+
require 'new_relic/agent/stats_engine/samplers'
|
|
3
|
+
require 'new_relic/agent/stats_engine/transactions'
|
|
4
|
+
|
|
5
|
+
module NewRelic
|
|
6
|
+
module Agent
|
|
7
|
+
# This class handles all the statistics gathering for the agent
|
|
8
|
+
class StatsEngine
|
|
9
|
+
include MetricStats
|
|
10
|
+
include Samplers
|
|
11
|
+
include Transactions
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
# Makes the unit tests happy
|
|
15
|
+
Thread::current[:newrelic_scope_stack] = nil
|
|
16
|
+
start_sampler_thread
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def log
|
|
20
|
+
NewRelic::Control.instance.log
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'new_relic/collection_helper'
|
|
2
|
+
require 'new_relic/transaction_sample'
|
|
3
|
+
require 'new_relic/control'
|
|
4
|
+
require 'new_relic/agent/instrumentation/metric_frame'
|
|
5
|
+
module NewRelic
|
|
6
|
+
module Agent
|
|
7
|
+
# a builder is created with every sampled transaction, to dynamically
|
|
8
|
+
# generate the sampled data. It is a thread-local object, and is not
|
|
9
|
+
# accessed by any other thread so no need for synchronization.
|
|
10
|
+
class TransactionSampleBuilder
|
|
11
|
+
attr_reader :current_segment, :sample
|
|
12
|
+
|
|
13
|
+
include NewRelic::CollectionHelper
|
|
14
|
+
|
|
15
|
+
def initialize(time=Time.now)
|
|
16
|
+
@sample = NewRelic::TransactionSample.new(time.to_f)
|
|
17
|
+
@sample_start = time.to_f
|
|
18
|
+
@current_segment = @sample.root_segment
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def sample_id
|
|
22
|
+
@sample.sample_id
|
|
23
|
+
end
|
|
24
|
+
def ignored?
|
|
25
|
+
@ignore || @sample.params[:path].nil?
|
|
26
|
+
end
|
|
27
|
+
def ignore_transaction
|
|
28
|
+
@ignore = true
|
|
29
|
+
end
|
|
30
|
+
def trace_entry(metric_name, time)
|
|
31
|
+
segment = @sample.create_segment(time.to_f - @sample_start, metric_name)
|
|
32
|
+
@current_segment.add_called_segment(segment)
|
|
33
|
+
@current_segment = segment
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def trace_exit(metric_name, time)
|
|
37
|
+
if metric_name != @current_segment.metric_name
|
|
38
|
+
fail "unbalanced entry/exit: #{metric_name} != #{@current_segment.metric_name}"
|
|
39
|
+
end
|
|
40
|
+
@current_segment.end_trace(time.to_f - @sample_start)
|
|
41
|
+
@current_segment = @current_segment.parent_segment
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def finish_trace(time)
|
|
45
|
+
# This should never get called twice, but in a rare case that we can't reproduce in house it does.
|
|
46
|
+
# log forensics and return gracefully
|
|
47
|
+
if @sample.frozen?
|
|
48
|
+
log = NewRelic::Control.instance.log
|
|
49
|
+
log.error "Unexpected double-freeze of Transaction Trace Object: \n#{@sample.to_s}"
|
|
50
|
+
return
|
|
51
|
+
end
|
|
52
|
+
@sample.root_segment.end_trace(time.to_f - @sample_start)
|
|
53
|
+
@sample.params[:custom_params] = normalize_params(NewRelic::Agent::Instrumentation::MetricFrame.custom_parameters)
|
|
54
|
+
@sample.freeze
|
|
55
|
+
@current_segment = nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def scope_depth
|
|
59
|
+
depth = -1 # have to account for the root
|
|
60
|
+
current = @current_segment
|
|
61
|
+
|
|
62
|
+
while(current)
|
|
63
|
+
depth += 1
|
|
64
|
+
current = current.parent_segment
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
depth
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def freeze
|
|
71
|
+
@sample.freeze unless sample.frozen?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def set_profile(profile)
|
|
75
|
+
@sample.profile = profile
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def set_transaction_info(path, uri, params)
|
|
79
|
+
@sample.params[:path] = path
|
|
80
|
+
|
|
81
|
+
if NewRelic::Control.instance.capture_params
|
|
82
|
+
params = normalize_params params
|
|
83
|
+
|
|
84
|
+
@sample.params[:request_params].merge!(params)
|
|
85
|
+
@sample.params[:request_params].delete :controller
|
|
86
|
+
@sample.params[:request_params].delete :action
|
|
87
|
+
end
|
|
88
|
+
@sample.params[:uri] ||= uri || params[:uri]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def set_transaction_cpu_time(cpu_time)
|
|
92
|
+
@sample.params[:cpu_time] = cpu_time
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def sample
|
|
96
|
+
@sample
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|