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,466 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
module AppOpticsAPM
|
|
7
|
+
module Inst
|
|
8
|
+
##
|
|
9
|
+
# Moped
|
|
10
|
+
#
|
|
11
|
+
module Moped
|
|
12
|
+
FLAVOR = :mongodb
|
|
13
|
+
|
|
14
|
+
# Moped::Database
|
|
15
|
+
DB_OPS = [:command, :drop].freeze
|
|
16
|
+
|
|
17
|
+
# Moped::Indexes
|
|
18
|
+
INDEX_OPS = [:create, :drop].freeze
|
|
19
|
+
|
|
20
|
+
# Moped::Query
|
|
21
|
+
QUERY_OPS = [:count, :sort, :limit, :distinct, :update, :update_all, :upsert,
|
|
22
|
+
:explain, :modify, :remove, :remove_all].freeze
|
|
23
|
+
|
|
24
|
+
# Moped::Collection
|
|
25
|
+
COLLECTION_OPS = [:drop, :find, :indexes, :insert, :aggregate].freeze
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# remote_host
|
|
29
|
+
#
|
|
30
|
+
# This utility method converts the server into a host:port
|
|
31
|
+
# pair for reporting
|
|
32
|
+
#
|
|
33
|
+
def remote_host(server)
|
|
34
|
+
if ::Moped::VERSION < '2.0.0'
|
|
35
|
+
server
|
|
36
|
+
else
|
|
37
|
+
"#{server.address.host}:#{server.address.port}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# MopedDatabase
|
|
44
|
+
#
|
|
45
|
+
module MopedDatabase
|
|
46
|
+
include AppOpticsAPM::Inst::Moped
|
|
47
|
+
|
|
48
|
+
def self.included(klass)
|
|
49
|
+
AppOpticsAPM::Inst::Moped::DB_OPS.each do |m|
|
|
50
|
+
::AppOpticsAPM::Util.method_alias(klass, m)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def extract_trace_details(op)
|
|
55
|
+
report_kvs = {}
|
|
56
|
+
report_kvs[:Flavor] = AppOpticsAPM::Inst::Moped::FLAVOR
|
|
57
|
+
# FIXME: We're only grabbing the first of potentially multiple servers here
|
|
58
|
+
report_kvs[:RemoteHost] = remote_host(session.cluster.seeds.first)
|
|
59
|
+
report_kvs[:Database] = name
|
|
60
|
+
report_kvs[:QueryOp] = op.to_s
|
|
61
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:moped][:collect_backtraces]
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
64
|
+
ensure
|
|
65
|
+
return report_kvs
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def command_with_appoptics(command)
|
|
69
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.layer_op && command.key?(:mapreduce)
|
|
70
|
+
begin
|
|
71
|
+
report_kvs = extract_trace_details(:map_reduce)
|
|
72
|
+
report_kvs[:Map_Function] = command[:map]
|
|
73
|
+
report_kvs[:Reduce_Function] = command[:reduce]
|
|
74
|
+
rescue => e
|
|
75
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
79
|
+
command_without_appoptics(command)
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
command_without_appoptics(command)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def drop_with_appoptics
|
|
87
|
+
return drop_without_appoptics unless AppOpticsAPM.tracing?
|
|
88
|
+
|
|
89
|
+
report_kvs = extract_trace_details(:drop_database)
|
|
90
|
+
|
|
91
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
92
|
+
drop_without_appoptics
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
##
|
|
98
|
+
# MopedIndexes
|
|
99
|
+
#
|
|
100
|
+
module MopedIndexes
|
|
101
|
+
include AppOpticsAPM::Inst::Moped
|
|
102
|
+
|
|
103
|
+
def self.included(klass)
|
|
104
|
+
AppOpticsAPM::Inst::Moped::INDEX_OPS.each do |m|
|
|
105
|
+
::AppOpticsAPM::Util.method_alias(klass, m)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def extract_trace_details(op)
|
|
110
|
+
report_kvs = {}
|
|
111
|
+
report_kvs[:Flavor] = AppOpticsAPM::Inst::Moped::FLAVOR
|
|
112
|
+
|
|
113
|
+
# FIXME: We're only grabbing the first of potentially multiple servers here
|
|
114
|
+
first = database.session.cluster.seeds.first
|
|
115
|
+
if ::Moped::VERSION < '2.0.0'
|
|
116
|
+
report_kvs[:RemoteHost] = first
|
|
117
|
+
else
|
|
118
|
+
report_kvs[:RemoteHost] = "#{first.address.host}:#{first.address.port}"
|
|
119
|
+
end
|
|
120
|
+
report_kvs[:Database] = database.name
|
|
121
|
+
report_kvs[:QueryOp] = op.to_s
|
|
122
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:moped][:collect_backtraces]
|
|
123
|
+
rescue StandardError => e
|
|
124
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
125
|
+
ensure
|
|
126
|
+
return report_kvs
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def create_with_appoptics(key, options = {})
|
|
130
|
+
return create_without_appoptics(key, options) unless AppOpticsAPM.tracing?
|
|
131
|
+
|
|
132
|
+
begin
|
|
133
|
+
# We report :create_index here to be consistent
|
|
134
|
+
# with other mongo implementations
|
|
135
|
+
report_kvs = extract_trace_details(:create_index)
|
|
136
|
+
report_kvs[:Key] = key.to_json
|
|
137
|
+
report_kvs[:Options] = options.to_json
|
|
138
|
+
rescue StandardError => e
|
|
139
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs, :create_index) do
|
|
143
|
+
create_without_appoptics(key, options = {})
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def drop_with_appoptics(key = nil)
|
|
148
|
+
return drop_without_appoptics(key) unless AppOpticsAPM.tracing?
|
|
149
|
+
|
|
150
|
+
begin
|
|
151
|
+
# We report :drop_indexes here to be consistent
|
|
152
|
+
# with other mongo implementations
|
|
153
|
+
report_kvs = extract_trace_details(:drop_indexes)
|
|
154
|
+
report_kvs[:Key] = key.nil? ? :all : key.to_json
|
|
155
|
+
rescue StandardError => e
|
|
156
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
160
|
+
drop_without_appoptics(key = nil)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
##
|
|
166
|
+
# MopedQuery
|
|
167
|
+
#
|
|
168
|
+
module MopedQuery
|
|
169
|
+
include AppOpticsAPM::Inst::Moped
|
|
170
|
+
|
|
171
|
+
def self.included(klass)
|
|
172
|
+
AppOpticsAPM::Inst::Moped::QUERY_OPS.each do |m|
|
|
173
|
+
::AppOpticsAPM::Util.method_alias(klass, m)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def extract_trace_details(op)
|
|
178
|
+
report_kvs = {}
|
|
179
|
+
report_kvs[:Flavor] = AppOpticsAPM::Inst::Moped::FLAVOR
|
|
180
|
+
# FIXME: We're only grabbing the first of potentially multiple servers here
|
|
181
|
+
first = collection.database.session.cluster.seeds.first
|
|
182
|
+
report_kvs[:RemoteHost] = remote_host(first)
|
|
183
|
+
report_kvs[:Database] = collection.database.name
|
|
184
|
+
report_kvs[:Collection] = collection.name
|
|
185
|
+
report_kvs[:QueryOp] = op.to_s
|
|
186
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:moped][:collect_backtraces]
|
|
187
|
+
rescue StandardError => e
|
|
188
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
189
|
+
ensure
|
|
190
|
+
return report_kvs
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def count_with_appoptics
|
|
194
|
+
return count_without_appoptics unless AppOpticsAPM.tracing?
|
|
195
|
+
|
|
196
|
+
begin
|
|
197
|
+
report_kvs = extract_trace_details(:count)
|
|
198
|
+
report_kvs[:Query] = selector.empty? ? :all : selector.to_json
|
|
199
|
+
rescue StandardError => e
|
|
200
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
204
|
+
count_without_appoptics
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def sort_with_appoptics(sort)
|
|
209
|
+
return sort_without_appoptics(sort) unless AppOpticsAPM.tracing?
|
|
210
|
+
|
|
211
|
+
begin
|
|
212
|
+
report_kvs = extract_trace_details(:sort)
|
|
213
|
+
report_kvs[:Query] = selector.empty? ? :all : selector.to_json
|
|
214
|
+
report_kvs[:Order] = sort.to_s
|
|
215
|
+
rescue StandardError => e
|
|
216
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
220
|
+
sort_without_appoptics(sort)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def limit_with_appoptics(limit)
|
|
225
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?(:explain)
|
|
226
|
+
begin
|
|
227
|
+
report_kvs = extract_trace_details(:limit)
|
|
228
|
+
report_kvs[:Query] = selector.empty? ? :all : selector.to_json
|
|
229
|
+
report_kvs[:Limit] = limit.to_s
|
|
230
|
+
rescue StandardError => e
|
|
231
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
235
|
+
limit_without_appoptics(limit)
|
|
236
|
+
end
|
|
237
|
+
else
|
|
238
|
+
limit_without_appoptics(limit)
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def distinct_with_appoptics(key)
|
|
243
|
+
return distinct_without_appoptics(key) unless AppOpticsAPM.tracing?
|
|
244
|
+
|
|
245
|
+
begin
|
|
246
|
+
report_kvs = extract_trace_details(:distinct)
|
|
247
|
+
report_kvs[:Query] = selector.empty? ? :all : selector.to_json
|
|
248
|
+
report_kvs[:Key] = key.to_s
|
|
249
|
+
rescue StandardError => e
|
|
250
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
254
|
+
distinct_without_appoptics(key)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def update_with_appoptics(change, flags = nil)
|
|
259
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?([:update_all, :upsert])
|
|
260
|
+
begin
|
|
261
|
+
report_kvs = extract_trace_details(:update)
|
|
262
|
+
report_kvs[:Flags] = flags.to_s if flags
|
|
263
|
+
report_kvs[:Update_Document] = change.to_json
|
|
264
|
+
rescue StandardError => e
|
|
265
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
269
|
+
update_without_appoptics(change, flags)
|
|
270
|
+
end
|
|
271
|
+
else
|
|
272
|
+
update_without_appoptics(change, flags)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def update_all_with_appoptics(change)
|
|
277
|
+
return update_all_without_appoptics(change) unless AppOpticsAPM.tracing?
|
|
278
|
+
|
|
279
|
+
begin
|
|
280
|
+
report_kvs = extract_trace_details(:update_all)
|
|
281
|
+
report_kvs[:Update_Document] = change.to_json
|
|
282
|
+
rescue StandardError => e
|
|
283
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs, :update_all) do
|
|
287
|
+
update_all_without_appoptics(change)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def upsert_with_appoptics(change)
|
|
292
|
+
return upsert_without_appoptics(change) unless AppOpticsAPM.tracing?
|
|
293
|
+
|
|
294
|
+
begin
|
|
295
|
+
report_kvs = extract_trace_details(:upsert)
|
|
296
|
+
report_kvs[:Query] = selector.to_json
|
|
297
|
+
report_kvs[:Update_Document] = change.to_json
|
|
298
|
+
rescue StandardError => e
|
|
299
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs, :upsert) do
|
|
303
|
+
upsert_without_appoptics(change)
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def explain_with_appoptics
|
|
308
|
+
return explain_without_appoptics unless AppOpticsAPM.tracing?
|
|
309
|
+
|
|
310
|
+
begin
|
|
311
|
+
report_kvs = extract_trace_details(:explain)
|
|
312
|
+
report_kvs[:Query] = selector.empty? ? :all : selector.to_json
|
|
313
|
+
rescue StandardError => e
|
|
314
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs, :explain) do
|
|
318
|
+
explain_without_appoptics
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def modify_with_appoptics(change, options = {})
|
|
323
|
+
return modify_without_appoptics(change, options) unless AppOpticsAPM.tracing?
|
|
324
|
+
|
|
325
|
+
begin
|
|
326
|
+
report_kvs = extract_trace_details(:modify)
|
|
327
|
+
report_kvs[:Update_Document] = selector.empty? ? :all : selector.to_json
|
|
328
|
+
report_kvs[:Change] = change.to_json
|
|
329
|
+
report_kvs[:Options] = options.to_json
|
|
330
|
+
rescue StandardError => e
|
|
331
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
335
|
+
modify_without_appoptics(change, options)
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def remove_with_appoptics
|
|
340
|
+
return remove_without_appoptics unless AppOpticsAPM.tracing?
|
|
341
|
+
|
|
342
|
+
begin
|
|
343
|
+
report_kvs = extract_trace_details(:remove)
|
|
344
|
+
report_kvs[:Query] = selector.to_json
|
|
345
|
+
rescue StandardError => e
|
|
346
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
350
|
+
remove_without_appoptics
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def remove_all_with_appoptics
|
|
355
|
+
return remove_all_without_appoptics unless AppOpticsAPM.tracing?
|
|
356
|
+
|
|
357
|
+
begin
|
|
358
|
+
report_kvs = extract_trace_details(:remove_all)
|
|
359
|
+
report_kvs[:Query] = selector.to_json
|
|
360
|
+
rescue StandardError => e
|
|
361
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
365
|
+
remove_all_without_appoptics
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
##
|
|
371
|
+
# MopedCollection
|
|
372
|
+
#
|
|
373
|
+
module MopedCollection
|
|
374
|
+
include AppOpticsAPM::Inst::Moped
|
|
375
|
+
|
|
376
|
+
def self.included(klass)
|
|
377
|
+
AppOpticsAPM::Inst::Moped::COLLECTION_OPS.each do |m|
|
|
378
|
+
::AppOpticsAPM::Util.method_alias(klass, m)
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def extract_trace_details(op)
|
|
383
|
+
report_kvs = {}
|
|
384
|
+
report_kvs[:Flavor] = AppOpticsAPM::Inst::Moped::FLAVOR
|
|
385
|
+
# FIXME: We're only grabbing the first of potentially multiple servers here
|
|
386
|
+
report_kvs[:RemoteHost] = remote_host(database.session.cluster.seeds.first)
|
|
387
|
+
report_kvs[:Database] = database.name
|
|
388
|
+
report_kvs[:Collection] = name
|
|
389
|
+
report_kvs[:QueryOp] = op.to_s
|
|
390
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:moped][:collect_backtraces]
|
|
391
|
+
rescue StandardError => e
|
|
392
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
393
|
+
ensure
|
|
394
|
+
return report_kvs
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def drop_with_appoptics
|
|
398
|
+
return drop_without_appoptics unless AppOpticsAPM.tracing?
|
|
399
|
+
|
|
400
|
+
# We report :drop_collection here to be consistent
|
|
401
|
+
# with other mongo implementations
|
|
402
|
+
report_kvs = extract_trace_details(:drop_collection)
|
|
403
|
+
|
|
404
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
405
|
+
drop_without_appoptics
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def find_with_appoptics(selector = {})
|
|
410
|
+
return find_without_appoptics(selector) unless AppOpticsAPM.tracing?
|
|
411
|
+
|
|
412
|
+
begin
|
|
413
|
+
report_kvs = extract_trace_details(:find)
|
|
414
|
+
report_kvs[:Query] = selector.empty? ? 'all' : selector.to_json
|
|
415
|
+
rescue StandardError => e
|
|
416
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
420
|
+
find_without_appoptics(selector)
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def indexes_with_appoptics
|
|
425
|
+
return indexes_without_appoptics unless AppOpticsAPM.tracing?
|
|
426
|
+
|
|
427
|
+
report_kvs = extract_trace_details(:indexes)
|
|
428
|
+
|
|
429
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
430
|
+
indexes_without_appoptics
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def insert_with_appoptics(documents, flags = nil)
|
|
435
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?(:create_index)
|
|
436
|
+
report_kvs = extract_trace_details(:insert)
|
|
437
|
+
|
|
438
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
439
|
+
insert_without_appoptics(documents, flags)
|
|
440
|
+
end
|
|
441
|
+
else
|
|
442
|
+
insert_without_appoptics(documents, flags)
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def aggregate_with_appoptics(*pipeline)
|
|
447
|
+
return aggregate_without_appoptics(*pipeline) unless AppOpticsAPM.tracing?
|
|
448
|
+
|
|
449
|
+
report_kvs = extract_trace_details(:aggregate)
|
|
450
|
+
report_kvs[:Query] = pipeline
|
|
451
|
+
|
|
452
|
+
AppOpticsAPM::API.trace(:mongo, report_kvs) do
|
|
453
|
+
aggregate_without_appoptics(pipeline)
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
if defined?(::Moped) && AppOpticsAPM::Config[:moped][:enabled]
|
|
461
|
+
::AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting moped' if AppOpticsAPM::Config[:verbose]
|
|
462
|
+
::AppOpticsAPM::Util.send_include(::Moped::Database, ::AppOpticsAPM::Inst::MopedDatabase)
|
|
463
|
+
::AppOpticsAPM::Util.send_include(::Moped::Collection, ::AppOpticsAPM::Inst::MopedCollection)
|
|
464
|
+
::AppOpticsAPM::Util.send_include(::Moped::Query, ::AppOpticsAPM::Inst::MopedQuery)
|
|
465
|
+
::AppOpticsAPM::Util.send_include(::Moped::Indexes, ::AppOpticsAPM::Inst::MopedIndexes)
|
|
466
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'cgi'
|
|
6
|
+
|
|
7
|
+
module AppOpticsAPM
|
|
8
|
+
##
|
|
9
|
+
# AppOpticsAPM::Rack
|
|
10
|
+
#
|
|
11
|
+
# The AppOpticsAPM::Rack middleware used to sample a subset of incoming
|
|
12
|
+
# requests for instrumentation and reporting. Tracing context can
|
|
13
|
+
# be received here (via the X-Trace HTTP header) or initiated here
|
|
14
|
+
# based on configured tracing mode.
|
|
15
|
+
#
|
|
16
|
+
# After the rack layer passes on to the following layers (Rails, Sinatra,
|
|
17
|
+
# Padrino, Grape), then the instrumentation downstream will
|
|
18
|
+
# automatically detect whether this is a sampled request or not
|
|
19
|
+
# and act accordingly. (to instrument or not)
|
|
20
|
+
#
|
|
21
|
+
class Rack
|
|
22
|
+
attr_reader :app
|
|
23
|
+
|
|
24
|
+
def initialize(app)
|
|
25
|
+
@app = app
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def collect(req, env)
|
|
29
|
+
report_kvs = {}
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
report_kvs[:'HTTP-Host'] = req.host
|
|
33
|
+
report_kvs[:Port] = req.port
|
|
34
|
+
report_kvs[:Proto] = req.scheme
|
|
35
|
+
report_kvs[:Method] = req.request_method
|
|
36
|
+
report_kvs[:AJAX] = true if req.xhr?
|
|
37
|
+
report_kvs[:ClientIP] = req.ip
|
|
38
|
+
|
|
39
|
+
if AppOpticsAPM::Config[:rack][:log_args]
|
|
40
|
+
report_kvs[:'Query-String'] = ::CGI.unescape(req.query_string) unless req.query_string.empty?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Report any request queue'ing headers. Report as 'Request-Start' or the summed Queue-Time
|
|
44
|
+
report_kvs[:'Request-Start'] = env['HTTP_X_REQUEST_START'] if env.key?('HTTP_X_REQUEST_START')
|
|
45
|
+
report_kvs[:'Request-Start'] = env['HTTP_X_QUEUE_START'] if env.key?('HTTP_X_QUEUE_START')
|
|
46
|
+
report_kvs[:'Queue-Time'] = env['HTTP_X_QUEUE_TIME'] if env.key?('HTTP_X_QUEUE_TIME')
|
|
47
|
+
|
|
48
|
+
report_kvs[:'Forwarded-For'] = env['HTTP_X_FORWARDED_FOR'] if env.key?('HTTP_X_FORWARDED_FOR')
|
|
49
|
+
report_kvs[:'Forwarded-Host'] = env['HTTP_X_FORWARDED_HOST'] if env.key?('HTTP_X_FORWARDED_HOST')
|
|
50
|
+
report_kvs[:'Forwarded-Proto'] = env['HTTP_X_FORWARDED_PROTO'] if env.key?('HTTP_X_FORWARDED_PROTO')
|
|
51
|
+
report_kvs[:'Forwarded-Port'] = env['HTTP_X_FORWARDED_PORT'] if env.key?('HTTP_X_FORWARDED_PORT')
|
|
52
|
+
|
|
53
|
+
report_kvs[:'Ruby.AppOpticsAPM.Version'] = ::AppOpticsAPM::Version::STRING
|
|
54
|
+
report_kvs[:ProcessID] = Process.pid
|
|
55
|
+
report_kvs[:ThreadID] = Thread.current.to_s[/0x\w*/]
|
|
56
|
+
rescue StandardError => e
|
|
57
|
+
# Discard any potential exceptions. Debug log and report whatever we can.
|
|
58
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] Rack KV collection error: #{e.inspect}"
|
|
59
|
+
end
|
|
60
|
+
report_kvs
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def call(env)
|
|
64
|
+
start = Time.now
|
|
65
|
+
status = 500
|
|
66
|
+
req = ::Rack::Request.new(env)
|
|
67
|
+
req_url = req.url # saving it here because rails3.2 overrides it when there is a 500 error
|
|
68
|
+
|
|
69
|
+
# In the case of nested Ruby apps such as Grape inside of Rails
|
|
70
|
+
# or Grape inside of Grape, each app has it's own instance
|
|
71
|
+
# of rack middleware. We avoid tracing rack more than once and
|
|
72
|
+
# instead start instrumenting from the first rack pass.
|
|
73
|
+
if AppOpticsAPM.tracing? && AppOpticsAPM.layer == :rack
|
|
74
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/rack] Rack skipped!"
|
|
75
|
+
return @app.call(env)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
begin
|
|
79
|
+
report_kvs = {}
|
|
80
|
+
|
|
81
|
+
report_kvs[:URL] = AppOpticsAPM::Config[:rack][:log_args] ? ::CGI.unescape(req.fullpath) : ::CGI.unescape(req.path)
|
|
82
|
+
|
|
83
|
+
# Check for and validate X-Trace request header to pick up tracing context
|
|
84
|
+
xtrace = env.is_a?(Hash) ? env['HTTP_X_TRACE'] : nil
|
|
85
|
+
xtrace_header = AppOpticsAPM::XTrace.valid?(xtrace) ? xtrace : nil
|
|
86
|
+
|
|
87
|
+
# Under JRuby, JAppOpticsAPM may have already started a trace. Make note of this
|
|
88
|
+
# if so and don't clear context on log_end (see appoptics_apm/api/logging.rb)
|
|
89
|
+
AppOpticsAPM.has_incoming_context = AppOpticsAPM.tracing?
|
|
90
|
+
AppOpticsAPM.has_xtrace_header = xtrace_header
|
|
91
|
+
AppOpticsAPM.is_continued_trace = AppOpticsAPM.has_incoming_context || AppOpticsAPM.has_xtrace_header
|
|
92
|
+
|
|
93
|
+
xtrace = AppOpticsAPM::API.log_start(:rack, xtrace_header, report_kvs)
|
|
94
|
+
|
|
95
|
+
# We only trace a subset of requests based off of sample rate so if
|
|
96
|
+
# AppOpticsAPM::API.log_start really did start a trace, we act accordingly here.
|
|
97
|
+
if AppOpticsAPM.tracing?
|
|
98
|
+
report_kvs = collect(req, env)
|
|
99
|
+
|
|
100
|
+
# We log an info event with the HTTP KVs found in AppOpticsAPM::Rack.collect
|
|
101
|
+
# This is done here so in the case of stacks that try/catch/abort
|
|
102
|
+
# (looking at you Grape) we're sure the KVs get reported now as
|
|
103
|
+
# this code may not be returned to later.
|
|
104
|
+
AppOpticsAPM::API.log_info(:rack, report_kvs)
|
|
105
|
+
|
|
106
|
+
status, headers, response = @app.call(env)
|
|
107
|
+
|
|
108
|
+
xtrace = AppOpticsAPM::API.log_end(:rack, :Status => status)
|
|
109
|
+
|
|
110
|
+
else
|
|
111
|
+
status, headers, response = @app.call(env)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
[status, headers, response]
|
|
115
|
+
rescue Exception => e
|
|
116
|
+
# it is ok to rescue Exception here because we are reraising it (we just need a chance to log_end)
|
|
117
|
+
if AppOpticsAPM.tracing?
|
|
118
|
+
AppOpticsAPM::API.log_exception(:rack, e)
|
|
119
|
+
xtrace = AppOpticsAPM::API.log_end(:rack, :Status => 500, 'TransactionName' => transaction_name(env))
|
|
120
|
+
end
|
|
121
|
+
raise
|
|
122
|
+
ensure
|
|
123
|
+
if headers && AppOpticsAPM::XTrace.valid?(xtrace)
|
|
124
|
+
unless defined?(JRUBY_VERSION) && AppOpticsAPM.is_continued_trace?
|
|
125
|
+
headers['X-Trace'] = xtrace if headers.is_a?(Hash)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
ensure
|
|
130
|
+
unless ::AppOpticsAPM::Util.static_asset?(env['PATH_INFO'])
|
|
131
|
+
status = status.to_i
|
|
132
|
+
error = status.between?(500,599) ? 1 : 0
|
|
133
|
+
duration =(1000 * 1000 * (Time.now - start)).round(0)
|
|
134
|
+
AppOpticsAPM::Span.createHttpSpan(transaction_name(env), req_url, duration, status, req.request_method, error)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
private
|
|
139
|
+
|
|
140
|
+
def transaction_name(env)
|
|
141
|
+
if env['appoptics_apm.controller'] || env['appoptics_apm.action']
|
|
142
|
+
[env['appoptics_apm.controller'], env['appoptics_apm.action']].join('.')
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|