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.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +5 -0
  3. data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
  4. data/.github/workflows/build_and_release_gem.yml +103 -0
  5. data/.github/workflows/build_for_packagecloud.yml +70 -0
  6. data/.github/workflows/docker-images.yml +47 -0
  7. data/.github/workflows/run_cpluplus_tests.yml +73 -0
  8. data/.github/workflows/run_tests.yml +168 -0
  9. data/.github/workflows/scripts/test_install.rb +23 -0
  10. data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
  11. data/.github/workflows/test_on_4_linux.yml +159 -0
  12. data/.gitignore +36 -0
  13. data/.rubocop.yml +29 -0
  14. data/.travis.yml +130 -0
  15. data/.yardopts +6 -0
  16. data/CHANGELOG.md +769 -0
  17. data/CONFIG.md +33 -0
  18. data/Gemfile +14 -0
  19. data/LICENSE +202 -0
  20. data/README.md +393 -0
  21. data/appoptics_apm.gemspec +70 -0
  22. data/bin/appoptics_apm_config +15 -0
  23. data/examples/prepend.rb +13 -0
  24. data/examples/sdk_examples.rb +158 -0
  25. data/ext/oboe_metal/README.md +69 -0
  26. data/ext/oboe_metal/extconf.rb +151 -0
  27. data/ext/oboe_metal/lib/.keep +0 -0
  28. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
  29. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
  30. data/ext/oboe_metal/noop/noop.c +8 -0
  31. data/ext/oboe_metal/src/README.md +6 -0
  32. data/ext/oboe_metal/src/VERSION +2 -0
  33. data/ext/oboe_metal/src/bson/bson.h +220 -0
  34. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  35. data/ext/oboe_metal/src/frames.cc +246 -0
  36. data/ext/oboe_metal/src/frames.h +40 -0
  37. data/ext/oboe_metal/src/init_appoptics_apm.cc +21 -0
  38. data/ext/oboe_metal/src/logging.cc +95 -0
  39. data/ext/oboe_metal/src/logging.h +35 -0
  40. data/ext/oboe_metal/src/oboe.h +1156 -0
  41. data/ext/oboe_metal/src/oboe_api.cpp +652 -0
  42. data/ext/oboe_metal/src/oboe_api.hpp +431 -0
  43. data/ext/oboe_metal/src/oboe_debug.h +59 -0
  44. data/ext/oboe_metal/src/oboe_swig_wrap.cc +7329 -0
  45. data/ext/oboe_metal/src/profiling.cc +435 -0
  46. data/ext/oboe_metal/src/profiling.h +78 -0
  47. data/ext/oboe_metal/test/CMakeLists.txt +53 -0
  48. data/ext/oboe_metal/test/FindGMock.cmake +43 -0
  49. data/ext/oboe_metal/test/README.md +56 -0
  50. data/ext/oboe_metal/test/frames_test.cc +164 -0
  51. data/ext/oboe_metal/test/profiling_test.cc +93 -0
  52. data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
  53. data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
  54. data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
  55. data/ext/oboe_metal/test/test.h +11 -0
  56. data/ext/oboe_metal/test/test_main.cc +32 -0
  57. data/init.rb +4 -0
  58. data/lib/appoptics_apm/api/layerinit.rb +41 -0
  59. data/lib/appoptics_apm/api/logging.rb +381 -0
  60. data/lib/appoptics_apm/api/memcache.rb +37 -0
  61. data/lib/appoptics_apm/api/metrics.rb +63 -0
  62. data/lib/appoptics_apm/api/tracing.rb +57 -0
  63. data/lib/appoptics_apm/api/util.rb +120 -0
  64. data/lib/appoptics_apm/api.rb +21 -0
  65. data/lib/appoptics_apm/base.rb +231 -0
  66. data/lib/appoptics_apm/config.rb +299 -0
  67. data/lib/appoptics_apm/frameworks/grape.rb +98 -0
  68. data/lib/appoptics_apm/frameworks/padrino.rb +78 -0
  69. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
  70. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  71. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  72. data/lib/appoptics_apm/frameworks/rails/inst/action_controller6.rb +50 -0
  73. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  74. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +88 -0
  75. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  76. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  77. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  78. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
  79. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
  80. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +114 -0
  81. data/lib/appoptics_apm/frameworks/rails/inst/logger_formatters.rb +27 -0
  82. data/lib/appoptics_apm/frameworks/rails.rb +100 -0
  83. data/lib/appoptics_apm/frameworks/sinatra.rb +96 -0
  84. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  85. data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
  86. data/lib/appoptics_apm/inst/curb.rb +332 -0
  87. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  88. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  89. data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
  90. data/lib/appoptics_apm/inst/excon.rb +125 -0
  91. data/lib/appoptics_apm/inst/faraday.rb +106 -0
  92. data/lib/appoptics_apm/inst/graphql.rb +240 -0
  93. data/lib/appoptics_apm/inst/grpc_client.rb +159 -0
  94. data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
  95. data/lib/appoptics_apm/inst/http.rb +81 -0
  96. data/lib/appoptics_apm/inst/httpclient.rb +174 -0
  97. data/lib/appoptics_apm/inst/logger_formatter.rb +50 -0
  98. data/lib/appoptics_apm/inst/logging_log_event.rb +28 -0
  99. data/lib/appoptics_apm/inst/lumberjack_formatter.rb +13 -0
  100. data/lib/appoptics_apm/inst/memcached.rb +86 -0
  101. data/lib/appoptics_apm/inst/mongo.rb +246 -0
  102. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  103. data/lib/appoptics_apm/inst/moped.rb +466 -0
  104. data/lib/appoptics_apm/inst/rack.rb +182 -0
  105. data/lib/appoptics_apm/inst/rack_cache.rb +35 -0
  106. data/lib/appoptics_apm/inst/redis.rb +274 -0
  107. data/lib/appoptics_apm/inst/resque.rb +151 -0
  108. data/lib/appoptics_apm/inst/rest-client.rb +48 -0
  109. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  110. data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
  111. data/lib/appoptics_apm/inst/sidekiq-worker.rb +66 -0
  112. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  113. data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
  114. data/lib/appoptics_apm/instrumentation.rb +22 -0
  115. data/lib/appoptics_apm/loading.rb +65 -0
  116. data/lib/appoptics_apm/logger.rb +14 -0
  117. data/lib/appoptics_apm/noop/README.md +9 -0
  118. data/lib/appoptics_apm/noop/context.rb +27 -0
  119. data/lib/appoptics_apm/noop/metadata.rb +25 -0
  120. data/lib/appoptics_apm/noop/profiling.rb +21 -0
  121. data/lib/appoptics_apm/oboe_init_options.rb +211 -0
  122. data/lib/appoptics_apm/ruby.rb +35 -0
  123. data/lib/appoptics_apm/sdk/current_trace.rb +77 -0
  124. data/lib/appoptics_apm/sdk/custom_metrics.rb +94 -0
  125. data/lib/appoptics_apm/sdk/logging.rb +37 -0
  126. data/lib/appoptics_apm/sdk/tracing.rb +434 -0
  127. data/lib/appoptics_apm/support/profiling.rb +18 -0
  128. data/lib/appoptics_apm/support/transaction_metrics.rb +67 -0
  129. data/lib/appoptics_apm/support/transaction_settings.rb +219 -0
  130. data/lib/appoptics_apm/support/x_trace_options.rb +110 -0
  131. data/lib/appoptics_apm/support_report.rb +119 -0
  132. data/lib/appoptics_apm/test.rb +95 -0
  133. data/lib/appoptics_apm/thread_local.rb +26 -0
  134. data/lib/appoptics_apm/util.rb +326 -0
  135. data/lib/appoptics_apm/version.rb +16 -0
  136. data/lib/appoptics_apm/xtrace.rb +115 -0
  137. data/lib/appoptics_apm.rb +77 -0
  138. data/lib/joboe_metal.rb +212 -0
  139. data/lib/oboe.rb +7 -0
  140. data/lib/oboe_metal.rb +172 -0
  141. data/lib/rails/generators/appoptics_apm/install_generator.rb +47 -0
  142. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +425 -0
  143. data/log/.keep +0 -0
  144. data/yardoc_frontpage.md +26 -0
  145. 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