appoptics_apm-zearn 4.13.1
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/.dockerignore +5 -0
- data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
- data/.github/workflows/build_and_release_gem.yml +103 -0
- data/.github/workflows/build_for_packagecloud.yml +70 -0
- data/.github/workflows/docker-images.yml +47 -0
- data/.github/workflows/run_cpluplus_tests.yml +73 -0
- data/.github/workflows/run_tests.yml +168 -0
- data/.github/workflows/scripts/test_install.rb +23 -0
- data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
- data/.github/workflows/test_on_4_linux.yml +159 -0
- data/.gitignore +36 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +130 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Gemfile +14 -0
- data/LICENSE +202 -0
- data/README.md +393 -0
- data/appoptics_apm.gemspec +70 -0
- data/bin/appoptics_apm_config +15 -0
- data/examples/prepend.rb +13 -0
- data/examples/sdk_examples.rb +158 -0
- data/ext/oboe_metal/README.md +69 -0
- data/ext/oboe_metal/extconf.rb +151 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/noop/noop.c +8 -0
- data/ext/oboe_metal/src/README.md +6 -0
- data/ext/oboe_metal/src/VERSION +2 -0
- data/ext/oboe_metal/src/bson/bson.h +220 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/frames.cc +246 -0
- data/ext/oboe_metal/src/frames.h +40 -0
- data/ext/oboe_metal/src/init_appoptics_apm.cc +21 -0
- data/ext/oboe_metal/src/logging.cc +95 -0
- data/ext/oboe_metal/src/logging.h +35 -0
- data/ext/oboe_metal/src/oboe.h +1156 -0
- data/ext/oboe_metal/src/oboe_api.cpp +652 -0
- data/ext/oboe_metal/src/oboe_api.hpp +431 -0
- data/ext/oboe_metal/src/oboe_debug.h +59 -0
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +7329 -0
- data/ext/oboe_metal/src/profiling.cc +435 -0
- data/ext/oboe_metal/src/profiling.h +78 -0
- data/ext/oboe_metal/test/CMakeLists.txt +53 -0
- data/ext/oboe_metal/test/FindGMock.cmake +43 -0
- data/ext/oboe_metal/test/README.md +56 -0
- data/ext/oboe_metal/test/frames_test.cc +164 -0
- data/ext/oboe_metal/test/profiling_test.cc +93 -0
- data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
- data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
- data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
- data/ext/oboe_metal/test/test.h +11 -0
- data/ext/oboe_metal/test/test_main.cc +32 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm/api/layerinit.rb +41 -0
- data/lib/appoptics_apm/api/logging.rb +381 -0
- data/lib/appoptics_apm/api/memcache.rb +37 -0
- data/lib/appoptics_apm/api/metrics.rb +63 -0
- data/lib/appoptics_apm/api/tracing.rb +57 -0
- data/lib/appoptics_apm/api/util.rb +120 -0
- data/lib/appoptics_apm/api.rb +21 -0
- data/lib/appoptics_apm/base.rb +231 -0
- data/lib/appoptics_apm/config.rb +299 -0
- data/lib/appoptics_apm/frameworks/grape.rb +98 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +78 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -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_controller6.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 +88 -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 +29 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +114 -0
- data/lib/appoptics_apm/frameworks/rails/inst/logger_formatters.rb +27 -0
- data/lib/appoptics_apm/frameworks/rails.rb +100 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +96 -0
- data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
- data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
- data/lib/appoptics_apm/inst/curb.rb +332 -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 +101 -0
- data/lib/appoptics_apm/inst/excon.rb +125 -0
- data/lib/appoptics_apm/inst/faraday.rb +106 -0
- data/lib/appoptics_apm/inst/graphql.rb +240 -0
- data/lib/appoptics_apm/inst/grpc_client.rb +159 -0
- data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
- data/lib/appoptics_apm/inst/http.rb +81 -0
- data/lib/appoptics_apm/inst/httpclient.rb +174 -0
- data/lib/appoptics_apm/inst/logger_formatter.rb +50 -0
- data/lib/appoptics_apm/inst/logging_log_event.rb +28 -0
- data/lib/appoptics_apm/inst/lumberjack_formatter.rb +13 -0
- data/lib/appoptics_apm/inst/memcached.rb +86 -0
- data/lib/appoptics_apm/inst/mongo.rb +246 -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 +182 -0
- data/lib/appoptics_apm/inst/rack_cache.rb +35 -0
- data/lib/appoptics_apm/inst/redis.rb +274 -0
- data/lib/appoptics_apm/inst/resque.rb +151 -0
- data/lib/appoptics_apm/inst/rest-client.rb +48 -0
- data/lib/appoptics_apm/inst/sequel.rb +178 -0
- data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
- data/lib/appoptics_apm/inst/sidekiq-worker.rb +66 -0
- data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
- data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
- data/lib/appoptics_apm/instrumentation.rb +22 -0
- data/lib/appoptics_apm/loading.rb +65 -0
- data/lib/appoptics_apm/logger.rb +14 -0
- data/lib/appoptics_apm/noop/README.md +9 -0
- data/lib/appoptics_apm/noop/context.rb +27 -0
- data/lib/appoptics_apm/noop/metadata.rb +25 -0
- data/lib/appoptics_apm/noop/profiling.rb +21 -0
- data/lib/appoptics_apm/oboe_init_options.rb +211 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/sdk/current_trace.rb +77 -0
- data/lib/appoptics_apm/sdk/custom_metrics.rb +94 -0
- data/lib/appoptics_apm/sdk/logging.rb +37 -0
- data/lib/appoptics_apm/sdk/tracing.rb +434 -0
- data/lib/appoptics_apm/support/profiling.rb +18 -0
- data/lib/appoptics_apm/support/transaction_metrics.rb +67 -0
- data/lib/appoptics_apm/support/transaction_settings.rb +219 -0
- data/lib/appoptics_apm/support/x_trace_options.rb +110 -0
- data/lib/appoptics_apm/support_report.rb +119 -0
- data/lib/appoptics_apm/test.rb +95 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +326 -0
- data/lib/appoptics_apm/version.rb +16 -0
- data/lib/appoptics_apm/xtrace.rb +115 -0
- data/lib/appoptics_apm.rb +77 -0
- data/lib/joboe_metal.rb +212 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +172 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +47 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +425 -0
- data/log/.keep +0 -0
- data/yardoc_frontpage.md +26 -0
- metadata +231 -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) && !AppOpticsAPM.tracing_layer_op?(: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,182 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
require 'cgi'
|
6
|
+
|
7
|
+
if AppOpticsAPM.loaded
|
8
|
+
module AppOpticsAPM
|
9
|
+
##
|
10
|
+
# AppOpticsAPM::Rack
|
11
|
+
#
|
12
|
+
# The AppOpticsAPM::Rack middleware used to sample a subset of incoming
|
13
|
+
# requests for instrumentation and reporting. Tracing context can
|
14
|
+
# be received here (via the X-Trace HTTP header) or initiated here
|
15
|
+
# based on configured tracing mode.
|
16
|
+
#
|
17
|
+
# After the rack layer passes on to the following layers (Rails, Sinatra,
|
18
|
+
# Padrino, Grape), then the instrumentation downstream will
|
19
|
+
# automatically detect whether this is a sampled request or not
|
20
|
+
# and act accordingly.
|
21
|
+
#
|
22
|
+
class Rack
|
23
|
+
attr_reader :app
|
24
|
+
|
25
|
+
def initialize(app)
|
26
|
+
@app = app
|
27
|
+
end
|
28
|
+
|
29
|
+
def call(env)
|
30
|
+
|
31
|
+
# In the case of nested Ruby apps such as Grape inside of Rails
|
32
|
+
# or Grape inside of Grape, each app has it's own instance
|
33
|
+
# of rack middleware. We want to avoid tracing rack more than once
|
34
|
+
return @app.call(env) if AppOpticsAPM.tracing? && AppOpticsAPM.layer == :rack
|
35
|
+
|
36
|
+
incoming = AppOpticsAPM::Context.isValid
|
37
|
+
AppOpticsAPM.transaction_name = nil
|
38
|
+
|
39
|
+
url = env['PATH_INFO']
|
40
|
+
options = AppOpticsAPM::XTraceOptions.new(env['HTTP_X_TRACE_OPTIONS'], env['HTTP_X_TRACE_OPTIONS_SIGNATURE'])
|
41
|
+
xtrace = AppOpticsAPM::XTrace.valid?(env['HTTP_X_TRACE']) ? (env['HTTP_X_TRACE']) : nil
|
42
|
+
settings = AppOpticsAPM::TransactionSettings.new(url, xtrace, options)
|
43
|
+
profile_spans = AppOpticsAPM::Config['profiling'] == :enabled ? 1 : -1
|
44
|
+
|
45
|
+
response =
|
46
|
+
propagate_xtrace(env, settings, xtrace) do
|
47
|
+
sample(env, settings, options, profile_spans) do
|
48
|
+
AppOpticsAPM::Profiling.run do
|
49
|
+
AppOpticsAPM::TransactionMetrics.metrics(env, settings) do
|
50
|
+
@app.call(env)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end || [500, {}, nil]
|
55
|
+
options.add_response_header(response[1], settings)
|
56
|
+
|
57
|
+
AppOpticsAPM::Context.clear unless incoming
|
58
|
+
response
|
59
|
+
rescue
|
60
|
+
AppOpticsAPM::Context.clear unless incoming
|
61
|
+
raise
|
62
|
+
# can't use ensure for Context.clearing, because the Grape middleware
|
63
|
+
# needs the context in case of an error, it is somewhat convoluted ...
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.noop?
|
67
|
+
false
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def collect(env)
|
73
|
+
req = ::Rack::Request.new(env)
|
74
|
+
report_kvs = {}
|
75
|
+
|
76
|
+
begin
|
77
|
+
report_kvs[:'HTTP-Host'] = req.host
|
78
|
+
report_kvs[:Port] = req.port
|
79
|
+
report_kvs[:Proto] = req.scheme
|
80
|
+
report_kvs[:Method] = req.request_method
|
81
|
+
report_kvs[:AJAX] = true if req.xhr?
|
82
|
+
report_kvs[:ClientIP] = req.ip
|
83
|
+
|
84
|
+
if AppOpticsAPM::Config[:rack][:log_args]
|
85
|
+
report_kvs[:'Query-String'] = ::CGI.unescape(req.query_string) unless req.query_string.empty?
|
86
|
+
end
|
87
|
+
|
88
|
+
report_kvs[:URL] = AppOpticsAPM::Config[:rack][:log_args] ? ::CGI.unescape(req.fullpath) : ::CGI.unescape(req.path)
|
89
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:rack][:collect_backtraces]
|
90
|
+
|
91
|
+
# Report any request queue'ing headers. Report as 'Request-Start' or the summed Queue-Time
|
92
|
+
report_kvs[:'Request-Start'] = env['HTTP_X_REQUEST_START'] if env.key?('HTTP_X_REQUEST_START')
|
93
|
+
report_kvs[:'Request-Start'] = env['HTTP_X_QUEUE_START'] if env.key?('HTTP_X_QUEUE_START')
|
94
|
+
report_kvs[:'Queue-Time'] = env['HTTP_X_QUEUE_TIME'] if env.key?('HTTP_X_QUEUE_TIME')
|
95
|
+
|
96
|
+
report_kvs[:'Forwarded-For'] = env['HTTP_X_FORWARDED_FOR'] if env.key?('HTTP_X_FORWARDED_FOR')
|
97
|
+
report_kvs[:'Forwarded-Host'] = env['HTTP_X_FORWARDED_HOST'] if env.key?('HTTP_X_FORWARDED_HOST')
|
98
|
+
report_kvs[:'Forwarded-Proto'] = env['HTTP_X_FORWARDED_PROTO'] if env.key?('HTTP_X_FORWARDED_PROTO')
|
99
|
+
report_kvs[:'Forwarded-Port'] = env['HTTP_X_FORWARDED_PORT'] if env.key?('HTTP_X_FORWARDED_PORT')
|
100
|
+
|
101
|
+
report_kvs[:'Ruby.AppOptics.Version'] = AppOpticsAPM::Version::STRING
|
102
|
+
report_kvs[:ProcessID] = Process.pid
|
103
|
+
report_kvs[:ThreadID] = Thread.current.to_s[/0x\w*/]
|
104
|
+
rescue StandardError => e
|
105
|
+
# Discard any potential exceptions. Debug log and report whatever we can.
|
106
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] Rack KV collection error: #{e.inspect}"
|
107
|
+
end
|
108
|
+
report_kvs
|
109
|
+
end
|
110
|
+
|
111
|
+
def propagate_xtrace(env, settings, xtrace)
|
112
|
+
return yield unless settings.do_propagate
|
113
|
+
|
114
|
+
if xtrace
|
115
|
+
xtrace_local = xtrace.dup
|
116
|
+
AppOpticsAPM::XTrace.unset_sampled(xtrace_local) unless settings.do_sample
|
117
|
+
env['HTTP_X_TRACE'] = xtrace_local
|
118
|
+
end
|
119
|
+
|
120
|
+
status, headers, response = yield
|
121
|
+
|
122
|
+
headers ||= {}
|
123
|
+
headers['X-Trace'] = AppOpticsAPM::Context.toString if AppOpticsAPM::Context.isValid
|
124
|
+
headers['X-Trace'] ||= xtrace if xtrace
|
125
|
+
headers['X-Trace'] && AppOpticsAPM::XTrace.unset_sampled(headers['X-Trace']) unless settings.do_sample
|
126
|
+
|
127
|
+
[status, headers, response]
|
128
|
+
end
|
129
|
+
|
130
|
+
def sample(env, settings, options, profile_spans)
|
131
|
+
xtrace = env['HTTP_X_TRACE']
|
132
|
+
if settings.do_sample
|
133
|
+
begin
|
134
|
+
report_kvs = collect(env)
|
135
|
+
settings.add_kvs(report_kvs)
|
136
|
+
options&.add_kvs(report_kvs, settings)
|
137
|
+
|
138
|
+
AppOpticsAPM::API.log_start(:rack, xtrace, report_kvs, settings)
|
139
|
+
|
140
|
+
status, headers, response = yield
|
141
|
+
|
142
|
+
AppOpticsAPM::API.log_exit(:rack, { Status: status,
|
143
|
+
TransactionName: AppOpticsAPM.transaction_name,
|
144
|
+
ProfileSpans: profile_spans})
|
145
|
+
|
146
|
+
[status, headers, response]
|
147
|
+
rescue Exception => e
|
148
|
+
# it is ok to rescue Exception here because we are reraising it (we just need a chance to log_end)
|
149
|
+
AppOpticsAPM::API.log_exception(:rack, e)
|
150
|
+
AppOpticsAPM::API.log_exit(:rack, { Status: status,
|
151
|
+
TransactionName: AppOpticsAPM.transaction_name,
|
152
|
+
ProfileSpans: profile_spans
|
153
|
+
})
|
154
|
+
raise
|
155
|
+
end
|
156
|
+
else
|
157
|
+
AppOpticsAPM::API.create_nontracing_context(xtrace)
|
158
|
+
yield
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
else
|
165
|
+
module AppOpticsAPM
|
166
|
+
class Rack
|
167
|
+
attr_reader :app
|
168
|
+
|
169
|
+
def initialize(app)
|
170
|
+
@app = app
|
171
|
+
end
|
172
|
+
|
173
|
+
def call(env)
|
174
|
+
@app.call(env)
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.noop?
|
178
|
+
true
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright (c) 2020 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module RackCacheContext
|
6
|
+
|
7
|
+
###
|
8
|
+
# This adds a controller.action like transaction name for
|
9
|
+
# requests directly served from the cache without involving a controller.
|
10
|
+
# The resulting transaction name is `rack-cache.<cache-store>`,
|
11
|
+
# e.g. `rack-cache.memcached`
|
12
|
+
#
|
13
|
+
# It is not a full instrumentation, no span is added.
|
14
|
+
#
|
15
|
+
def call!(env)
|
16
|
+
metastore_type = begin
|
17
|
+
if options['rack-cache.metastore']
|
18
|
+
options['rack-cache.metastore'].match(/^([^\:]*)\:/)[1]
|
19
|
+
end || 'unknown_store'
|
20
|
+
rescue
|
21
|
+
'unknown_store'
|
22
|
+
end
|
23
|
+
|
24
|
+
env['appoptics_apm.action'] = metastore_type
|
25
|
+
env['appoptics_apm.controller'] = 'rack-cache'
|
26
|
+
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if AppOpticsAPM::Config[:rack_cache][:transaction_name] && defined?(Rack::Cache::Context)
|
33
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting rack_cache' if AppOpticsAPM::Config[:verbose]
|
34
|
+
Rack::Cache::Context.send(:prepend, ::AppOpticsAPM::RackCacheContext)
|
35
|
+
end
|