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,414 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
require 'new_relic/version'
|
|
3
|
+
|
|
4
|
+
module NewRelic
|
|
5
|
+
# An instance of LocalEnvironment is responsible for determining
|
|
6
|
+
# three things:
|
|
7
|
+
#
|
|
8
|
+
# * Framework - :rails, :rails3, :merb, :ruby, :external, :test
|
|
9
|
+
# * Dispatcher - A supported dispatcher, or nil (:mongrel, :thin, :passenger, :webrick, etc)
|
|
10
|
+
# * Dispatcher Instance ID, which distinguishes agents on a single host from each other
|
|
11
|
+
#
|
|
12
|
+
# If the environment can't be determined, it will be set to
|
|
13
|
+
# nil and dispatcher_instance_id will have nil.
|
|
14
|
+
#
|
|
15
|
+
# NewRelic::LocalEnvironment should be accessed through NewRelic::Control#env (via the NewRelic::Control singleton).
|
|
16
|
+
class LocalEnvironment
|
|
17
|
+
|
|
18
|
+
# mongrel, thin, webrick, or possibly nil
|
|
19
|
+
attr_accessor :dispatcher
|
|
20
|
+
# used to distinguish instances of a dispatcher from each other, may be nil
|
|
21
|
+
attr_writer :dispatcher_instance_id
|
|
22
|
+
# rails, rails3, merb, external, ruby, test, etc
|
|
23
|
+
attr_accessor :framework
|
|
24
|
+
# The number of cpus, if detected, or nil - many platforms do not
|
|
25
|
+
# support this :(
|
|
26
|
+
attr_reader :processors
|
|
27
|
+
alias environment dispatcher
|
|
28
|
+
|
|
29
|
+
def initialize
|
|
30
|
+
# Extend self with any any submodules of LocalEnvironment. These can override
|
|
31
|
+
# the discover methods to discover new framworks and dispatchers.
|
|
32
|
+
NewRelic::LocalEnvironment.constants.each do | const |
|
|
33
|
+
mod = NewRelic::LocalEnvironment.const_get const
|
|
34
|
+
self.extend mod if mod.instance_of? Module
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
discover_framework
|
|
38
|
+
discover_dispatcher
|
|
39
|
+
@dispatcher = nil if @dispatcher == :none
|
|
40
|
+
@gems = Set.new
|
|
41
|
+
@plugins = Set.new
|
|
42
|
+
@config = Hash.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Add the given key/value pair to the app environment
|
|
46
|
+
# settings. Must pass either a value or a block. Block
|
|
47
|
+
# is called to get the value and any raised errors are
|
|
48
|
+
# silently ignored.
|
|
49
|
+
def append_environment_value(name, value = nil)
|
|
50
|
+
value = yield if block_given?
|
|
51
|
+
@config[name] = value if value
|
|
52
|
+
rescue Exception
|
|
53
|
+
# puts "#{e}\n #{e.backtrace.join("\n ")}"
|
|
54
|
+
raise if @framework == :test
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# yields to the block and appends the returned value to the list
|
|
58
|
+
# of gems - this catches errors that might be raised in the block
|
|
59
|
+
def append_gem_list
|
|
60
|
+
@gems += yield
|
|
61
|
+
rescue Exception => e
|
|
62
|
+
# puts "#{e}\n #{e.backtrace.join("\n ")}"
|
|
63
|
+
raise if @framework == :test
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# yields to the block and appends the returned value to the list
|
|
67
|
+
# of plugins - this catches errors that might be raised in the block
|
|
68
|
+
def append_plugin_list
|
|
69
|
+
@plugins += yield
|
|
70
|
+
rescue Exception
|
|
71
|
+
# puts "#{e}\n #{e.backtrace.join("\n ")}"
|
|
72
|
+
raise if @framework == :test
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# An instance id pulled from either @dispatcher_instance_id or by
|
|
76
|
+
# splitting out the first part of the running file
|
|
77
|
+
def dispatcher_instance_id
|
|
78
|
+
if @dispatcher_instance_id.nil?
|
|
79
|
+
if @dispatcher.nil?
|
|
80
|
+
@dispatcher_instance_id = File.basename($0).split(".").first
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
@dispatcher_instance_id
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Interrogates some common ruby constants for useful information
|
|
87
|
+
# about what kind of ruby environment the agent is running in
|
|
88
|
+
def gather_ruby_info
|
|
89
|
+
append_environment_value('Ruby version'){ RUBY_VERSION }
|
|
90
|
+
append_environment_value('Ruby description'){ RUBY_DESCRIPTION } if defined? ::RUBY_DESCRIPTION
|
|
91
|
+
append_environment_value('Ruby platform') { RUBY_PLATFORM }
|
|
92
|
+
append_environment_value('Ruby patchlevel') { RUBY_PATCHLEVEL }
|
|
93
|
+
# room here for other ruby implementations, when.
|
|
94
|
+
if defined? ::JRUBY_VERSION
|
|
95
|
+
gather_jruby_info
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# like gather_ruby_info but for the special case of JRuby
|
|
100
|
+
def gather_jruby_info
|
|
101
|
+
append_environment_value('JRuby version') { JRUBY_VERSION }
|
|
102
|
+
append_environment_value('Java VM version') { ENV_JAVA['java.vm.version']}
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# See what the number of cpus is, works only on some linux variants
|
|
106
|
+
def gather_cpu_info
|
|
107
|
+
return unless File.readable? '/proc/cpuinfo'
|
|
108
|
+
@processors = append_environment_value('Processors') do
|
|
109
|
+
processors = File.readlines('/proc/cpuinfo').select { |line| line =~ /^processor\s*:/ }.size
|
|
110
|
+
raise "Cannot determine the number of processors in /proc/cpuinfo" unless processors > 0
|
|
111
|
+
processors
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Grabs the architecture string from either `uname -p` or the env
|
|
116
|
+
# variable PROCESSOR_ARCHITECTURE
|
|
117
|
+
def gather_architecture_info
|
|
118
|
+
append_environment_value('Arch') { `uname -p` } ||
|
|
119
|
+
append_environment_value('Arch') { ENV['PROCESSOR_ARCHITECTURE'] }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# gathers OS info from either `uname -v`, `uname -s`, or the OS
|
|
123
|
+
# env variable
|
|
124
|
+
def gather_os_info
|
|
125
|
+
append_environment_value('OS version') { `uname -v` }
|
|
126
|
+
append_environment_value('OS') { `uname -s` } ||
|
|
127
|
+
append_environment_value('OS') { ENV['OS'] }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Gathers the architecture and cpu info
|
|
131
|
+
def gather_system_info
|
|
132
|
+
gather_architecture_info
|
|
133
|
+
gather_cpu_info
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Looks for a capistrano file indicating the current revision
|
|
137
|
+
def gather_revision_info
|
|
138
|
+
rev_file = File.join(NewRelic::Control.instance.root, "REVISION")
|
|
139
|
+
if File.readable?(rev_file) && File.size(rev_file) < 64
|
|
140
|
+
append_environment_value('Revision') do
|
|
141
|
+
File.open(rev_file) { | file | file.readline.strip }
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# The name of the AR database adapter for the current environment and
|
|
147
|
+
# the current schema version
|
|
148
|
+
def gather_ar_adapter_info
|
|
149
|
+
|
|
150
|
+
append_environment_value 'Database adapter' do
|
|
151
|
+
if defined?(ActiveRecord) && defined?(ActiveRecord::Base) &&
|
|
152
|
+
ActiveRecord::Base.respond_to?(:configurations)
|
|
153
|
+
config = ActiveRecord::Base.configurations[NewRelic::Control.instance.env]
|
|
154
|
+
if config
|
|
155
|
+
config['adapter']
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
append_environment_value 'Database schema version' do
|
|
160
|
+
ActiveRecord::Migrator.current_version
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Datamapper version
|
|
165
|
+
def gather_dm_adapter_info
|
|
166
|
+
append_environment_value 'DataMapper version' do
|
|
167
|
+
require 'dm-core/version'
|
|
168
|
+
DataMapper::VERSION
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# sensing for which adapter is defined, then appends the relevant
|
|
173
|
+
# config information
|
|
174
|
+
def gather_db_info
|
|
175
|
+
# room here for more database adapters, when.
|
|
176
|
+
if defined? ::ActiveRecord
|
|
177
|
+
gather_ar_adapter_info
|
|
178
|
+
end
|
|
179
|
+
if defined? ::DataMapper
|
|
180
|
+
gather_dm_adapter_info
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Collect base statistics about the environment and record them for
|
|
185
|
+
# comparison and change detection.
|
|
186
|
+
def gather_environment_info
|
|
187
|
+
append_environment_value 'Framework', @framework.to_s
|
|
188
|
+
append_environment_value 'Dispatcher', @dispatcher.to_s if @dispatcher
|
|
189
|
+
append_environment_value 'Dispatcher instance id', @dispatcher_instance_id if @dispatcher_instance_id
|
|
190
|
+
append_environment_value('Environment') { NewRelic::Control.instance.env }
|
|
191
|
+
|
|
192
|
+
# miscellaneous other helpful debugging information
|
|
193
|
+
gather_ruby_info
|
|
194
|
+
gather_system_info
|
|
195
|
+
gather_revision_info
|
|
196
|
+
gather_db_info
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Take a snapshot of the environment information for this application
|
|
200
|
+
# Returns an associative array
|
|
201
|
+
def snapshot
|
|
202
|
+
i = @config.to_a
|
|
203
|
+
i << [ 'Plugin List', @plugins.to_a] if not @plugins.empty?
|
|
204
|
+
i << [ 'Gems', @gems.to_a] if not @gems.empty?
|
|
205
|
+
i
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# it's a working jruby if it has the runtime method, and object
|
|
209
|
+
# space is enabled
|
|
210
|
+
def working_jruby?
|
|
211
|
+
!(defined?(::JRuby) && JRuby.respond_to?(:runtime) && !JRuby.runtime.is_object_space_enabled)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Runs through all the objects in ObjectSpace to find the first one that
|
|
215
|
+
# match the provided class
|
|
216
|
+
def find_class_in_object_space(klass)
|
|
217
|
+
ObjectSpace.each_object(klass) do |x|
|
|
218
|
+
return x
|
|
219
|
+
end
|
|
220
|
+
return nil
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Sets the @mongrel instance variable if we can find a Mongrel::HttpServer
|
|
224
|
+
def mongrel
|
|
225
|
+
return @mongrel if @mongrel
|
|
226
|
+
if defined?(::Mongrel) && defined?(::Mongrel::HttpServer) && working_jruby?
|
|
227
|
+
@mongrel = find_class_in_object_space(::Mongrel::HttpServer)
|
|
228
|
+
end
|
|
229
|
+
@mongrel
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private
|
|
233
|
+
|
|
234
|
+
# Although you can override the framework with NEWRELIC_DISPATCHER this
|
|
235
|
+
# is not advisable since it implies certain api's being available.
|
|
236
|
+
def discover_dispatcher
|
|
237
|
+
@dispatcher ||= ENV['NEWRELIC_DISPATCHER'] && ENV['NEWRELIC_DISPATCHER'].to_sym
|
|
238
|
+
@dispatcher ||= ENV['NEW_RELIC_DISPATCHER'] && ENV['NEW_RELIC_DISPATCHER'].to_sym
|
|
239
|
+
dispatchers = %w[passenger torquebox glassfish thin mongrel litespeed webrick fastcgi unicorn sinatra]
|
|
240
|
+
while dispatchers.any? && @dispatcher.nil?
|
|
241
|
+
send 'check_for_'+(dispatchers.shift)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def discover_framework
|
|
246
|
+
# Although you can override the framework with NEWRELIC_FRAMEWORK this
|
|
247
|
+
# is not advisable since it implies certain api's being available.
|
|
248
|
+
#
|
|
249
|
+
# Note that the odd defined? sequence is necessary to work around a bug in an older version
|
|
250
|
+
# of JRuby.
|
|
251
|
+
@framework ||= case
|
|
252
|
+
when ENV['NEWRELIC_FRAMEWORK'] then ENV['NEWRELIC_FRAMEWORK'].to_sym
|
|
253
|
+
when ENV['NEW_RELIC_FRAMEWORK'] then ENV['NEW_RELIC_FRAMEWORK'].to_sym
|
|
254
|
+
when defined?(::NewRelic::TEST) then :test
|
|
255
|
+
when defined?(::Merb) && defined?(::Merb::Plugins) then :merb
|
|
256
|
+
when defined?(::Rails) then check_rails_version
|
|
257
|
+
when defined?(::Sinatra) && defined?(::Sinatra::Base) then :sinatra
|
|
258
|
+
when defined?(::NewRelic::IA) then :external
|
|
259
|
+
else :ruby
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def check_rails_version
|
|
264
|
+
if Rails::VERSION::MAJOR < 3
|
|
265
|
+
:rails
|
|
266
|
+
else
|
|
267
|
+
:rails3
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def check_for_torquebox
|
|
272
|
+
return unless defined?(::JRuby) &&
|
|
273
|
+
( org.torquebox::TorqueBox rescue nil)
|
|
274
|
+
@dispatcher = :torquebox
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def check_for_glassfish
|
|
278
|
+
return unless defined?(::JRuby) &&
|
|
279
|
+
(((com.sun.grizzly.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
|
|
280
|
+
defined?(com::sun::grizzly::jruby::rack::DefaultRackApplicationFactory)) ||
|
|
281
|
+
(jruby_rack? && defined?(::GlassFish::Server)))
|
|
282
|
+
@dispatcher = :glassfish
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def check_for_trinidad
|
|
286
|
+
return unless defined?(::JRuby) && jruby_rack? && defined?(::Trinidad::Server)
|
|
287
|
+
@dispatcher = :trinidad
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def jruby_rack?
|
|
291
|
+
((org.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
|
|
292
|
+
defined?(org::jruby::rack::DefaultRackApplicationFactory))
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def check_for_webrick
|
|
296
|
+
return unless defined?(::WEBrick) && defined?(::WEBrick::VERSION)
|
|
297
|
+
@dispatcher = :webrick
|
|
298
|
+
if defined?(::OPTIONS) && OPTIONS.respond_to?(:fetch)
|
|
299
|
+
# OPTIONS is set by script/server
|
|
300
|
+
@dispatcher_instance_id = OPTIONS.fetch(:port)
|
|
301
|
+
end
|
|
302
|
+
@dispatcher_instance_id = default_port unless @dispatcher_instance_id
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def check_for_fastcgi
|
|
306
|
+
return unless defined?(::FCGI)
|
|
307
|
+
@dispatcher = :fastcgi
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# this case covers starting by mongrel_rails
|
|
311
|
+
def check_for_mongrel
|
|
312
|
+
return unless defined?(::Mongrel) && defined?(::Mongrel::HttpServer)
|
|
313
|
+
@dispatcher = :mongrel
|
|
314
|
+
|
|
315
|
+
# Get the port from the server if it's started
|
|
316
|
+
|
|
317
|
+
if mongrel && mongrel.respond_to?(:port)
|
|
318
|
+
@dispatcher_instance_id = mongrel.port.to_s
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Get the port from the configurator if one was created
|
|
322
|
+
if @dispatcher_instance_id.nil? && defined?(::Mongrel::Configurator)
|
|
323
|
+
ObjectSpace.each_object(Mongrel::Configurator) do |mongrel|
|
|
324
|
+
@dispatcher_instance_id = mongrel.defaults[:port] && mongrel.defaults[:port].to_s
|
|
325
|
+
end unless defined?(::JRuby) && !JRuby.runtime.is_object_space_enabled
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Still can't find the port. Let's look at ARGV to fall back
|
|
329
|
+
@dispatcher_instance_id = default_port if @dispatcher_instance_id.nil?
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def check_for_unicorn
|
|
333
|
+
if (defined?(::Unicorn) && defined?(::Unicorn::HttpServer)) && working_jruby?
|
|
334
|
+
v = find_class_in_object_space(::Unicorn::HttpServer)
|
|
335
|
+
@dispatcher = :unicorn if v
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def check_for_sinatra
|
|
340
|
+
return unless defined?(::Sinatra) && defined?(::Sinatra::Base)
|
|
341
|
+
|
|
342
|
+
begin
|
|
343
|
+
version = ::Sinatra::VERSION
|
|
344
|
+
rescue
|
|
345
|
+
$stderr.puts("Error determining Sinatra version")
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
if ::NewRelic::VersionNumber.new('0.9.2') > version
|
|
349
|
+
$stderr.puts("Your Sinatra version is #{version}, we highly recommend upgrading to >=0.9.2")
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
@dispatcher = :sinatra
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def check_for_thin
|
|
356
|
+
if defined?(::Thin) && defined?(::Thin::Server)
|
|
357
|
+
# This case covers the thin web dispatcher
|
|
358
|
+
# Same issue as above- we assume only one instance per process
|
|
359
|
+
ObjectSpace.each_object(Thin::Server) do |thin_dispatcher|
|
|
360
|
+
@dispatcher = :thin
|
|
361
|
+
backend = thin_dispatcher.backend
|
|
362
|
+
# We need a way to uniquely identify and distinguish agents. The port
|
|
363
|
+
# works for this. When using sockets, use the socket file name.
|
|
364
|
+
if backend.respond_to? :port
|
|
365
|
+
@dispatcher_instance_id = backend.port
|
|
366
|
+
elsif backend.respond_to? :socket
|
|
367
|
+
@dispatcher_instance_id = backend.socket
|
|
368
|
+
else
|
|
369
|
+
raise "Unknown thin backend: #{backend}"
|
|
370
|
+
end
|
|
371
|
+
end # each thin instance
|
|
372
|
+
end
|
|
373
|
+
if defined?(::Thin) && defined?(::Thin::VERSION) && !@dispatcher
|
|
374
|
+
@dispatcher = :thin
|
|
375
|
+
@dispatcher_instance_id = default_port
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def check_for_litespeed
|
|
380
|
+
if caller.pop =~ /fcgi-bin\/RailsRunner\.rb/
|
|
381
|
+
@dispatcher = :litespeed
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def check_for_passenger
|
|
386
|
+
if (defined?(::Passenger) && defined?(::Passenger::AbstractServer)) || defined?(::IN_PHUSION_PASSENGER)
|
|
387
|
+
@dispatcher = :passenger
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def default_port
|
|
393
|
+
require 'optparse'
|
|
394
|
+
# If nothing else is found, use the 3000 default
|
|
395
|
+
default_port = 3000
|
|
396
|
+
OptionParser.new do |opts|
|
|
397
|
+
opts.on("-p", "--port=port", String) { | p | default_port = p }
|
|
398
|
+
opts.parse(ARGV.clone) rescue nil
|
|
399
|
+
end
|
|
400
|
+
default_port
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
public
|
|
404
|
+
# outputs a human-readable description
|
|
405
|
+
def to_s
|
|
406
|
+
s = "LocalEnvironment["
|
|
407
|
+
s << @framework.to_s
|
|
408
|
+
s << ";dispatcher=#{@dispatcher}" if @dispatcher
|
|
409
|
+
s << ";instance=#{@dispatcher_instance_id}" if @dispatcher_instance_id
|
|
410
|
+
s << "]"
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
end
|
|
414
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module NewRelic
|
|
2
|
+
class MetricData
|
|
3
|
+
# nil, or a NewRelic::MetricSpec object if we have no cached ID
|
|
4
|
+
attr_accessor :metric_spec
|
|
5
|
+
# nil or a cached integer ID for the metric from the collector.
|
|
6
|
+
attr_accessor :metric_id
|
|
7
|
+
# the actual statistics object
|
|
8
|
+
attr_accessor :stats
|
|
9
|
+
|
|
10
|
+
def initialize(metric_spec, stats, metric_id)
|
|
11
|
+
@metric_spec = metric_spec
|
|
12
|
+
self.stats = stats
|
|
13
|
+
self.metric_id = metric_id
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def eql?(o)
|
|
17
|
+
(metric_spec.eql? o.metric_spec) && (stats.eql? o.stats)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def original_spec
|
|
21
|
+
@original_spec || @metric_spec
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# assigns a new metric spec, and retains the old metric spec as
|
|
25
|
+
# @original_spec if it exists currently
|
|
26
|
+
def metric_spec= new_spec
|
|
27
|
+
@original_spec = @metric_spec if @metric_spec
|
|
28
|
+
@metric_spec = new_spec
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def hash
|
|
32
|
+
metric_spec.hash ^ stats.hash
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Serialize with all attributes, but if the metric id is not nil, then don't send the metric spec
|
|
36
|
+
def to_json(*a)
|
|
37
|
+
%Q[{"metric_spec":#{metric_id ? 'null' : metric_spec.to_json},"stats":{"total_exclusive_time":#{stats.total_exclusive_time},"min_call_time":#{stats.min_call_time},"call_count":#{stats.call_count},"sum_of_squares":#{stats.sum_of_squares},"total_call_time":#{stats.total_call_time},"max_call_time":#{stats.max_call_time}},"metric_id":#{metric_id ? metric_id : 'null'}}]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_s
|
|
41
|
+
if metric_spec
|
|
42
|
+
"#{metric_spec.name}(#{metric_spec.scope}): #{stats}"
|
|
43
|
+
else
|
|
44
|
+
"#{metric_id}: #{stats}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
def inspect
|
|
48
|
+
"#<MetricData metric_spec:#{metric_spec.inspect}, stats:#{stats.inspect}, metric_id:#{metric_id.inspect}>"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# this struct uniquely defines a metric, optionally inside
|
|
2
|
+
# the call scope of another metric
|
|
3
|
+
class NewRelic::MetricSpec
|
|
4
|
+
attr_accessor :name
|
|
5
|
+
attr_accessor :scope
|
|
6
|
+
|
|
7
|
+
# the maximum length of a metric name or metric scope
|
|
8
|
+
MAX_LENGTH = 255
|
|
9
|
+
# Need a "zero-arg" constructor so it can be instantiated from java (using
|
|
10
|
+
# jruby) for sending responses to ruby agents from the java collector.
|
|
11
|
+
#
|
|
12
|
+
def initialize(metric_name = '', metric_scope = '')
|
|
13
|
+
self.name = (metric_name || '') && metric_name[0...MAX_LENGTH]
|
|
14
|
+
self.scope = metric_scope && metric_scope[0...MAX_LENGTH]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# truncates the name and scope to the MAX_LENGTH
|
|
18
|
+
def truncate!
|
|
19
|
+
self.name = name[0...MAX_LENGTH] if name && name.size > MAX_LENGTH
|
|
20
|
+
self.scope = scope[0...MAX_LENGTH] if scope && scope.size > MAX_LENGTH
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def ==(o)
|
|
24
|
+
self.eql?(o)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def eql? o
|
|
28
|
+
self.class == o.class &&
|
|
29
|
+
name.eql?(o.name) &&
|
|
30
|
+
# coerce scope to a string and compare
|
|
31
|
+
scope.to_s == o.scope.to_s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def hash
|
|
35
|
+
h = name.hash
|
|
36
|
+
h ^= scope.hash unless scope.nil?
|
|
37
|
+
h
|
|
38
|
+
end
|
|
39
|
+
# return a new metric spec if the given regex
|
|
40
|
+
# matches the name or scope.
|
|
41
|
+
def sub(pattern, replacement, apply_to_scope = true)
|
|
42
|
+
NewRelic::Control.instance.log.warn("The sub method on metric specs is deprecated") rescue nil
|
|
43
|
+
return nil if name !~ pattern &&
|
|
44
|
+
(!apply_to_scope || scope.nil? || scope !~ pattern)
|
|
45
|
+
new_name = name.sub(pattern, replacement)[0...MAX_LENGTH]
|
|
46
|
+
|
|
47
|
+
if apply_to_scope
|
|
48
|
+
new_scope = (scope && scope.sub(pattern, replacement)[0...MAX_LENGTH])
|
|
49
|
+
else
|
|
50
|
+
new_scope = scope
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
self.class.new new_name, new_scope
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def to_s
|
|
57
|
+
return name if scope.empty?
|
|
58
|
+
"#{name}:#{scope}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def inspect
|
|
62
|
+
"#<NewRelic::MetricSpec '#{name}':'#{scope}'>"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def to_json(*a)
|
|
66
|
+
{'name' => name,
|
|
67
|
+
'scope' => scope}.to_json(*a)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def <=>(o)
|
|
71
|
+
namecmp = self.name <=> o.name
|
|
72
|
+
return namecmp if namecmp != 0
|
|
73
|
+
return (self.scope || '') <=> (o.scope || '')
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# This class encapsulates an error that was noticed by New Relic in a managed app.
|
|
2
|
+
class NewRelic::NoticedError
|
|
3
|
+
extend NewRelic::CollectionHelper
|
|
4
|
+
attr_accessor :path, :timestamp, :params, :exception_class, :message
|
|
5
|
+
|
|
6
|
+
def initialize(path, data, exception, timestamp = Time.now)
|
|
7
|
+
self.path = path
|
|
8
|
+
self.params = NewRelic::NoticedError.normalize_params(data)
|
|
9
|
+
|
|
10
|
+
self.exception_class = exception.is_a?(Exception) ? exception.class.name : 'Error'
|
|
11
|
+
|
|
12
|
+
if exception.respond_to?('original_exception')
|
|
13
|
+
self.message = exception.original_exception.message.to_s
|
|
14
|
+
else
|
|
15
|
+
self.message = (exception || '<no message>').to_s
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# clamp long messages to 4k so that we don't send a lot of
|
|
19
|
+
# overhead across the wire
|
|
20
|
+
self.message = self.message[0..4095] if self.message.length > 4096
|
|
21
|
+
|
|
22
|
+
self.timestamp = timestamp
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'rack'
|
|
2
|
+
|
|
3
|
+
module NewRelic::Rack
|
|
4
|
+
class BrowserMonitoring
|
|
5
|
+
|
|
6
|
+
def initialize(app, options = {})
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# method required by Rack interface
|
|
11
|
+
def call(env)
|
|
12
|
+
|
|
13
|
+
# clear out the thread locals we use in case this is a static request
|
|
14
|
+
Thread.current[:newrelic_most_recent_transaction] = nil
|
|
15
|
+
Thread.current[:newrelic_start_time] = Time.now
|
|
16
|
+
Thread.current[:newrelic_queue_time] = 0
|
|
17
|
+
|
|
18
|
+
result = @app.call(env) # [status, headers, response]
|
|
19
|
+
|
|
20
|
+
if (NewRelic::Agent.browser_timing_header != "") && should_instrument?(result[0], result[1])
|
|
21
|
+
response_string = autoinstrument_source(result[2], result[1])
|
|
22
|
+
|
|
23
|
+
if (response_string)
|
|
24
|
+
Rack::Response.new(response_string, result[0], result[1]).finish
|
|
25
|
+
else
|
|
26
|
+
result
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def should_instrument?(status, headers)
|
|
34
|
+
status == 200 && headers["Content-Type"] && headers["Content-Type"].include?("text/html")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def autoinstrument_source(response, headers)
|
|
38
|
+
source = nil
|
|
39
|
+
response.each {|fragment| (source) ? (source << fragment) : (source = fragment)}
|
|
40
|
+
return nil unless source
|
|
41
|
+
|
|
42
|
+
body_start = source.index("<body")
|
|
43
|
+
body_close = source.rindex("</body>")
|
|
44
|
+
|
|
45
|
+
if body_start && body_close
|
|
46
|
+
footer = NewRelic::Agent.browser_timing_footer
|
|
47
|
+
header = NewRelic::Agent.browser_timing_header
|
|
48
|
+
|
|
49
|
+
if source.include?('X-UA-Compatible')
|
|
50
|
+
# put at end of header if UA-Compatible meta tag found
|
|
51
|
+
head_pos = source.index("</head>")
|
|
52
|
+
elsif head_open = source.index("<head")
|
|
53
|
+
# put at the beginning of the header
|
|
54
|
+
head_pos = source.index(">", head_open) + 1
|
|
55
|
+
else
|
|
56
|
+
# put the header right above body start
|
|
57
|
+
head_pos = body_start
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
source = source[0..(head_pos-1)] + header + source[head_pos..(body_close-1)] + footer + source[body_close..-1]
|
|
61
|
+
|
|
62
|
+
headers['Content-Length'] = source.length.to_s if headers['Content-Length']
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
source
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|