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,332 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module Inst
|
6
|
+
|
7
|
+
# Curb instrumentation wraps instance and class methods in two classes:
|
8
|
+
# Curl::Easy and Curl::Multi. This CurlUtility module is used as a common module
|
9
|
+
# to be shared among both modules.
|
10
|
+
module CurlUtility
|
11
|
+
|
12
|
+
private
|
13
|
+
##
|
14
|
+
# appoptics_collect
|
15
|
+
#
|
16
|
+
# Used as a central area to retrieve and return values
|
17
|
+
# that we're interesting in reporting to AppOpticsAPM
|
18
|
+
#
|
19
|
+
def appoptics_collect(verb = nil)
|
20
|
+
kvs = {}
|
21
|
+
|
22
|
+
kvs[:Spec] = 'rsc'
|
23
|
+
kvs[:IsService] = 1
|
24
|
+
|
25
|
+
# Conditionally log query args
|
26
|
+
if AppOpticsAPM::Config[:curb][:log_args]
|
27
|
+
kvs[:RemoteURL] = url
|
28
|
+
else
|
29
|
+
kvs[:RemoteURL] = url.split('?').first
|
30
|
+
end
|
31
|
+
|
32
|
+
kvs[:HTTPMethod] = verb if verb
|
33
|
+
|
34
|
+
# Avoid cross host tracing for blacklisted domains
|
35
|
+
kvs[:blacklisted] = AppOpticsAPM::API.blacklisted?(URI(url).hostname)
|
36
|
+
|
37
|
+
kvs
|
38
|
+
rescue => e
|
39
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] Error capturing curb KVs: #{e.message}"
|
40
|
+
if AppOpticsAPM::Config[:verbose]
|
41
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
42
|
+
AppOpticsAPM.logger.debug e.backtrace.join('\n')
|
43
|
+
end
|
44
|
+
ensure
|
45
|
+
return kvs
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# trace_curb_method
|
50
|
+
#
|
51
|
+
# An agnostic method that will profile any Curl::Easy method (and optional args and block)
|
52
|
+
# that you throw at it.
|
53
|
+
#
|
54
|
+
def trace_curb_method(kvs, method, args, &block)
|
55
|
+
# If we're not tracing, just do a fast return.
|
56
|
+
unless AppOpticsAPM.tracing?
|
57
|
+
unless AppOpticsAPM::API.blacklisted?(URI(url).hostname)
|
58
|
+
self.headers['X-Trace'] = AppOpticsAPM::Context.toString if AppOpticsAPM::Context.isValid
|
59
|
+
end
|
60
|
+
return self.send(method, args, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
response_context = nil
|
65
|
+
kvs.merge! appoptics_collect
|
66
|
+
|
67
|
+
AppOpticsAPM::API.log_entry(:curb, kvs)
|
68
|
+
kvs.clear
|
69
|
+
|
70
|
+
# The core curb call
|
71
|
+
unless AppOpticsAPM::API.blacklisted?(URI(url).hostname)
|
72
|
+
self.headers['X-Trace'] = AppOpticsAPM::Context.toString if AppOpticsAPM::Context.isValid
|
73
|
+
end
|
74
|
+
response = self.send(method, *args, &block)
|
75
|
+
|
76
|
+
kvs[:HTTPStatus] = response_code
|
77
|
+
|
78
|
+
# If we get a redirect, report the location header
|
79
|
+
if ((300..308).to_a.include? response_code) && headers.key?("Location")
|
80
|
+
kvs[:Location] = headers["Location"]
|
81
|
+
end
|
82
|
+
|
83
|
+
_, *response_headers = header_str.split(/[\r\n]+/).map(&:strip)
|
84
|
+
response_headers = Hash[response_headers.flat_map{ |s| s.scan(/^(\S+): (.+)/) }]
|
85
|
+
|
86
|
+
response_context = response_headers['X-Trace']
|
87
|
+
if response_context && !kvs[:blacklisted]
|
88
|
+
AppOpticsAPM::XTrace.continue_service_context(self.headers['X-Trace'], response_context)
|
89
|
+
end
|
90
|
+
|
91
|
+
response
|
92
|
+
rescue => e
|
93
|
+
AppOpticsAPM::API.log_exception(:curb, e)
|
94
|
+
raise e
|
95
|
+
ensure
|
96
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:curb][:collect_backtraces]
|
97
|
+
AppOpticsAPM::API.log_exit(:curb, kvs)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end # CurlUtility
|
102
|
+
|
103
|
+
# Instrumentation specific to ::Curl::Easy
|
104
|
+
module CurlEasy
|
105
|
+
# Common methods
|
106
|
+
include AppOpticsAPM::Inst::CurlUtility
|
107
|
+
|
108
|
+
def self.included(klass)
|
109
|
+
AppOpticsAPM::Util.method_alias(klass, :http, ::Curl::Easy)
|
110
|
+
AppOpticsAPM::Util.method_alias(klass, :perform, ::Curl::Easy)
|
111
|
+
AppOpticsAPM::Util.method_alias(klass, :http_put, ::Curl::Easy)
|
112
|
+
AppOpticsAPM::Util.method_alias(klass, :http_post, ::Curl::Easy)
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# http_post_with_appoptics
|
117
|
+
#
|
118
|
+
# ::Curl::Easy.new.http_post wrapper
|
119
|
+
#
|
120
|
+
def http_post_with_appoptics(*args, &block)
|
121
|
+
# If we're not tracing, just do a fast return.
|
122
|
+
if !AppOpticsAPM.tracing? || AppOpticsAPM.tracing_layer?(:curb)
|
123
|
+
unless AppOpticsAPM::API.blacklisted?(URI(url).hostname)
|
124
|
+
self.headers['X-Trace'] = AppOpticsAPM::Context.toString() if AppOpticsAPM::Context.isValid
|
125
|
+
end
|
126
|
+
return http_post_without_appoptics(*args)
|
127
|
+
end
|
128
|
+
|
129
|
+
kvs = {}
|
130
|
+
kvs[:HTTPMethod] = :POST
|
131
|
+
|
132
|
+
trace_curb_method(kvs, :http_post_without_appoptics, args, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# http_put_with_appoptics
|
137
|
+
#
|
138
|
+
# ::Curl::Easy.new.http_put wrapper
|
139
|
+
#
|
140
|
+
def http_put_with_appoptics(*args, &block)
|
141
|
+
# If we're not tracing, just do a fast return.
|
142
|
+
if !AppOpticsAPM.tracing? || AppOpticsAPM.tracing_layer?(:curb)
|
143
|
+
unless AppOpticsAPM::API.blacklisted?(URI(url).hostname)
|
144
|
+
self.headers['X-Trace'] = AppOpticsAPM::Context.toString() if AppOpticsAPM::Context.isValid
|
145
|
+
end
|
146
|
+
return http_put_without_appoptics(data)
|
147
|
+
end
|
148
|
+
|
149
|
+
kvs = {}
|
150
|
+
kvs[:HTTPMethod] = :PUT
|
151
|
+
|
152
|
+
trace_curb_method(kvs, :http_put_without_appoptics, args, &block)
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# perform_with_appoptics
|
157
|
+
#
|
158
|
+
# ::Curl::Easy.new.perform wrapper
|
159
|
+
#
|
160
|
+
def perform_with_appoptics(&block)
|
161
|
+
# If we're not tracing, just do a fast return.
|
162
|
+
# excluding curb layer: because the curb C code for easy.http calls perform,
|
163
|
+
# we have to make sure we don't log again
|
164
|
+
if !AppOpticsAPM.tracing? || AppOpticsAPM.tracing_layer?(:curb)
|
165
|
+
unless AppOpticsAPM::API.blacklisted?(URI(url).hostname)
|
166
|
+
self.headers['X-Trace'] = AppOpticsAPM::Context.toString() if AppOpticsAPM::Context.isValid
|
167
|
+
end
|
168
|
+
return perform_without_appoptics(&block)
|
169
|
+
end
|
170
|
+
|
171
|
+
kvs = {}
|
172
|
+
# This perform gets called from two places, ::Curl::Easy.new.perform
|
173
|
+
# and Curl::Easy.new.http_head. In the case of http_head we detect the
|
174
|
+
# HTTP verb via get info.
|
175
|
+
if self.getinfo(self.sym2curl(:nobody))
|
176
|
+
kvs[:HTTPMethod] = :HEAD
|
177
|
+
else
|
178
|
+
kvs[:HTTPMethod] = :GET
|
179
|
+
end
|
180
|
+
|
181
|
+
trace_curb_method(kvs, :perform_without_appoptics, nil, &block)
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# http_with_appoptics
|
186
|
+
#
|
187
|
+
# ::Curl::Easy.new.http wrapper
|
188
|
+
#
|
189
|
+
def http_with_appoptics(verb, &block)
|
190
|
+
# If we're not tracing, just do a fast return.
|
191
|
+
unless AppOpticsAPM.tracing?
|
192
|
+
unless AppOpticsAPM::API.blacklisted?(URI(url).hostname)
|
193
|
+
self.headers['X-Trace'] = AppOpticsAPM::Context.toString() if AppOpticsAPM::Context.isValid
|
194
|
+
end
|
195
|
+
return http_without_appoptics(verb)
|
196
|
+
end
|
197
|
+
|
198
|
+
kvs = {}
|
199
|
+
kvs[:HTTPMethod] = verb
|
200
|
+
|
201
|
+
trace_curb_method(kvs, :http_without_appoptics, [verb], &block)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# CurlMultiCM
|
207
|
+
#
|
208
|
+
# This module contains the class method wrappers for the CurlMulti class.
|
209
|
+
# This module should be _extended_ by CurlMulti.
|
210
|
+
#
|
211
|
+
module CurlMultiCM
|
212
|
+
include AppOpticsAPM::Inst::CurlUtility
|
213
|
+
|
214
|
+
def self.extended(klass)
|
215
|
+
AppOpticsAPM::Util.class_method_alias(klass, :http, ::Curl::Multi)
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# http_with_appoptics
|
220
|
+
#
|
221
|
+
# ::Curl::Multi.new.http wrapper
|
222
|
+
#
|
223
|
+
def http_with_appoptics(urls_with_config, multi_options={}, &block)
|
224
|
+
# If we're not tracing, just do a fast return.
|
225
|
+
unless AppOpticsAPM.tracing?
|
226
|
+
urls_with_config.each do |conf|
|
227
|
+
unless AppOpticsAPM::API.blacklisted?(URI(conf[:url]).hostname)
|
228
|
+
conf[:headers] ||= {}
|
229
|
+
conf[:headers]['X-Trace'] = AppOpticsAPM::Context.toString if AppOpticsAPM::Context.isValid
|
230
|
+
end
|
231
|
+
end
|
232
|
+
return http_without_appoptics(urls_with_config, multi_options, &block)
|
233
|
+
end
|
234
|
+
|
235
|
+
begin
|
236
|
+
kvs = {}
|
237
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:curb][:collect_backtraces]
|
238
|
+
|
239
|
+
AppOpticsAPM::API.log_entry(:curb_multi, kvs)
|
240
|
+
context = AppOpticsAPM::Context.toString
|
241
|
+
urls_with_config.each do |conf|
|
242
|
+
unless AppOpticsAPM::API.blacklisted?(URI(conf[:url]).hostname)
|
243
|
+
conf[:headers] ||= {}
|
244
|
+
conf[:headers]['X-Trace'] = context if AppOpticsAPM::Context.isValid
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
traces = []
|
249
|
+
# The core curb call
|
250
|
+
http_without_appoptics(urls_with_config, multi_options) do |easy, response_code, method|
|
251
|
+
# this is the only way we can access the headers, they are not exposed otherwise
|
252
|
+
unless AppOpticsAPM::API.blacklisted?(URI(easy.url).hostname)
|
253
|
+
xtrace = easy.header_str.scan(/X-Trace: ([0-9A-F]*)/).map{ |m| m[0] }
|
254
|
+
traces << xtrace[0] unless xtrace.empty?
|
255
|
+
end
|
256
|
+
block.call(easy, response_code, method) if block
|
257
|
+
end
|
258
|
+
AppOpticsAPM::XTrace.continue_service_context(context, traces.pop) unless traces.empty?
|
259
|
+
rescue => e
|
260
|
+
AppOpticsAPM::API.log_exception(:curb_multi, e)
|
261
|
+
raise e
|
262
|
+
ensure
|
263
|
+
AppOpticsAPM::API.log_multi_exit(:curb_multi, traces)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
##
|
269
|
+
# CurlMultiIM
|
270
|
+
#
|
271
|
+
# This module contains the instance method wrappers for the CurlMulti class.
|
272
|
+
# This module should be _included_ into CurlMulti.
|
273
|
+
#
|
274
|
+
module CurlMultiIM
|
275
|
+
include AppOpticsAPM::Inst::CurlUtility
|
276
|
+
|
277
|
+
def self.included(klass)
|
278
|
+
AppOpticsAPM::Util.method_alias(klass, :perform, ::Curl::Multi)
|
279
|
+
end
|
280
|
+
|
281
|
+
##
|
282
|
+
# perform_with_appoptics
|
283
|
+
#
|
284
|
+
# ::Curl::Multi.new.perform wrapper
|
285
|
+
#
|
286
|
+
# the reason we instrument this method is because it can be called directly,
|
287
|
+
# therefore we exclude calls that already have a curb layer assigned
|
288
|
+
# Be aware: this method is also called from the c-implementation
|
289
|
+
#
|
290
|
+
def perform_with_appoptics(&block)
|
291
|
+
# If we're not tracing or we're already tracing curb, just do a fast return.
|
292
|
+
if !AppOpticsAPM.tracing? || [:curb, :curb_multi].include?(AppOpticsAPM.layer)
|
293
|
+
self.requests.each do |request|
|
294
|
+
request = request[1] if request.is_a?(Array)
|
295
|
+
unless AppOpticsAPM::API.blacklisted?(URI(request.url).hostname)
|
296
|
+
request.headers['X-Trace'] = AppOpticsAPM::Context.toString if AppOpticsAPM::Context.isValid
|
297
|
+
end
|
298
|
+
end
|
299
|
+
return perform_without_appoptics(&block)
|
300
|
+
end
|
301
|
+
|
302
|
+
begin
|
303
|
+
kvs = {}
|
304
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:curb][:collect_backtraces]
|
305
|
+
|
306
|
+
AppOpticsAPM::API.log_entry(:curb_multi, kvs)
|
307
|
+
|
308
|
+
self.requests.each do |request|
|
309
|
+
request = request[1] if request.is_a?(Array)
|
310
|
+
unless AppOpticsAPM::API.blacklisted?(URI(request.url).hostname)
|
311
|
+
request.headers['X-Trace'] = AppOpticsAPM::Context.toString if AppOpticsAPM::Context.isValid
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
perform_without_appoptics(&block)
|
316
|
+
rescue => e
|
317
|
+
AppOpticsAPM::API.log_exception(:curb_multi, e)
|
318
|
+
raise e
|
319
|
+
ensure
|
320
|
+
AppOpticsAPM::API.log_exit(:curb_multi)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
if AppOpticsAPM::Config[:curb][:enabled] && defined?(::Curl)
|
328
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting curb' if AppOpticsAPM::Config[:verbose]
|
329
|
+
AppOpticsAPM::Util.send_include(::Curl::Easy, AppOpticsAPM::Inst::CurlEasy)
|
330
|
+
AppOpticsAPM::Util.send_extend(::Curl::Multi, AppOpticsAPM::Inst::CurlMultiCM)
|
331
|
+
AppOpticsAPM::Util.send_include(::Curl::Multi, AppOpticsAPM::Inst::CurlMultiIM)
|
332
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module Inst
|
6
|
+
module Dalli
|
7
|
+
include AppOpticsAPM::API::Memcache
|
8
|
+
|
9
|
+
def self.included(cls)
|
10
|
+
cls.class_eval do
|
11
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting memcache (dalli)' if AppOpticsAPM::Config[:verbose]
|
12
|
+
if ::Dalli::Client.private_method_defined? :perform
|
13
|
+
alias perform_without_appoptics perform
|
14
|
+
alias perform perform_with_appoptics
|
15
|
+
else
|
16
|
+
AppOpticsAPM.logger.warn '[appoptics_apm/loading] Couldn\'t properly instrument Memcache (Dalli). Partial traces may occur.'
|
17
|
+
end
|
18
|
+
|
19
|
+
if ::Dalli::Client.method_defined? :get_multi
|
20
|
+
alias get_multi_without_appoptics get_multi
|
21
|
+
alias get_multi get_multi_with_appoptics
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def perform_with_appoptics(*all_args, &blk)
|
27
|
+
op, key, *args = *all_args
|
28
|
+
|
29
|
+
report_kvs = {}
|
30
|
+
report_kvs[:KVOp] = op
|
31
|
+
report_kvs[:KVKey] = key
|
32
|
+
if @servers.is_a?(Array) && !@servers.empty?
|
33
|
+
report_kvs[:RemoteHost] = @servers.join(", ")
|
34
|
+
end
|
35
|
+
|
36
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?(:get_multi)
|
37
|
+
AppOpticsAPM::API.trace(:memcache, report_kvs) do
|
38
|
+
result = perform_without_appoptics(*all_args, &blk)
|
39
|
+
|
40
|
+
# Clear the hash for a potential info event
|
41
|
+
report_kvs.clear
|
42
|
+
report_kvs[:KVHit] = memcache_hit?(result) if op == :get && key.class == String
|
43
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:dalli][:collect_backtraces]
|
44
|
+
|
45
|
+
result
|
46
|
+
end
|
47
|
+
else
|
48
|
+
perform_without_appoptics(*all_args, &blk)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_multi_with_appoptics(*keys)
|
53
|
+
return get_multi_without_appoptics(*keys) unless AppOpticsAPM.tracing?
|
54
|
+
|
55
|
+
info_kvs = {}
|
56
|
+
|
57
|
+
begin
|
58
|
+
info_kvs[:KVKeyCount] = keys.flatten.length
|
59
|
+
info_kvs[:KVKeyCount] = (info_kvs[:KVKeyCount] - 1) if keys.last.is_a?(Hash) || keys.last.nil?
|
60
|
+
if @servers.is_a?(Array) && !@servers.empty?
|
61
|
+
info_kvs[:RemoteHost] = @servers.join(", ")
|
62
|
+
end
|
63
|
+
rescue => e
|
64
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
65
|
+
end
|
66
|
+
|
67
|
+
info_kvs[:KVOp] = :get_multi
|
68
|
+
info_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:dalli][:collect_backtraces]
|
69
|
+
AppOpticsAPM::API.trace(:memcache, info_kvs, :get_multi) do
|
70
|
+
values = get_multi_without_appoptics(*keys)
|
71
|
+
|
72
|
+
info_kvs[:KVHitCount] = values.length
|
73
|
+
|
74
|
+
values
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
if defined?(Dalli) && AppOpticsAPM::Config[:dalli][:enabled]
|
82
|
+
::Dalli::Client.module_eval do
|
83
|
+
include AppOpticsAPM::Inst::Dalli
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
if defined?(Delayed)
|
5
|
+
module AppOpticsAPM
|
6
|
+
module Inst
|
7
|
+
module DelayedJob
|
8
|
+
##
|
9
|
+
# ForkHandler
|
10
|
+
#
|
11
|
+
# Since delayed job doesn't offer a hook into `after_fork`, we alias the method
|
12
|
+
# here to do our magic after a fork happens.
|
13
|
+
#
|
14
|
+
module ForkHandler
|
15
|
+
def self.extended(klass)
|
16
|
+
AppOpticsAPM::Util.class_method_alias(klass, :after_fork, ::Delayed::Worker)
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_fork_with_appoptics
|
20
|
+
AppOpticsAPM.logger.info '[appoptics_apm/delayed_job] Detected fork. Restarting AppOpticsAPM reporter.' if AppOpticsAPM::Config[:verbose]
|
21
|
+
AppOpticsAPM::Reporter.restart unless ENV.key?('APPOPTICS_GEM_TEST')
|
22
|
+
|
23
|
+
after_fork_without_appoptics
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# AppOpticsAPM::Inst::DelayedJob::Plugin
|
29
|
+
#
|
30
|
+
# The AppOpticsAPM DelayedJob plugin. Here we wrap `enqueue` and
|
31
|
+
# `perform` to capture the timing of the bits we're interested
|
32
|
+
# in.
|
33
|
+
#
|
34
|
+
class Plugin < Delayed::Plugin
|
35
|
+
callbacks do |lifecycle|
|
36
|
+
|
37
|
+
# enqueue
|
38
|
+
if AppOpticsAPM::Config[:delayed_jobclient][:enabled]
|
39
|
+
lifecycle.around(:enqueue) do |job, &block|
|
40
|
+
begin
|
41
|
+
report_kvs = {}
|
42
|
+
report_kvs[:Spec] = :pushq
|
43
|
+
report_kvs[:Flavor] = :DelayedJob
|
44
|
+
report_kvs[:JobName] = job.name
|
45
|
+
report_kvs[:MsgID] = job.id
|
46
|
+
report_kvs[:Queue] = job.queue if job.queue
|
47
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:delayed_jobclient][:collect_backtraces]
|
48
|
+
|
49
|
+
AppOpticsAPM::API.trace(:'delayed_job-client', report_kvs) do
|
50
|
+
block.call(job)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# invoke_job
|
57
|
+
if AppOpticsAPM::Config[:delayed_jobworker][:enabled]
|
58
|
+
lifecycle.around(:perform) do |worker, job, &block|
|
59
|
+
begin
|
60
|
+
report_kvs = {}
|
61
|
+
report_kvs[:Spec] = :job
|
62
|
+
report_kvs[:Flavor] = :DelayedJob
|
63
|
+
report_kvs[:JobName] = job.name
|
64
|
+
report_kvs[:MsgID] = job.id
|
65
|
+
report_kvs[:Queue] = job.queue if job.queue
|
66
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:delayed_jobworker][:collect_backtraces]
|
67
|
+
|
68
|
+
# DelayedJob Specific KVs
|
69
|
+
report_kvs[:priority] = job.priority
|
70
|
+
report_kvs[:attempts] = job.attempts
|
71
|
+
report_kvs[:WorkerName] = job.locked_by
|
72
|
+
rescue => e
|
73
|
+
AppOpticsAPM.logger.warn "[appoptics_apm/warning] inst/delayed_job.rb: #{e.message}"
|
74
|
+
end
|
75
|
+
|
76
|
+
AppOpticsAPM::SDK.start_trace(:'delayed_job-worker', nil, report_kvs) do
|
77
|
+
result = block.call(worker, job)
|
78
|
+
AppOpticsAPM::API.log_exception(:'delayed_job-worker', job.error) if job.error
|
79
|
+
result
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting delayed_job' if AppOpticsAPM::Config[:verbose]
|
90
|
+
AppOpticsAPM::Util.send_extend(::Delayed::Worker, AppOpticsAPM::Inst::DelayedJob::ForkHandler)
|
91
|
+
Delayed::Worker.plugins << AppOpticsAPM::Inst::DelayedJob::Plugin
|
92
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module Inst
|
6
|
+
module EventMachine
|
7
|
+
module HttpConnection
|
8
|
+
def setup_request_with_appoptics(*args, &block)
|
9
|
+
context = AppOpticsAPM::Context.toString
|
10
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(@uri)
|
11
|
+
|
12
|
+
if AppOpticsAPM.tracing?
|
13
|
+
report_kvs = {}
|
14
|
+
|
15
|
+
begin
|
16
|
+
report_kvs[:Spec] = 'rsc'
|
17
|
+
report_kvs[:IsService] = 1
|
18
|
+
report_kvs[:RemoteURL] = @uri
|
19
|
+
report_kvs[:HTTPMethod] = args[0]
|
20
|
+
report_kvs[:Blacklisted] = true if blacklisted
|
21
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:em_http_request][:collect_backtraces]
|
22
|
+
rescue => e
|
23
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] em-http-request KV error: #{e.inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
context = AppOpticsAPM::API.log_entry('em-http-request', report_kvs)
|
27
|
+
end
|
28
|
+
client = setup_request_without_appoptics(*args, &block)
|
29
|
+
client.req.headers['X-Trace'] = context unless blacklisted
|
30
|
+
client
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module HttpClient
|
35
|
+
def parse_response_header_with_appoptics(*args, &block)
|
36
|
+
report_kvs = {}
|
37
|
+
xtrace = nil
|
38
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(@uri)
|
39
|
+
|
40
|
+
begin
|
41
|
+
report_kvs[:HTTPStatus] = args[2]
|
42
|
+
report_kvs[:Async] = 1
|
43
|
+
rescue => e
|
44
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] em-http-request KV error: #{e.inspect}"
|
45
|
+
end
|
46
|
+
|
47
|
+
parse_response_header_without_appoptics(*args, &block)
|
48
|
+
|
49
|
+
unless blacklisted
|
50
|
+
headers = args[0]
|
51
|
+
context = AppOpticsAPM::Context.toString
|
52
|
+
task_id = AppOpticsAPM::XTrace.task_id(context)
|
53
|
+
|
54
|
+
if headers.is_a?(Hash) && headers.key?('X-Trace')
|
55
|
+
xtrace = headers['X-Trace']
|
56
|
+
end
|
57
|
+
|
58
|
+
if AppOpticsAPM::XTrace.valid?(xtrace) && AppOpticsAPM.tracing?
|
59
|
+
|
60
|
+
# Assure that we received back a valid X-Trace with the same task_id
|
61
|
+
if task_id == AppOpticsAPM::XTrace.task_id(xtrace)
|
62
|
+
AppOpticsAPM::Context.fromString(xtrace)
|
63
|
+
else
|
64
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/em-http] Mismatched returned X-Trace ID : #{xtrace}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
ensure
|
70
|
+
AppOpticsAPM::API.log_exit(:'em-http-request', report_kvs)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if defined?(EventMachine::HttpConnection) && defined?(EventMachine::HttpClient) && AppOpticsAPM::Config[:em_http_request][:enabled]
|
78
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting em-http-request' if AppOpticsAPM::Config[:verbose]
|
79
|
+
|
80
|
+
class EventMachine::HttpConnection
|
81
|
+
include AppOpticsAPM::Inst::EventMachine::HttpConnection
|
82
|
+
|
83
|
+
if method_defined?(:setup_request)
|
84
|
+
class_eval 'alias :setup_request_without_appoptics :setup_request'
|
85
|
+
class_eval 'alias :setup_request :setup_request_with_appoptics'
|
86
|
+
else
|
87
|
+
AppOpticsAPM.logger.warn '[appoptics_apm/loading] Couldn\'t properly instrument em-http-request (:setup_request). Partial traces may occur.'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class EventMachine::HttpClient
|
92
|
+
include AppOpticsAPM::Inst::EventMachine::HttpClient
|
93
|
+
|
94
|
+
if method_defined?(:parse_response_header)
|
95
|
+
class_eval 'alias :parse_response_header_without_appoptics :parse_response_header'
|
96
|
+
class_eval 'alias :parse_response_header :parse_response_header_with_appoptics'
|
97
|
+
else
|
98
|
+
AppOpticsAPM.logger.warn '[appoptics_apm/loading] Couldn\'t properly instrument em-http-request (:parse_response_header). Partial traces may occur.'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|