appoptics_apm 4.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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +43 -0
- data/.dockerignore +5 -0
- data/.gitignore +23 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +82 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Dockerfile +41 -0
- data/Dockerfile_test +66 -0
- data/Gemfile +41 -0
- data/LICENSE +193 -0
- data/README.md +351 -0
- data/Rakefile +202 -0
- data/Vagrantfile +67 -0
- data/appoptics_apm.gemspec +55 -0
- data/build_gems.sh +15 -0
- data/docker-compose.yml +73 -0
- data/examples/DNT.md +35 -0
- data/examples/carrying_context.rb +220 -0
- data/examples/instrumenting_metal_controller.rb +8 -0
- data/examples/puma_on_heroku_config.rb +17 -0
- data/examples/tracing_async_threads.rb +124 -0
- data/examples/tracing_background_jobs.rb +53 -0
- data/examples/tracing_forked_processes.rb +99 -0
- data/examples/unicorn_on_heroku_config.rb +28 -0
- data/ext/oboe_metal/extconf.rb +54 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/lib/liboboe-1.0.so.0.0.0 +0 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/VERSION +1 -0
- data/ext/oboe_metal/src/bson/bson.h +221 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/oboe.h +883 -0
- data/ext/oboe_metal/src/oboe.hpp +793 -0
- data/ext/oboe_metal/src/oboe_debug.h +50 -0
- data/ext/oboe_metal/src/oboe_wrap.cxx +6088 -0
- data/ext/oboe_metal/tests/test.rb +11 -0
- data/gemfiles/delayed_job.gemfile +36 -0
- data/gemfiles/frameworks.gemfile +44 -0
- data/gemfiles/instrumentation_mocked.gemfile +29 -0
- data/gemfiles/libraries.gemfile +85 -0
- data/gemfiles/rails23.gemfile +39 -0
- data/gemfiles/rails30.gemfile +42 -0
- data/gemfiles/rails31.gemfile +44 -0
- data/gemfiles/rails32.gemfile +54 -0
- data/gemfiles/rails40.gemfile +27 -0
- data/gemfiles/rails41.gemfile +27 -0
- data/gemfiles/rails42.gemfile +35 -0
- data/gemfiles/rails50.gemfile +44 -0
- data/gemfiles/rails51.gemfile +44 -0
- data/get_version.rb +5 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm/api/layerinit.rb +39 -0
- data/lib/appoptics_apm/api/logging.rb +359 -0
- data/lib/appoptics_apm/api/memcache.rb +34 -0
- data/lib/appoptics_apm/api/profiling.rb +201 -0
- data/lib/appoptics_apm/api/tracing.rb +152 -0
- data/lib/appoptics_apm/api/util.rb +128 -0
- data/lib/appoptics_apm/api.rb +18 -0
- data/lib/appoptics_apm/base.rb +252 -0
- data/lib/appoptics_apm/config.rb +281 -0
- data/lib/appoptics_apm/frameworks/grape.rb +93 -0
- data/lib/appoptics_apm/frameworks/padrino/templates.rb +58 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +52 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +106 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller2.rb +61 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +58 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view_2x.rb +56 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +120 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +101 -0
- data/lib/appoptics_apm/frameworks/rails.rb +116 -0
- data/lib/appoptics_apm/frameworks/sinatra/templates.rb +56 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +71 -0
- data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
- data/lib/appoptics_apm/inst/bunny-consumer.rb +92 -0
- data/lib/appoptics_apm/inst/curb.rb +329 -0
- data/lib/appoptics_apm/inst/dalli.rb +85 -0
- data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
- data/lib/appoptics_apm/inst/em-http-request.rb +105 -0
- data/lib/appoptics_apm/inst/excon.rb +130 -0
- data/lib/appoptics_apm/inst/faraday.rb +77 -0
- data/lib/appoptics_apm/inst/http.rb +83 -0
- data/lib/appoptics_apm/inst/httpclient.rb +176 -0
- data/lib/appoptics_apm/inst/memcache.rb +102 -0
- data/lib/appoptics_apm/inst/memcached.rb +94 -0
- data/lib/appoptics_apm/inst/mongo.rb +242 -0
- data/lib/appoptics_apm/inst/mongo2.rb +225 -0
- data/lib/appoptics_apm/inst/moped.rb +466 -0
- data/lib/appoptics_apm/inst/rack.rb +146 -0
- data/lib/appoptics_apm/inst/redis.rb +275 -0
- data/lib/appoptics_apm/inst/resque.rb +151 -0
- data/lib/appoptics_apm/inst/rest-client.rb +50 -0
- data/lib/appoptics_apm/inst/sequel.rb +178 -0
- data/lib/appoptics_apm/inst/sidekiq-client.rb +53 -0
- data/lib/appoptics_apm/inst/sidekiq-worker.rb +67 -0
- data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
- data/lib/appoptics_apm/inst/typhoeus.rb +113 -0
- data/lib/appoptics_apm/instrumentation.rb +22 -0
- data/lib/appoptics_apm/legacy_method_profiling.rb +97 -0
- data/lib/appoptics_apm/loading.rb +66 -0
- data/lib/appoptics_apm/logger.rb +41 -0
- data/lib/appoptics_apm/method_profiling.rb +33 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/support.rb +135 -0
- data/lib/appoptics_apm/test.rb +94 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +312 -0
- data/lib/appoptics_apm/version.rb +15 -0
- data/lib/appoptics_apm/xtrace.rb +103 -0
- data/lib/appoptics_apm.rb +72 -0
- data/lib/joboe_metal.rb +214 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +80 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +187 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +222 -0
- data/ruby_setup.sh +47 -0
- data/run_docker_build_gem_upload_to_packagecloud.sh +20 -0
- data/run_tests_docker.rb +32 -0
- data/test/benchmark/README.md +65 -0
- data/test/benchmark/logging_bench.rb +54 -0
- data/test/benchmark/with_libraries_gemfile/bunny_bench.rb +69 -0
- data/test/benchmark/with_rails5x_gemfile/action_controller5x_bench.rb +43 -0
- data/test/frameworks/apps/grape_nested.rb +33 -0
- data/test/frameworks/apps/grape_simple.rb +80 -0
- data/test/frameworks/apps/padrino_simple.rb +80 -0
- data/test/frameworks/apps/sinatra_simple.rb +55 -0
- data/test/frameworks/grape_test.rb +286 -0
- data/test/frameworks/padrino_test.rb +222 -0
- data/test/frameworks/rails3x_test.rb +554 -0
- data/test/frameworks/rails4x_test.rb +570 -0
- data/test/frameworks/rails5x_api_test.rb +210 -0
- data/test/frameworks/rails5x_test.rb +376 -0
- data/test/frameworks/rails_shared_tests.rb +172 -0
- data/test/frameworks/sinatra_test.rb +140 -0
- data/test/instrumentation/bunny_client_test.rb +276 -0
- data/test/instrumentation/bunny_consumer_test.rb +204 -0
- data/test/instrumentation/curb_test.rb +398 -0
- data/test/instrumentation/dalli_test.rb +177 -0
- data/test/instrumentation/em_http_request_test.rb +89 -0
- data/test/instrumentation/excon_test.rb +231 -0
- data/test/instrumentation/faraday_test.rb +228 -0
- data/test/instrumentation/http_test.rb +143 -0
- data/test/instrumentation/httpclient_test.rb +320 -0
- data/test/instrumentation/memcache_test.rb +260 -0
- data/test/instrumentation/memcached_test.rb +229 -0
- data/test/instrumentation/mongo_v1_test.rb +479 -0
- data/test/instrumentation/mongo_v2_index_test.rb +124 -0
- data/test/instrumentation/mongo_v2_test.rb +584 -0
- data/test/instrumentation/mongo_v2_view_test.rb +435 -0
- data/test/instrumentation/moped_test.rb +517 -0
- data/test/instrumentation/rack_test.rb +165 -0
- data/test/instrumentation/redis_hashes_test.rb +268 -0
- data/test/instrumentation/redis_keys_test.rb +321 -0
- data/test/instrumentation/redis_lists_test.rb +310 -0
- data/test/instrumentation/redis_misc_test.rb +163 -0
- data/test/instrumentation/redis_sets_test.rb +296 -0
- data/test/instrumentation/redis_sortedsets_test.rb +328 -0
- data/test/instrumentation/redis_strings_test.rb +349 -0
- data/test/instrumentation/resque_test.rb +185 -0
- data/test/instrumentation/rest-client_test.rb +288 -0
- data/test/instrumentation/sequel_mysql2_test.rb +353 -0
- data/test/instrumentation/sequel_mysql_test.rb +334 -0
- data/test/instrumentation/sequel_pg_test.rb +336 -0
- data/test/instrumentation/sidekiq-client_test.rb +159 -0
- data/test/instrumentation/sidekiq-worker_test.rb +180 -0
- data/test/instrumentation/twitter-cassandra_test.rb +424 -0
- data/test/instrumentation/typhoeus_test.rb +284 -0
- data/test/jobs/delayed_job/db_worker_job.rb +29 -0
- data/test/jobs/delayed_job/error_worker_job.rb +10 -0
- data/test/jobs/delayed_job/remote_call_worker_job.rb +20 -0
- data/test/jobs/resque/db_worker_job.rb +29 -0
- data/test/jobs/resque/error_worker_job.rb +10 -0
- data/test/jobs/resque/remote_call_worker_job.rb +20 -0
- data/test/jobs/sidekiq/db_worker_job.rb +29 -0
- data/test/jobs/sidekiq/error_worker_job.rb +10 -0
- data/test/jobs/sidekiq/remote_call_worker_job.rb +20 -0
- data/test/minitest_helper.rb +276 -0
- data/test/mocked/curb_mocked_test.rb +311 -0
- data/test/mocked/excon_mocked_test.rb +166 -0
- data/test/mocked/faraday_mocked_test.rb +93 -0
- data/test/mocked/http_mocked_test.rb +129 -0
- data/test/mocked/httpclient_mocked_test.rb +245 -0
- data/test/mocked/rest_client_mocked_test.rb +103 -0
- data/test/mocked/typhoeus_mocked_test.rb +192 -0
- data/test/models/widget.rb +36 -0
- data/test/profiling/legacy_method_profiling_test.rb +201 -0
- data/test/profiling/method_profiling_test.rb +631 -0
- data/test/queues/delayed_job-client_test.rb +95 -0
- data/test/queues/delayed_job-worker_test.rb +91 -0
- data/test/reporter/reporter_test.rb +14 -0
- data/test/servers/delayed_job.rb +107 -0
- data/test/servers/rackapp_8101.rb +29 -0
- data/test/servers/rails3x_8140.rb +96 -0
- data/test/servers/rails4x_8140.rb +96 -0
- data/test/servers/rails5x_8140.rb +95 -0
- data/test/servers/rails5x_api_8150.rb +78 -0
- data/test/servers/sidekiq.rb +29 -0
- data/test/servers/sidekiq.yml +7 -0
- data/test/servers/sidekiq_initializer.rb +25 -0
- data/test/settings +0 -0
- data/test/support/auto_tracing_test.rb +50 -0
- data/test/support/backcompat_test.rb +276 -0
- data/test/support/config_test.rb +149 -0
- data/test/support/dnt_test.rb +98 -0
- data/test/support/init_report_test.rb +25 -0
- data/test/support/liboboe_settings_test.rb +110 -0
- data/test/support/logging_test.rb +130 -0
- data/test/support/noop_test.rb +88 -0
- data/test/support/sql_sanitize_test.rb +55 -0
- data/test/support/tracing_mode_test.rb +33 -0
- data/test/support/tvalias_test.rb +15 -0
- data/test/support/xtrace_test.rb +41 -0
- metadata +475 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require "minitest_helper"
|
|
5
|
+
|
|
6
|
+
if defined?(::Rails)
|
|
7
|
+
|
|
8
|
+
describe "Rails3x" do
|
|
9
|
+
before do
|
|
10
|
+
clear_all_traces
|
|
11
|
+
AppOpticsAPM.config_lock.synchronize {
|
|
12
|
+
@tm = AppOpticsAPM::Config[:tracing_mode]
|
|
13
|
+
@collect_backtraces = AppOpticsAPM::Config[:action_controller][:collect_backtraces]
|
|
14
|
+
@sample_rate = AppOpticsAPM::Config[:sample_rate]
|
|
15
|
+
@sanitize_sql = AppOpticsAPM::Config[:sanitize_sql]
|
|
16
|
+
}
|
|
17
|
+
ENV['DBTYPE'] = "postgresql" unless ENV['DBTYPE']
|
|
18
|
+
ENV['TEST_DB_URI'] ||= 'http://127.0.0.1:8140'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
after do
|
|
22
|
+
AppOpticsAPM.config_lock.synchronize {
|
|
23
|
+
AppOpticsAPM::Config[:action_controller][:collect_backtraces] = @collect_backtraces
|
|
24
|
+
AppOpticsAPM::Config[:tracing_mode] = @tm
|
|
25
|
+
AppOpticsAPM::Config[:sample_rate] = @sample_rate
|
|
26
|
+
AppOpticsAPM::Config[:sanitize_sql] = @sanitize_sql
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should trace a request to a rails stack" do
|
|
31
|
+
|
|
32
|
+
uri = URI.parse("#{ENV['TEST_DB_URI']}/hello/world")
|
|
33
|
+
r = Net::HTTP.get_response(uri)
|
|
34
|
+
|
|
35
|
+
traces = get_all_traces
|
|
36
|
+
|
|
37
|
+
traces.count.must_equal 8
|
|
38
|
+
unless defined?(JRUBY_VERSION)
|
|
39
|
+
# We don't test this under JRuby because the Java instrumentation
|
|
40
|
+
# for the DB drivers doesn't use our test reporter hence we won't
|
|
41
|
+
# see all trace events. :-( To be improved.
|
|
42
|
+
valid_edges?(traces).must_equal true
|
|
43
|
+
end
|
|
44
|
+
validate_outer_layers(traces, 'rack')
|
|
45
|
+
|
|
46
|
+
traces[0]['Layer'].must_equal "rack"
|
|
47
|
+
traces[0]['Label'].must_equal "entry"
|
|
48
|
+
traces[0]['URL'].must_equal "/hello/world"
|
|
49
|
+
|
|
50
|
+
traces[1]['Layer'].must_equal "rack"
|
|
51
|
+
traces[1]['Label'].must_equal "info"
|
|
52
|
+
|
|
53
|
+
traces[2]['Layer'].must_equal "rails"
|
|
54
|
+
traces[2]['Label'].must_equal "entry"
|
|
55
|
+
|
|
56
|
+
traces[3]['Label'].must_equal "info"
|
|
57
|
+
traces[3]['Controller'].must_equal "HelloController"
|
|
58
|
+
traces[3]['Action'].must_equal "world"
|
|
59
|
+
|
|
60
|
+
traces[4]['Layer'].must_equal "actionview"
|
|
61
|
+
traces[4]['Label'].must_equal "entry"
|
|
62
|
+
|
|
63
|
+
traces[5]['Layer'].must_equal "actionview"
|
|
64
|
+
traces[5]['Label'].must_equal "exit"
|
|
65
|
+
|
|
66
|
+
traces[6]['Layer'].must_equal "rails"
|
|
67
|
+
traces[6]['Label'].must_equal "exit"
|
|
68
|
+
|
|
69
|
+
traces[7]['Layer'].must_equal "rack"
|
|
70
|
+
traces[7]['Label'].must_equal "exit"
|
|
71
|
+
|
|
72
|
+
# Validate the existence of the response header
|
|
73
|
+
r.header.key?('X-Trace').must_equal true
|
|
74
|
+
r.header['X-Trace'].must_equal traces[7]['X-Trace']
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should trace a request to a rails metal stack" do
|
|
78
|
+
|
|
79
|
+
uri = URI.parse("#{ENV['TEST_DB_URI']}/hello/metal")
|
|
80
|
+
r = Net::HTTP.get_response(uri)
|
|
81
|
+
|
|
82
|
+
traces = get_all_traces
|
|
83
|
+
|
|
84
|
+
traces.count.must_equal 5
|
|
85
|
+
unless defined?(JRUBY_VERSION)
|
|
86
|
+
# We don't test this under JRuby because the Java instrumentation
|
|
87
|
+
# for the DB drivers doesn't use our test reporter hence we won't
|
|
88
|
+
# see all trace events. :-( To be improved.
|
|
89
|
+
valid_edges?(traces).must_equal true
|
|
90
|
+
end
|
|
91
|
+
validate_outer_layers(traces, 'rack')
|
|
92
|
+
|
|
93
|
+
traces[0]['Layer'].must_equal "rack"
|
|
94
|
+
traces[0]['Label'].must_equal "entry"
|
|
95
|
+
traces[0]['URL'].must_equal "/hello/metal"
|
|
96
|
+
|
|
97
|
+
traces[1]['Layer'].must_equal "rack"
|
|
98
|
+
traces[1]['Label'].must_equal "info"
|
|
99
|
+
|
|
100
|
+
traces[2]['Label'].must_equal "profile_entry"
|
|
101
|
+
traces[2]['Language'].must_equal "ruby"
|
|
102
|
+
traces[2]['ProfileName'].must_equal "world"
|
|
103
|
+
traces[2]['Class'].must_equal "FerroController"
|
|
104
|
+
|
|
105
|
+
traces[3]['Label'].must_equal "profile_exit"
|
|
106
|
+
traces[3]['Language'].must_equal "ruby"
|
|
107
|
+
traces[3]['ProfileName'].must_equal "world"
|
|
108
|
+
|
|
109
|
+
traces[4]['Layer'].must_equal "rack"
|
|
110
|
+
traces[4]['Label'].must_equal "exit"
|
|
111
|
+
|
|
112
|
+
# Validate the existence of the response header
|
|
113
|
+
r.header.key?('X-Trace').must_equal true
|
|
114
|
+
r.header['X-Trace'].must_equal traces[4]['X-Trace']
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# TODO: should we have this test for other rails versions as well?
|
|
118
|
+
# TODO: review this test and why it fails (sometimes?)
|
|
119
|
+
it "should trace rails postgresql db calls" do
|
|
120
|
+
# Skip for JRuby since the java instrumentation
|
|
121
|
+
# handles DB instrumentation for JRuby
|
|
122
|
+
skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != "postgresql"
|
|
123
|
+
|
|
124
|
+
uri = URI.parse('http://127.0.0.1:8140/hello/db')
|
|
125
|
+
r = Net::HTTP.get_response(uri)
|
|
126
|
+
|
|
127
|
+
traces = get_all_traces
|
|
128
|
+
|
|
129
|
+
traces.count.must_equal 14
|
|
130
|
+
valid_edges?(traces).must_equal true
|
|
131
|
+
validate_outer_layers(traces, 'rack')
|
|
132
|
+
|
|
133
|
+
traces[4]['Layer'].must_equal "activerecord"
|
|
134
|
+
traces[4]['Label'].must_equal "entry"
|
|
135
|
+
traces[4]['Flavor'].must_equal "postgresql"
|
|
136
|
+
|
|
137
|
+
# Some versions of rails adds in another space before the ORDER keyword.
|
|
138
|
+
# Make 2 or more consecutive spaces just 1
|
|
139
|
+
sql = traces[4]['Query'].gsub(/\s{2,}/, ' ')
|
|
140
|
+
sql.must_equal "INSERT INTO \"widgets\" (\"created_at\", \"description\", \"name\", \"updated_at\") VALUES ($?, $?, $?, $?) RETURNING \"id\""
|
|
141
|
+
|
|
142
|
+
traces[4]['Name'].must_equal "SQL"
|
|
143
|
+
traces[4].key?('Backtrace').must_equal true
|
|
144
|
+
|
|
145
|
+
traces[5]['Layer'].must_equal "activerecord"
|
|
146
|
+
traces[5]['Label'].must_equal "exit"
|
|
147
|
+
|
|
148
|
+
traces[6]['Layer'].must_equal "activerecord"
|
|
149
|
+
traces[6]['Label'].must_equal "entry"
|
|
150
|
+
traces[6]['Flavor'].must_equal "postgresql"
|
|
151
|
+
traces[6]['Query'].must_equal "SELECT \"widgets\".* FROM \"widgets\" WHERE \"widgets\".\"name\" = ? LIMIT ?"
|
|
152
|
+
traces[6]['Name'].must_equal "Widget Load"
|
|
153
|
+
traces[6].key?('Backtrace').must_equal true
|
|
154
|
+
traces[6].key?('QueryArgs').must_equal false
|
|
155
|
+
|
|
156
|
+
traces[7]['Layer'].must_equal "activerecord"
|
|
157
|
+
traces[7]['Label'].must_equal "exit"
|
|
158
|
+
|
|
159
|
+
traces[8]['Layer'].must_equal "activerecord"
|
|
160
|
+
traces[8]['Label'].must_equal "entry"
|
|
161
|
+
traces[8]['Flavor'].must_equal "postgresql"
|
|
162
|
+
|
|
163
|
+
# Remove the widget id so we can test everything else
|
|
164
|
+
sql = traces[8]['Query'].gsub(/\d+/, 'xxx')
|
|
165
|
+
sql.must_equal "DELETE FROM \"widgets\" WHERE \"widgets\".\"id\" = ?"
|
|
166
|
+
|
|
167
|
+
traces[8]['Name'].must_equal "SQL"
|
|
168
|
+
traces[8].key?('Backtrace').must_equal true
|
|
169
|
+
traces[8].key?('QueryArgs').must_equal false
|
|
170
|
+
|
|
171
|
+
traces[9]['Layer'].must_equal "activerecord"
|
|
172
|
+
traces[9]['Label'].must_equal "exit"
|
|
173
|
+
|
|
174
|
+
# Validate the existence of the response header
|
|
175
|
+
r['X-Trace'].must_equal traces[13]['X-Trace']
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "should trace rails mysql db calls" do
|
|
179
|
+
# Skip for JRuby since the java instrumentation
|
|
180
|
+
# handles DB instrumentation for JRuby
|
|
181
|
+
skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != "mysql"
|
|
182
|
+
|
|
183
|
+
AppOpticsAPM::Config[:sanitize_sql] = false
|
|
184
|
+
|
|
185
|
+
uri = URI.parse("#{ENV['TEST_DB_URI']}/hello/db")
|
|
186
|
+
r = Net::HTTP.get_response(uri)
|
|
187
|
+
|
|
188
|
+
traces = get_all_traces
|
|
189
|
+
traces.count.must_equal 18
|
|
190
|
+
valid_edges?(traces).must_equal true
|
|
191
|
+
validate_outer_layers(traces, 'rack')
|
|
192
|
+
|
|
193
|
+
traces[4]['Layer'].must_equal "activerecord"
|
|
194
|
+
traces[4]['Label'].must_equal "entry"
|
|
195
|
+
traces[4]['Flavor'].must_equal "mysql"
|
|
196
|
+
traces[4]['Query'].must_equal "BEGIN"
|
|
197
|
+
traces[4].key?('Backtrace').must_equal true
|
|
198
|
+
|
|
199
|
+
traces[5]['Layer'].must_equal "activerecord"
|
|
200
|
+
traces[5]['Label'].must_equal "exit"
|
|
201
|
+
|
|
202
|
+
traces[6]['Layer'].must_equal "activerecord"
|
|
203
|
+
traces[6]['Label'].must_equal "entry"
|
|
204
|
+
traces[6]['Flavor'].must_equal "mysql"
|
|
205
|
+
traces[6]['Query'].must_equal "INSERT INTO `widgets` (`created_at`, `description`, `name`, `updated_at`) VALUES (?, ?, ?, ?)"
|
|
206
|
+
traces[6]['Name'].must_equal "SQL"
|
|
207
|
+
traces[6].key?('Backtrace').must_equal true
|
|
208
|
+
traces[6].key?('QueryArgs').must_equal true
|
|
209
|
+
|
|
210
|
+
traces[7]['Layer'].must_equal "activerecord"
|
|
211
|
+
traces[7]['Label'].must_equal "exit"
|
|
212
|
+
|
|
213
|
+
traces[8]['Layer'].must_equal "activerecord"
|
|
214
|
+
traces[8]['Label'].must_equal "entry"
|
|
215
|
+
traces[8]['Flavor'].must_equal "mysql"
|
|
216
|
+
traces[8]['Query'].must_equal "COMMIT"
|
|
217
|
+
traces[8].key?('Backtrace').must_equal true
|
|
218
|
+
|
|
219
|
+
traces[9]['Layer'].must_equal "activerecord"
|
|
220
|
+
traces[9]['Label'].must_equal "exit"
|
|
221
|
+
|
|
222
|
+
traces[10]['Layer'].must_equal "activerecord"
|
|
223
|
+
traces[10]['Label'].must_equal "entry"
|
|
224
|
+
traces[10]['Flavor'].must_equal "mysql"
|
|
225
|
+
traces[10]['Name'].must_equal "Widget Load"
|
|
226
|
+
traces[10].key?('Backtrace').must_equal true
|
|
227
|
+
|
|
228
|
+
# Some versions of rails adds in another space before the ORDER keyword.
|
|
229
|
+
# Make 2 or more consecutive spaces just 1
|
|
230
|
+
sql = traces[10]['Query'].gsub(/\s{2,}/, ' ')
|
|
231
|
+
sql.must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = 'blah' LIMIT 1"
|
|
232
|
+
|
|
233
|
+
traces[11]['Layer'].must_equal "activerecord"
|
|
234
|
+
traces[11]['Label'].must_equal "exit"
|
|
235
|
+
|
|
236
|
+
traces[12]['Layer'].must_equal "activerecord"
|
|
237
|
+
traces[12]['Label'].must_equal "entry"
|
|
238
|
+
traces[12]['Flavor'].must_equal "mysql"
|
|
239
|
+
traces[12]['Name'].must_equal "SQL"
|
|
240
|
+
traces[12].key?('Backtrace').must_equal true
|
|
241
|
+
traces[12].key?('QueryArgs').must_equal false
|
|
242
|
+
|
|
243
|
+
# Replace the datestamps with xxx to make testing easier
|
|
244
|
+
sql = traces[12]['Query'].gsub(/\d+/, 'xxx')
|
|
245
|
+
sql.must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = xxx"
|
|
246
|
+
|
|
247
|
+
traces[13]['Layer'].must_equal "activerecord"
|
|
248
|
+
traces[13]['Label'].must_equal "exit"
|
|
249
|
+
|
|
250
|
+
traces[14]['Layer'].must_equal "actionview"
|
|
251
|
+
traces[14]['Label'].must_equal "entry"
|
|
252
|
+
|
|
253
|
+
# Validate the existence of the response header
|
|
254
|
+
r['X-Trace'].must_equal traces[17]['X-Trace']
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
it "should trace rails mysql db calls with sanitize sql" do
|
|
258
|
+
# Skip for JRuby since the java instrumentation
|
|
259
|
+
# handles DB instrumentation for JRuby
|
|
260
|
+
skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != "mysql"
|
|
261
|
+
|
|
262
|
+
AppOpticsAPM::Config[:sanitize_sql] = true
|
|
263
|
+
|
|
264
|
+
uri = URI.parse("#{ENV['TEST_DB_URI']}/hello/db")
|
|
265
|
+
r = Net::HTTP.get_response(uri)
|
|
266
|
+
|
|
267
|
+
traces = get_all_traces
|
|
268
|
+
traces.count.must_equal 18
|
|
269
|
+
valid_edges?(traces).must_equal true
|
|
270
|
+
validate_outer_layers(traces, 'rack')
|
|
271
|
+
|
|
272
|
+
traces[4]['Layer'].must_equal "activerecord"
|
|
273
|
+
traces[4]['Label'].must_equal "entry"
|
|
274
|
+
traces[4]['Flavor'].must_equal "mysql"
|
|
275
|
+
traces[4]['Query'].must_equal "BEGIN"
|
|
276
|
+
traces[4].key?('Backtrace').must_equal true
|
|
277
|
+
|
|
278
|
+
traces[5]['Layer'].must_equal "activerecord"
|
|
279
|
+
traces[5]['Label'].must_equal "exit"
|
|
280
|
+
|
|
281
|
+
traces[6]['Layer'].must_equal "activerecord"
|
|
282
|
+
traces[6]['Label'].must_equal "entry"
|
|
283
|
+
traces[6]['Flavor'].must_equal "mysql"
|
|
284
|
+
traces[6]['Query'].must_equal "INSERT INTO `widgets` (`created_at`, `description`, `name`, `updated_at`) VALUES (?, ?, ?, ?)"
|
|
285
|
+
traces[6]['Name'].must_equal "SQL"
|
|
286
|
+
traces[6].key?('Backtrace').must_equal true
|
|
287
|
+
traces[6].key?('QueryArgs').must_equal false
|
|
288
|
+
|
|
289
|
+
traces[7]['Layer'].must_equal "activerecord"
|
|
290
|
+
traces[7]['Label'].must_equal "exit"
|
|
291
|
+
|
|
292
|
+
traces[8]['Layer'].must_equal "activerecord"
|
|
293
|
+
traces[8]['Label'].must_equal "entry"
|
|
294
|
+
traces[8]['Flavor'].must_equal "mysql"
|
|
295
|
+
traces[8]['Query'].must_equal "COMMIT"
|
|
296
|
+
traces[8].key?('Backtrace').must_equal true
|
|
297
|
+
|
|
298
|
+
traces[9]['Layer'].must_equal "activerecord"
|
|
299
|
+
traces[9]['Label'].must_equal "exit"
|
|
300
|
+
|
|
301
|
+
traces[10]['Layer'].must_equal "activerecord"
|
|
302
|
+
traces[10]['Label'].must_equal "entry"
|
|
303
|
+
traces[10]['Flavor'].must_equal "mysql"
|
|
304
|
+
traces[10]['Name'].must_equal "Widget Load"
|
|
305
|
+
traces[10].key?('Backtrace').must_equal true
|
|
306
|
+
traces[10]['Query'].gsub!(/ /, ' ')
|
|
307
|
+
traces[10]['Query'].must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = ? LIMIT ?"
|
|
308
|
+
|
|
309
|
+
traces[11]['Layer'].must_equal "activerecord"
|
|
310
|
+
traces[11]['Label'].must_equal "exit"
|
|
311
|
+
|
|
312
|
+
traces[12]['Layer'].must_equal "activerecord"
|
|
313
|
+
traces[12]['Label'].must_equal "entry"
|
|
314
|
+
traces[12]['Flavor'].must_equal "mysql"
|
|
315
|
+
traces[12]['Name'].must_equal "SQL"
|
|
316
|
+
traces[12].key?('Backtrace').must_equal true
|
|
317
|
+
traces[12].key?('QueryArgs').must_equal false
|
|
318
|
+
|
|
319
|
+
# Replace the datestamps with xxx to make testing easier
|
|
320
|
+
sql = traces[12]['Query'].gsub(/\d+/, 'xxx')
|
|
321
|
+
sql.must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = ?"
|
|
322
|
+
|
|
323
|
+
traces[13]['Layer'].must_equal "activerecord"
|
|
324
|
+
traces[13]['Label'].must_equal "exit"
|
|
325
|
+
|
|
326
|
+
traces[14]['Layer'].must_equal "actionview"
|
|
327
|
+
traces[14]['Label'].must_equal "entry"
|
|
328
|
+
|
|
329
|
+
# Validate the existence of the response header
|
|
330
|
+
r['X-Trace'].must_equal traces[17]['X-Trace']
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
it "should trace rails mysql2 db calls" do
|
|
334
|
+
# Skip for JRuby since the java instrumentation
|
|
335
|
+
# handles DB instrumentation for JRuby
|
|
336
|
+
skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != 'mysql2'
|
|
337
|
+
|
|
338
|
+
AppOpticsAPM::Config[:sanitize_sql] = false
|
|
339
|
+
|
|
340
|
+
uri = URI.parse("#{ENV['TEST_DB_URI']}/hello/db")
|
|
341
|
+
r = Net::HTTP.get_response(uri)
|
|
342
|
+
|
|
343
|
+
traces = get_all_traces
|
|
344
|
+
|
|
345
|
+
traces.count.must_equal 14
|
|
346
|
+
valid_edges?(traces).must_equal true
|
|
347
|
+
validate_outer_layers(traces, 'rack')
|
|
348
|
+
|
|
349
|
+
traces[4]['Layer'].must_equal "activerecord"
|
|
350
|
+
traces[4]['Label'].must_equal "entry"
|
|
351
|
+
traces[4]['Flavor'].must_equal "mysql"
|
|
352
|
+
|
|
353
|
+
# Replace the datestamps with xxx to make testing easier
|
|
354
|
+
traces[4]['Query'].gsub!(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d/, 'xxx')
|
|
355
|
+
traces[4]['Query'].must_equal "INSERT INTO `widgets` (`created_at`, `description`, `name`, `updated_at`) VALUES ('xxx', 'This is an amazing widget.', 'blah', 'xxx')"
|
|
356
|
+
|
|
357
|
+
traces[4]['Name'].must_equal "SQL"
|
|
358
|
+
traces[4].key?('Backtrace').must_equal true
|
|
359
|
+
|
|
360
|
+
traces[5]['Layer'].must_equal "activerecord"
|
|
361
|
+
traces[5]['Label'].must_equal "exit"
|
|
362
|
+
|
|
363
|
+
traces[6]['Layer'].must_equal "activerecord"
|
|
364
|
+
traces[6]['Label'].must_equal "entry"
|
|
365
|
+
traces[6]['Flavor'].must_equal "mysql"
|
|
366
|
+
traces[6]['Query'].must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = 'blah' LIMIT 1"
|
|
367
|
+
traces[6]['Name'].must_equal "Widget Load"
|
|
368
|
+
traces[6].key?('Backtrace').must_equal true
|
|
369
|
+
|
|
370
|
+
traces[7]['Layer'].must_equal "activerecord"
|
|
371
|
+
traces[7]['Label'].must_equal "exit"
|
|
372
|
+
|
|
373
|
+
traces[8]['Layer'].must_equal "activerecord"
|
|
374
|
+
traces[8]['Label'].must_equal "entry"
|
|
375
|
+
traces[8]['Flavor'].must_equal "mysql"
|
|
376
|
+
|
|
377
|
+
# Replace the datestamps with xxx to make testing easier
|
|
378
|
+
sql = traces[8]['Query'].gsub(/\d+/, 'xxx')
|
|
379
|
+
sql.must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = xxx"
|
|
380
|
+
|
|
381
|
+
traces[8]['Name'].must_equal "SQL"
|
|
382
|
+
traces[8].key?('Backtrace').must_equal true
|
|
383
|
+
traces[8].key?('QueryArgs').must_equal false
|
|
384
|
+
|
|
385
|
+
traces[9]['Layer'].must_equal "activerecord"
|
|
386
|
+
traces[9]['Label'].must_equal "exit"
|
|
387
|
+
|
|
388
|
+
# Validate the existence of the response header
|
|
389
|
+
r.header.key?('X-Trace').must_equal true
|
|
390
|
+
r.header['X-Trace'].must_equal traces[13]['X-Trace']
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it "should trace rails mysql2 db calls with sanitize sql" do
|
|
394
|
+
# Skip for JRuby since the java instrumentation
|
|
395
|
+
# handles DB instrumentation for JRuby
|
|
396
|
+
skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != 'mysql2'
|
|
397
|
+
|
|
398
|
+
AppOpticsAPM::Config[:sanitize_sql] = true
|
|
399
|
+
|
|
400
|
+
uri = URI.parse("#{ENV['TEST_DB_URI']}/hello/db")
|
|
401
|
+
r = Net::HTTP.get_response(uri)
|
|
402
|
+
|
|
403
|
+
traces = get_all_traces
|
|
404
|
+
|
|
405
|
+
traces.count.must_equal 14
|
|
406
|
+
valid_edges?(traces).must_equal true
|
|
407
|
+
validate_outer_layers(traces, 'rack')
|
|
408
|
+
|
|
409
|
+
traces[4]['Layer'].must_equal "activerecord"
|
|
410
|
+
traces[4]['Label'].must_equal "entry"
|
|
411
|
+
traces[4]['Flavor'].must_equal "mysql"
|
|
412
|
+
|
|
413
|
+
traces[4]['Query'].must_equal "INSERT INTO `widgets` (`created_at`, `description`, `name`, `updated_at`) VALUES (?, ?, ?, ?)"
|
|
414
|
+
|
|
415
|
+
traces[4]['Name'].must_equal "SQL"
|
|
416
|
+
traces[4].key?('Backtrace').must_equal true
|
|
417
|
+
|
|
418
|
+
traces[5]['Layer'].must_equal "activerecord"
|
|
419
|
+
traces[5]['Label'].must_equal "exit"
|
|
420
|
+
|
|
421
|
+
traces[6]['Layer'].must_equal "activerecord"
|
|
422
|
+
traces[6]['Label'].must_equal "entry"
|
|
423
|
+
traces[6]['Flavor'].must_equal "mysql"
|
|
424
|
+
traces[6]['Query'].must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = ? LIMIT ?"
|
|
425
|
+
traces[6]['Name'].must_equal "Widget Load"
|
|
426
|
+
traces[6].key?('Backtrace').must_equal true
|
|
427
|
+
traces[6].key?('QueryArgs').must_equal false
|
|
428
|
+
|
|
429
|
+
traces[7]['Layer'].must_equal "activerecord"
|
|
430
|
+
traces[7]['Label'].must_equal "exit"
|
|
431
|
+
|
|
432
|
+
traces[8]['Layer'].must_equal "activerecord"
|
|
433
|
+
traces[8]['Label'].must_equal "entry"
|
|
434
|
+
traces[8]['Flavor'].must_equal "mysql"
|
|
435
|
+
|
|
436
|
+
# Replace the datestamps with xxx to make testing easier
|
|
437
|
+
sql = traces[8]['Query'].gsub(/\d+/, 'xxx')
|
|
438
|
+
sql.must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = ?"
|
|
439
|
+
|
|
440
|
+
traces[8]['Name'].must_equal "SQL"
|
|
441
|
+
traces[8].key?('Backtrace').must_equal true
|
|
442
|
+
traces[8].key?('QueryArgs').must_equal false
|
|
443
|
+
|
|
444
|
+
traces[9]['Layer'].must_equal "activerecord"
|
|
445
|
+
traces[9]['Label'].must_equal "exit"
|
|
446
|
+
|
|
447
|
+
# Validate the existence of the response header
|
|
448
|
+
r.header.key?('X-Trace').must_equal true
|
|
449
|
+
r.header['X-Trace'].must_equal traces[13]['X-Trace']
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
it "should collect backtraces when true" do
|
|
453
|
+
|
|
454
|
+
AppOpticsAPM::Config[:action_controller][:collect_backtraces] = true
|
|
455
|
+
|
|
456
|
+
uri = URI.join(ENV['TEST_DB_URI'], '/hello/world')
|
|
457
|
+
r = Net::HTTP.get_response(uri)
|
|
458
|
+
|
|
459
|
+
traces = get_all_traces
|
|
460
|
+
|
|
461
|
+
traces.count.must_equal 8
|
|
462
|
+
unless defined?(JRUBY_VERSION)
|
|
463
|
+
# We don't test this under JRuby because the Java instrumentation
|
|
464
|
+
# for the DB drivers doesn't use our test reporter hence we won't
|
|
465
|
+
# see all trace events. :-( To be improved.
|
|
466
|
+
valid_edges?(traces).must_equal true
|
|
467
|
+
end
|
|
468
|
+
validate_outer_layers(traces, 'rack')
|
|
469
|
+
|
|
470
|
+
traces[0]['Layer'].must_equal "rack"
|
|
471
|
+
traces[0]['Label'].must_equal "entry"
|
|
472
|
+
traces[0]['URL'].must_equal "/hello/world"
|
|
473
|
+
|
|
474
|
+
traces[1]['Layer'].must_equal "rack"
|
|
475
|
+
traces[1]['Label'].must_equal "info"
|
|
476
|
+
|
|
477
|
+
traces[2]['Layer'].must_equal "rails"
|
|
478
|
+
traces[2]['Label'].must_equal "entry"
|
|
479
|
+
|
|
480
|
+
traces[3]['Label'].must_equal "info"
|
|
481
|
+
traces[3]['Controller'].must_equal "HelloController"
|
|
482
|
+
traces[3]['Action'].must_equal "world"
|
|
483
|
+
traces[3].key?('Backtrace').must_equal true
|
|
484
|
+
|
|
485
|
+
traces[4]['Layer'].must_equal "actionview"
|
|
486
|
+
traces[4]['Label'].must_equal "entry"
|
|
487
|
+
|
|
488
|
+
traces[5]['Layer'].must_equal "actionview"
|
|
489
|
+
traces[5]['Label'].must_equal "exit"
|
|
490
|
+
|
|
491
|
+
traces[6]['Layer'].must_equal "rails"
|
|
492
|
+
traces[6]['Label'].must_equal "exit"
|
|
493
|
+
|
|
494
|
+
traces[7]['Layer'].must_equal "rack"
|
|
495
|
+
traces[7]['Label'].must_equal "exit"
|
|
496
|
+
|
|
497
|
+
# Validate the existence of the response header
|
|
498
|
+
r.header.key?('X-Trace').must_equal true
|
|
499
|
+
r.header['X-Trace'].must_equal traces[7]['X-Trace']
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
it "should NOT collect backtraces when false" do
|
|
503
|
+
|
|
504
|
+
AppOpticsAPM::Config[:action_controller][:collect_backtraces] = false
|
|
505
|
+
|
|
506
|
+
uri = URI.parse("#{ENV['TEST_DB_URI']}/hello/world")
|
|
507
|
+
r = Net::HTTP.get_response(uri)
|
|
508
|
+
|
|
509
|
+
traces = get_all_traces
|
|
510
|
+
|
|
511
|
+
traces.count.must_equal 8
|
|
512
|
+
unless defined?(JRUBY_VERSION)
|
|
513
|
+
# We don't test this under JRuby because the Java instrumentation
|
|
514
|
+
# for the DB drivers doesn't use our test reporter hence we won't
|
|
515
|
+
# see all trace events. :-( To be improved.
|
|
516
|
+
valid_edges?(traces).must_equal true
|
|
517
|
+
end
|
|
518
|
+
validate_outer_layers(traces, 'rack')
|
|
519
|
+
|
|
520
|
+
traces[0]['Layer'].must_equal "rack"
|
|
521
|
+
traces[0]['Label'].must_equal "entry"
|
|
522
|
+
traces[0]['URL'].must_equal "/hello/world"
|
|
523
|
+
|
|
524
|
+
traces[1]['Layer'].must_equal "rack"
|
|
525
|
+
traces[1]['Label'].must_equal "info"
|
|
526
|
+
|
|
527
|
+
traces[2]['Layer'].must_equal "rails"
|
|
528
|
+
traces[2]['Label'].must_equal "entry"
|
|
529
|
+
|
|
530
|
+
traces[3]['Label'].must_equal "info"
|
|
531
|
+
traces[3]['Controller'].must_equal "HelloController"
|
|
532
|
+
traces[3]['Action'].must_equal "world"
|
|
533
|
+
traces[3].key?('Backtrace').must_equal false
|
|
534
|
+
|
|
535
|
+
traces[4]['Layer'].must_equal "actionview"
|
|
536
|
+
traces[4]['Label'].must_equal "entry"
|
|
537
|
+
|
|
538
|
+
traces[5]['Layer'].must_equal "actionview"
|
|
539
|
+
traces[5]['Label'].must_equal "exit"
|
|
540
|
+
|
|
541
|
+
traces[6]['Layer'].must_equal "rails"
|
|
542
|
+
traces[6]['Label'].must_equal "exit"
|
|
543
|
+
|
|
544
|
+
traces[7]['Layer'].must_equal "rack"
|
|
545
|
+
traces[7]['Label'].must_equal "exit"
|
|
546
|
+
|
|
547
|
+
# Validate the existence of the response header
|
|
548
|
+
r.header.key?('X-Trace').must_equal true
|
|
549
|
+
r.header['X-Trace'].must_equal traces[7]['X-Trace']
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
require_relative "rails_shared_tests"
|
|
553
|
+
end
|
|
554
|
+
end
|