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,89 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..', 'test_helper'))
|
|
2
|
+
class NewRelic::VersionNumberTest < Test::Unit::TestCase
|
|
3
|
+
|
|
4
|
+
def test_comparison__first
|
|
5
|
+
versions = %w[1.0.0 0.1.0 0.0.1 10.0.1 1.10.0].map {|s| NewRelic::VersionNumber.new s }
|
|
6
|
+
assert_equal %w[0.0.1 0.1.0 1.0.0 1.10.0 10.0.1], versions.sort.map(&:to_s)
|
|
7
|
+
v0 = NewRelic::VersionNumber.new '1.2.3'
|
|
8
|
+
v1 = NewRelic::VersionNumber.new '1.2.2'
|
|
9
|
+
v3 = NewRelic::VersionNumber.new '1.2.2'
|
|
10
|
+
assert v0 > v1
|
|
11
|
+
assert v1 == v1
|
|
12
|
+
assert v1 == v3
|
|
13
|
+
end
|
|
14
|
+
def test_comparison__second
|
|
15
|
+
v0 = NewRelic::VersionNumber.new '1.2.0'
|
|
16
|
+
v1 = NewRelic::VersionNumber.new '2.2.2'
|
|
17
|
+
v3 = NewRelic::VersionNumber.new '1.1.2'
|
|
18
|
+
assert v0 < v1
|
|
19
|
+
assert v1 > v3
|
|
20
|
+
assert v3 < v0
|
|
21
|
+
end
|
|
22
|
+
def test_bug
|
|
23
|
+
v0 = NewRelic::VersionNumber.new '2.8.999'
|
|
24
|
+
v1 = NewRelic::VersionNumber.new '2.9.10'
|
|
25
|
+
assert v1 > v0
|
|
26
|
+
assert v0 <= v1
|
|
27
|
+
end
|
|
28
|
+
def test_long_version
|
|
29
|
+
v0 = NewRelic::VersionNumber.new '1.2.3.4'
|
|
30
|
+
v1 = NewRelic::VersionNumber.new '1.2.3.3'
|
|
31
|
+
v3 = NewRelic::VersionNumber.new '1.3'
|
|
32
|
+
assert v0 > v1
|
|
33
|
+
assert v0 < '1.2.3.5'
|
|
34
|
+
assert ! (v0 < '1.2.3.4')
|
|
35
|
+
assert v3 > v0
|
|
36
|
+
end
|
|
37
|
+
def test_sort
|
|
38
|
+
values = %w[1.1.1
|
|
39
|
+
1.1.99
|
|
40
|
+
1.1.999
|
|
41
|
+
2.0.6
|
|
42
|
+
2.6.5
|
|
43
|
+
2.7
|
|
44
|
+
2.7.1
|
|
45
|
+
2.7.2
|
|
46
|
+
2.7.2.0
|
|
47
|
+
3
|
|
48
|
+
999]
|
|
49
|
+
assert_equal values, values.map{|v| NewRelic::VersionNumber.new v}.sort.map(&:to_s)
|
|
50
|
+
end
|
|
51
|
+
def test_prerelease
|
|
52
|
+
v0 = NewRelic::VersionNumber.new '1.2.0.beta'
|
|
53
|
+
assert_equal [1,2,0,'beta'], v0.parts
|
|
54
|
+
assert v0 > '1.1.9.0'
|
|
55
|
+
assert v0 > '1.1.9.alpha'
|
|
56
|
+
assert v0 > '1.2.0.alpha'
|
|
57
|
+
assert v0 == '1.2.0.beta'
|
|
58
|
+
assert v0 < '1.2.1'
|
|
59
|
+
assert v0 < '1.2.0'
|
|
60
|
+
assert v0 < '1.2.0.c'
|
|
61
|
+
assert v0 < '1.2.0.0'
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
def test_compare_string
|
|
65
|
+
v0 = NewRelic::VersionNumber.new '1.2.0'
|
|
66
|
+
v1 = NewRelic::VersionNumber.new '2.2.2'
|
|
67
|
+
v3 = NewRelic::VersionNumber.new '1.1.2'
|
|
68
|
+
assert v0 < '2.2.2'
|
|
69
|
+
assert v1 > '1.1.2'
|
|
70
|
+
assert v3 < '1.2.0'
|
|
71
|
+
assert v0 == '1.2.0'
|
|
72
|
+
end
|
|
73
|
+
def test_4_numbers
|
|
74
|
+
v0 = NewRelic::VersionNumber.new '1.2.0'
|
|
75
|
+
v1 = NewRelic::VersionNumber.new '1.2.0.1'
|
|
76
|
+
v2 = NewRelic::VersionNumber.new '1.2.1.0'
|
|
77
|
+
v3 = NewRelic::VersionNumber.new '1.2.1.1'
|
|
78
|
+
assert v0 < v1
|
|
79
|
+
assert v1 < v2
|
|
80
|
+
assert v2 < v3
|
|
81
|
+
assert v0 < v3
|
|
82
|
+
assert v0 < '1.2.0.1'
|
|
83
|
+
assert v0 > '1.1.0.1'
|
|
84
|
+
end
|
|
85
|
+
def test_string
|
|
86
|
+
assert_equal '1.2.0', NewRelic::VersionNumber.new('1.2.0').to_s
|
|
87
|
+
assert_equal '1.2', NewRelic::VersionNumber.new('1.2').to_s
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
module TestContexts
|
|
3
|
+
def with_running_agent
|
|
4
|
+
|
|
5
|
+
context 'with running agent' do # this is needed for the nested setups
|
|
6
|
+
|
|
7
|
+
setup do
|
|
8
|
+
@log_data = StringIO.new
|
|
9
|
+
@log = Logger.new(@log_data)
|
|
10
|
+
NewRelic::Agent.manual_start :log => @log
|
|
11
|
+
@agent = NewRelic::Agent.instance
|
|
12
|
+
@agent.transaction_sampler.send :clear_builder
|
|
13
|
+
@agent.transaction_sampler.reset!
|
|
14
|
+
@agent.stats_engine.clear_stats
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
yield
|
|
18
|
+
|
|
19
|
+
def teardown
|
|
20
|
+
super
|
|
21
|
+
NewRelic::Agent.shutdown
|
|
22
|
+
@log_data.reset
|
|
23
|
+
NewRelic::Control.instance['dispatcher']=nil
|
|
24
|
+
NewRelic::Control.instance['dispatcher_instance_id']=nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
module NewRelic; TEST = true; end unless defined? NewRelic::TEST
|
|
2
|
+
ENV['RAILS_ENV'] = 'test'
|
|
3
|
+
NEWRELIC_PLUGIN_DIR = File.expand_path(File.join(File.dirname(__FILE__),".."))
|
|
4
|
+
$LOAD_PATH << '.'
|
|
5
|
+
$LOAD_PATH << '../../..'
|
|
6
|
+
$LOAD_PATH << File.join(NEWRELIC_PLUGIN_DIR,"test")
|
|
7
|
+
$LOAD_PATH << File.join(NEWRELIC_PLUGIN_DIR,"ui/helpers")
|
|
8
|
+
$LOAD_PATH.uniq!
|
|
9
|
+
|
|
10
|
+
require 'rubygems'
|
|
11
|
+
# We can speed things up in tests that don't need to load rails.
|
|
12
|
+
# You can also run the tests in a mode without rails. Many tests
|
|
13
|
+
# will be skipped.
|
|
14
|
+
|
|
15
|
+
begin
|
|
16
|
+
require 'config/environment'
|
|
17
|
+
begin
|
|
18
|
+
require 'test_help'
|
|
19
|
+
rescue LoadError
|
|
20
|
+
# ignore load problems on test help - it doesn't exist in rails 3
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
rescue LoadError
|
|
24
|
+
# To run the tests against a standalone agent build, you need to
|
|
25
|
+
# add a rails app to the load path. It can be 2.* to 3.*. It should
|
|
26
|
+
# referenc newrelic_rpm in the Gemfile with a :path option pointing
|
|
27
|
+
# to this work directory.
|
|
28
|
+
guess = File.expand_path("../../../rpm", __FILE__)
|
|
29
|
+
if $LOAD_PATH.include? guess
|
|
30
|
+
puts "Unable to load Rails for New Relic tests. See note in test_helper.rb"
|
|
31
|
+
raise
|
|
32
|
+
else
|
|
33
|
+
$LOAD_PATH << guess
|
|
34
|
+
retry
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
require 'newrelic_rpm'
|
|
38
|
+
|
|
39
|
+
require 'test/unit'
|
|
40
|
+
require 'shoulda'
|
|
41
|
+
require 'test_contexts'
|
|
42
|
+
require 'mocha'
|
|
43
|
+
require 'mocha/integration/test_unit'
|
|
44
|
+
require 'mocha/integration/test_unit/assertion_counter'
|
|
45
|
+
|
|
46
|
+
class Test::Unit::TestCase
|
|
47
|
+
include Mocha::API
|
|
48
|
+
|
|
49
|
+
# we can delete this trick when we stop supporting rails2.0.x
|
|
50
|
+
if ENV['BRANCH'] != 'rails20'
|
|
51
|
+
# a hack because rails2.0.2 does not like double teardowns
|
|
52
|
+
def teardown
|
|
53
|
+
mocha_teardown
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def assert_between(floor, ceiling, value, message="expected #{floor} <= #{value} <= #{ceiling}")
|
|
59
|
+
assert((floor <= value && value <= ceiling), message)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def check_metric_time(metric, value, delta)
|
|
63
|
+
time = NewRelic::Agent.get_stats(metric).total_call_time
|
|
64
|
+
assert_between((value - delta), (value + delta), time)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def check_metric_count(metric, value)
|
|
68
|
+
count = NewRelic::Agent.get_stats(metric).call_count
|
|
69
|
+
assert_equal(value, count, "should have the correct number of calls")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def check_unscoped_metric_count(metric, value)
|
|
73
|
+
count = NewRelic::Agent.get_stats_unscoped(metric).call_count
|
|
74
|
+
assert_equal(value, count, "should have the correct number of calls")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def generate_unscoped_metric_counts(*metrics)
|
|
78
|
+
metrics.inject({}) do |sum, metric|
|
|
79
|
+
sum[metric] = NewRelic::Agent.get_stats_no_scope(metric).call_count
|
|
80
|
+
sum
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def generate_metric_counts(*metrics)
|
|
85
|
+
metrics.inject({}) do |sum, metric|
|
|
86
|
+
sum[metric] = NewRelic::Agent.get_stats(metric).call_count
|
|
87
|
+
sum
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def assert_does_not_call_metrics(*metrics)
|
|
92
|
+
first_metrics = generate_metric_counts(*metrics)
|
|
93
|
+
yield
|
|
94
|
+
last_metrics = generate_metric_counts(*metrics)
|
|
95
|
+
assert_equal first_metrics, last_metrics, "should not have changed these metrics"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def assert_calls_metrics(*metrics)
|
|
99
|
+
first_metrics = generate_metric_counts(*metrics)
|
|
100
|
+
yield
|
|
101
|
+
last_metrics = generate_metric_counts(*metrics)
|
|
102
|
+
assert_not_equal first_metrics, last_metrics, "should have changed these metrics"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def assert_calls_unscoped_metrics(*metrics)
|
|
106
|
+
first_metrics = generate_unscoped_metric_counts(*metrics)
|
|
107
|
+
yield
|
|
108
|
+
last_metrics = generate_unscoped_metric_counts(*metrics)
|
|
109
|
+
assert_not_equal first_metrics, last_metrics, "should have changed these metrics"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def compare_metrics(expected, actual)
|
|
114
|
+
actual.delete_if {|a| a.include?('GC/cumulative') } # in case we are in REE
|
|
115
|
+
assert_equal(expected.to_a.sort, actual.to_a.sort, "extra: #{(actual - expected).to_a.inspect}; missing: #{(expected - actual).to_a.inspect}")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
module TransactionSampleTestHelper
|
|
119
|
+
def make_sql_transaction(*sql)
|
|
120
|
+
sampler = NewRelic::Agent::TransactionSampler.new
|
|
121
|
+
sampler.notice_first_scope_push Time.now.to_f
|
|
122
|
+
sampler.notice_transaction '/path', nil, :jim => "cool"
|
|
123
|
+
sampler.notice_push_scope "a"
|
|
124
|
+
|
|
125
|
+
sampler.notice_transaction '/path/2', nil, :jim => "cool"
|
|
126
|
+
|
|
127
|
+
sql.each {|sql_statement| sampler.notice_sql(sql_statement, {:adapter => "test"}, 0 ) }
|
|
128
|
+
|
|
129
|
+
sleep 0.02
|
|
130
|
+
yield if block_given?
|
|
131
|
+
sampler.notice_pop_scope "a"
|
|
132
|
+
sampler.notice_scope_empty
|
|
133
|
+
|
|
134
|
+
sampler.samples[0]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def run_sample_trace_on(sampler, path='/path')
|
|
138
|
+
sampler.notice_first_scope_push Time.now.to_f
|
|
139
|
+
sampler.notice_transaction path, path, {}
|
|
140
|
+
sampler.notice_push_scope "Controller/sandwiches/index"
|
|
141
|
+
sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'wheat'", nil, 0)
|
|
142
|
+
sampler.notice_push_scope "ab"
|
|
143
|
+
sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'white'", nil, 0)
|
|
144
|
+
yield sampler if block_given?
|
|
145
|
+
sampler.notice_pop_scope "ab"
|
|
146
|
+
sampler.notice_push_scope "lew"
|
|
147
|
+
sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'french'", nil, 0)
|
|
148
|
+
sampler.notice_pop_scope "lew"
|
|
149
|
+
sampler.notice_pop_scope "Controller/sandwiches/index"
|
|
150
|
+
sampler.notice_scope_empty
|
|
151
|
+
sampler.samples[0]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require File.expand_path('../google_pie_chart', __FILE__)
|
|
3
|
+
require 'new_relic/collection_helper'
|
|
4
|
+
require 'new_relic/metric_parser/metric_parser'
|
|
5
|
+
module NewRelic::DeveloperModeHelper
|
|
6
|
+
include NewRelic::CollectionHelper
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# limit of how many detail/SQL rows we display - very large data sets (~10000+) crash browsers
|
|
11
|
+
def trace_row_display_limit
|
|
12
|
+
2000
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def trace_row_display_limit_reached
|
|
16
|
+
(!@detail_segment_count.nil? && @detail_segment_count > trace_row_display_limit) || @sample.sql_segments.length > trace_row_display_limit
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# return the sample but post processed to strip out segments that normally don't show
|
|
20
|
+
# up in production (after the first execution, at least) such as application code loading
|
|
21
|
+
def stripped_sample(sample = @sample)
|
|
22
|
+
sample.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# return the highest level in the call stack for the trace that is not rails or
|
|
26
|
+
# newrelic agent code
|
|
27
|
+
def application_caller(trace)
|
|
28
|
+
trace = strip_nr_from_backtrace(trace) unless params[:show_nr]
|
|
29
|
+
trace.each do |trace_line|
|
|
30
|
+
file, line, gem = file_and_line(trace_line)
|
|
31
|
+
unless file && exclude_file_from_stack_trace?(file, false, gem)
|
|
32
|
+
return trace_line
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
trace.last
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def application_stack_trace(trace, include_rails = false)
|
|
39
|
+
trace = strip_nr_from_backtrace(trace) unless params[:show_nr]
|
|
40
|
+
trace.reject do |trace_line|
|
|
41
|
+
file, line, gem = file_and_line(trace_line)
|
|
42
|
+
file && exclude_file_from_stack_trace?(file, include_rails, gem)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def render_backtrace
|
|
47
|
+
if @segment[:backtrace]
|
|
48
|
+
content_tag('h3', 'Application Stack Trace') +
|
|
49
|
+
render(:partial => 'stack_trace')
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def h(text)
|
|
54
|
+
text
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def agent_views_path(path)
|
|
58
|
+
path
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def url_for_source(trace_line)
|
|
62
|
+
file, line = file_and_line(trace_line)
|
|
63
|
+
return "#" if file.nil?
|
|
64
|
+
begin
|
|
65
|
+
file = Pathname.new(file).realpath
|
|
66
|
+
rescue Errno::ENOENT
|
|
67
|
+
# we hit this exception when Pathame.realpath fails for some reason; attempt a link to
|
|
68
|
+
# the file without a real path. It may also fail, only when the user clicks on this specific
|
|
69
|
+
# entry in the stack trace
|
|
70
|
+
rescue
|
|
71
|
+
# catch all other exceptions. We're going to create an invalid link below, but that's okay.
|
|
72
|
+
end
|
|
73
|
+
if using_textmate?
|
|
74
|
+
"txmt://open?url=file://#{file}&line=#{line}"
|
|
75
|
+
else
|
|
76
|
+
"show_source?file=#{file}&line=#{line}&anchor=selected_line"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def dev_name(metric_name)
|
|
81
|
+
NewRelic::MetricParser::MetricParser.parse(metric_name).developer_name
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# write the metric label for a segment metric in the detail view
|
|
85
|
+
def write_segment_label(segment)
|
|
86
|
+
if source_available && segment[:backtrace] && (source_url = url_for_source(application_caller(segment[:backtrace])))
|
|
87
|
+
link_to dev_name(segment.metric_name), source_url
|
|
88
|
+
else
|
|
89
|
+
dev_name(segment.metric_name)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def source_available
|
|
94
|
+
true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# write the metric label for a segment metric in the summary table of metrics
|
|
98
|
+
def write_summary_segment_label(segment)
|
|
99
|
+
dev_name(segment.metric_name)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def write_stack_trace_line(trace_line)
|
|
103
|
+
link_to trace_line, url_for_source(trace_line)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# write a link to the source for a trace
|
|
107
|
+
def link_to_source(trace)
|
|
108
|
+
image_url = 'file/images/' + (using_textmate? ? "textmate.png" : "file_icon.png")
|
|
109
|
+
|
|
110
|
+
link_to "<img src=#{image_url} alt=\"View Source\" title=\"View Source\"/>", url_for_source(application_caller(trace))
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# print the formatted timestamp for a segment
|
|
114
|
+
def timestamp(segment)
|
|
115
|
+
sprintf("%1.3f", segment.entry_timestamp)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def format_timestamp(time)
|
|
119
|
+
time.strftime("%H:%M:%S")
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def colorize(value, yellow_threshold = 0.05, red_threshold = 0.15, s=to_ms(value))
|
|
123
|
+
if value > yellow_threshold
|
|
124
|
+
color = (value > red_threshold ? 'red' : 'orange')
|
|
125
|
+
"<font color=#{color}>#{s}</font>"
|
|
126
|
+
else
|
|
127
|
+
"#{s}"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def expanded_image_path()
|
|
132
|
+
'/newrelic/file/images/arrow-open.png'
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def collapsed_image_path()
|
|
136
|
+
'/newrelic/file/images/arrow-close.png'
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def explain_sql_url(segment)
|
|
140
|
+
"explain_sql?id=#{@sample.sample_id}&segment=#{segment.segment_id}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def segment_duration_value(segment)
|
|
144
|
+
link_to colorize(segment.duration, 0.05, 0.15, "#{with_delimiter(to_ms(segment.duration))} ms"), explain_sql_url(segment)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def line_wrap_sql(sql)
|
|
148
|
+
sql.gsub(/\,/,', ').squeeze(' ') if sql
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def render_sample_details(sample)
|
|
152
|
+
@indentation_depth=0
|
|
153
|
+
# skip past the root segments to the first child, which is always the controller
|
|
154
|
+
first_segment = sample.root_segment.called_segments.first
|
|
155
|
+
|
|
156
|
+
# render the segments, then the css classes to indent them
|
|
157
|
+
render_segment_details(first_segment).to_s + render_indentation_classes(@indentation_depth).to_s
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# the rows logger plugin disables the sql tracing functionality of the NewRelic agent -
|
|
161
|
+
# notify the user about this
|
|
162
|
+
def rows_logger_present?
|
|
163
|
+
File.exist?(File.join(File.dirname(__FILE__), "../../../rows_logger/init.rb"))
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def expand_segment_image(segment, depth)
|
|
167
|
+
if depth > 0
|
|
168
|
+
if !segment.called_segments.empty?
|
|
169
|
+
row_class =segment_child_row_class(segment)
|
|
170
|
+
link_to_function("<img src=\"#{collapsed_image_path}\" id=\"image_#{row_class}\" class_for_children=\"#{row_class}\" class=\"#{(!segment.called_segments.empty?) ? 'parent_segment_image' : 'child_segment_image'}\"", "toggle_row_class(this)")
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def segment_child_row_class(segment)
|
|
176
|
+
"segment#{segment.segment_id}"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def summary_pie_chart(sample, width, height)
|
|
180
|
+
pie_chart = GooglePieChart.new
|
|
181
|
+
pie_chart.color, pie_chart.width, pie_chart.height = '6688AA', width, height
|
|
182
|
+
|
|
183
|
+
chart_data = sample.breakdown_data(6)
|
|
184
|
+
chart_data.each { |s| pie_chart.add_data_point dev_name(s.metric_name), to_ms(s.exclusive_time) }
|
|
185
|
+
|
|
186
|
+
pie_chart.render
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def segment_row_classes(segment, depth)
|
|
190
|
+
classes = []
|
|
191
|
+
|
|
192
|
+
classes << "segment#{segment.parent_segment.segment_id}" if depth > 1
|
|
193
|
+
|
|
194
|
+
classes << "view_segment" if segment.metric_name.index('View') == 0
|
|
195
|
+
classes << "summary_segment" if segment.is_a?(NewRelic::TransactionSample::CompositeSegment)
|
|
196
|
+
|
|
197
|
+
classes.join(' ')
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# render_segment_details should be called before calling this method
|
|
201
|
+
def render_indentation_classes(depth)
|
|
202
|
+
styles = []
|
|
203
|
+
(1..depth).each do |d|
|
|
204
|
+
styles << ".segment_indent_level#{d} { display: inline-block; margin-left: #{(d-1)*20}px }"
|
|
205
|
+
end
|
|
206
|
+
content_tag("style", styles.join(' '))
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def sql_link_mouseover_options(segment)
|
|
210
|
+
{ :onmouseover => "sql_mouse_over(#{segment.segment_id})", :onmouseout => "sql_mouse_out(#{segment.segment_id})"}
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def explain_sql_link(segment, child_sql = false)
|
|
214
|
+
link_to 'SQL', explain_sql_url(segment)+ '"' + sql_link_mouseover_options(segment).map {|k,v| "#{k}=\"#{v}\""}.join(' ')+ 'fake=\"'
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def explain_sql_links(segment)
|
|
218
|
+
if segment[:sql]
|
|
219
|
+
explain_sql_link segment
|
|
220
|
+
else
|
|
221
|
+
links = []
|
|
222
|
+
segment.called_segments.each do |child|
|
|
223
|
+
if child[:sql]
|
|
224
|
+
links << explain_sql_link(child, true)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
links[0..1].join(', ') + (links.length > 2?', ...':'')
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
private
|
|
232
|
+
# return three objects, the file path, the line in the file, and the gem the file belongs to
|
|
233
|
+
# if found
|
|
234
|
+
def file_and_line(stack_trace_line)
|
|
235
|
+
if stack_trace_line =~ /^(?:(\w+) \([\d.]*\) )?(.*):(\d+)/
|
|
236
|
+
return $2, $3, $1
|
|
237
|
+
else
|
|
238
|
+
return nil
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def using_textmate?
|
|
243
|
+
NewRelic::Control.instance.use_textmate?
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def render_segment_details(segment, depth=0)
|
|
248
|
+
@detail_segment_count ||= 0
|
|
249
|
+
@detail_segment_count += 1
|
|
250
|
+
|
|
251
|
+
return '' if @detail_segment_count > trace_row_display_limit
|
|
252
|
+
|
|
253
|
+
@indentation_depth = depth if depth > @indentation_depth
|
|
254
|
+
repeat = nil
|
|
255
|
+
if segment.is_a?(NewRelic::TransactionSample::CompositeSegment)
|
|
256
|
+
html = ''
|
|
257
|
+
else
|
|
258
|
+
repeat = segment.parent_segment.detail_segments.length if segment.parent_segment.is_a?(NewRelic::TransactionSample::CompositeSegment)
|
|
259
|
+
html = render(:partial => 'segment', :object => [segment, depth, repeat])
|
|
260
|
+
depth += 1
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
segment.called_segments.each do |child|
|
|
264
|
+
html << render_segment_details(child, depth)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
html
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def exclude_file_from_stack_trace?(file, include_rails, gem=nil)
|
|
271
|
+
return false if include_rails
|
|
272
|
+
return true if file !~ /\.(rb|java)/
|
|
273
|
+
return true if %w[rack activerecord activeresource activesupport actionpack railties].include? gem
|
|
274
|
+
%w[/actionmailer/
|
|
275
|
+
/activerecord
|
|
276
|
+
/activeresource
|
|
277
|
+
/activesupport
|
|
278
|
+
/lib/mongrel
|
|
279
|
+
/actionpack
|
|
280
|
+
/passenger/
|
|
281
|
+
/railties
|
|
282
|
+
benchmark.rb].each { |s| return true if file.include? s }
|
|
283
|
+
false
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def show_view_link(title, page_name)
|
|
287
|
+
link_to_function("[#{title}]", "show_view('#{page_name}')");
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def link_to(name, location)
|
|
292
|
+
location = "/newrelic/#{location}" unless /:\/\// =~ location
|
|
293
|
+
"<a href=\"#{location}\">#{name}</a>"
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def link_to_if(predicate, text, location="")
|
|
297
|
+
if predicate
|
|
298
|
+
link_to(text, location)
|
|
299
|
+
else
|
|
300
|
+
text
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def link_to_unless_current(text, hash)
|
|
305
|
+
unless params[hash.keys[0].to_s]
|
|
306
|
+
link_to(text,"?#{hash.keys[0]}=#{hash.values[0]}")
|
|
307
|
+
else
|
|
308
|
+
text
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def cycle(even, odd)
|
|
313
|
+
@cycle ||= 'a'
|
|
314
|
+
if @cycle == 'a'
|
|
315
|
+
@cycle = 'b'
|
|
316
|
+
even
|
|
317
|
+
else
|
|
318
|
+
@cycle = 'a'
|
|
319
|
+
odd
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def link_to_function(title, javascript)
|
|
324
|
+
"<a href=\"#\" onclick=\"#{javascript}; return false;\">#{title}</a>"
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def mime_type_from_extension(extension)
|
|
328
|
+
extension = extension[/[^.]*$/].dncase
|
|
329
|
+
case extension
|
|
330
|
+
when 'png'; 'image/png'
|
|
331
|
+
when 'gif'; 'image/gif'
|
|
332
|
+
when 'jpg'; 'image/jpg'
|
|
333
|
+
when 'css'; 'text/css'
|
|
334
|
+
when 'js'; 'text/javascript'
|
|
335
|
+
else 'text/plain'
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
def to_ms(number)
|
|
339
|
+
(number*1000).round
|
|
340
|
+
end
|
|
341
|
+
def to_percentage(value)
|
|
342
|
+
(value * 100).round if value
|
|
343
|
+
end
|
|
344
|
+
def with_delimiter(val)
|
|
345
|
+
return '0' if val.nil?
|
|
346
|
+
parts = val.to_s.split('.')
|
|
347
|
+
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
|
|
348
|
+
parts.join '.'
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def profile_table(profile)
|
|
352
|
+
out = StringIO.new
|
|
353
|
+
printer = RubyProf::GraphHtmlPrinter.new(profile)
|
|
354
|
+
printer.print(out, :min_percent=>0.5)
|
|
355
|
+
out.string[/<body>(.*)<\/body>/im, 0].gsub('<table>', '<table class=profile>')
|
|
356
|
+
end
|
|
357
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
# A wrapper around the google charts service.
|
|
3
|
+
class GooglePieChart
|
|
4
|
+
attr_accessor :width, :height, :color
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
# an array of [label, value]
|
|
8
|
+
@data = []
|
|
9
|
+
self.width = 300
|
|
10
|
+
self.height = 200
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_data_point(label, value)
|
|
14
|
+
@data << [label, value]
|
|
15
|
+
@max = (@max.nil? || @max < value ? value : @max)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# render the chart to html by creating an image object and
|
|
19
|
+
# placing the correct URL to the google charts api
|
|
20
|
+
def render
|
|
21
|
+
labels = []
|
|
22
|
+
values = []
|
|
23
|
+
@data.each do |label, value|
|
|
24
|
+
labels << CGI::escape(label)
|
|
25
|
+
values << (value > 0 ? value * 100 / @max : value).round.to_s
|
|
26
|
+
end
|
|
27
|
+
params = {:cht => 'p', :chs => "#{width}x#{height}", :chd => "t:#{values.join(',')}", :chl => labels.join('|') }
|
|
28
|
+
params['chco'] = color if color
|
|
29
|
+
|
|
30
|
+
url = "http://chart.apis.google.com/chart?#{to_query(params)}"
|
|
31
|
+
|
|
32
|
+
alt_msg = "This pie chart is generated by Google Charts. You must be connected to the Internet to view this chart."
|
|
33
|
+
html = "<img id=\"pie_chart_image\" src=\"#{url}\" alt=\"#{alt_msg}\"/>"
|
|
34
|
+
return html
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
# Hash#to_query is not present in all supported rails platforms, so implement
|
|
39
|
+
# its equivalent here.
|
|
40
|
+
def to_query(params)
|
|
41
|
+
p = []
|
|
42
|
+
params.each do |k,v|
|
|
43
|
+
p << "#{k}=#{v}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
p.join "&"
|
|
47
|
+
end
|
|
48
|
+
end
|