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,381 @@
1
+ #--
2
+ # Copyright (c) 2016 SolarWinds, LLC.
3
+ # All rights reserved.
4
+ #++
5
+
6
+ # Make sure Set is loaded if possible.
7
+ begin
8
+ require 'set'
9
+ rescue LoadError
10
+ class Set; end # :nodoc:
11
+ end
12
+
13
+
14
+ module AppOpticsAPM
15
+ module API
16
+ ##
17
+ # This modules provides the X-Trace logging facilities.
18
+ #
19
+ # These are the lower level methods, please see AppOpticsAPM::SDK
20
+ # for the higher level methods
21
+ #
22
+ # If using these directly make sure to always match a start/end and entry/exit to
23
+ # avoid broken traces.
24
+ module Logging
25
+ @@ints_or_nil = [Integer, Float, NilClass, String]
26
+ @@ints_or_nil << Fixnum unless RUBY_VERSION >= '2.4'
27
+
28
+ ##
29
+ # Public: Report an event in an active trace.
30
+ #
31
+ # ==== Arguments
32
+ #
33
+ # * +layer+ - The layer the reported event belongs to
34
+ # * +label+ - The label for the reported event. See SDK documentation for reserved labels and usage.
35
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
36
+ # * +event+ - An event to be used instead of generating a new one (see also start_trace_with_target)
37
+ #
38
+ # ==== Example
39
+ #
40
+ # AppOpticsAPM::API.log('logical_layer', 'entry')
41
+ # AppOpticsAPM::API.log('logical_layer', 'info', { :list_length => 20 })
42
+ # AppOpticsAPM::API.log('logical_layer', 'exit')
43
+ #
44
+ # Returns nothing.
45
+ def log(layer, label, opts = {}, event = nil)
46
+ return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
47
+
48
+ event ||= AppOpticsAPM::Context.createEvent
49
+ log_event(layer, label, event, opts)
50
+ end
51
+
52
+ ##
53
+ # Public: Report an exception.
54
+ #
55
+ # ==== Arguments
56
+ #
57
+ # * +layer+ - The layer the reported event belongs to
58
+ # * +exception+ - The exception to report, responds to :message and :backtrace(optional)
59
+ # * +opts+ - Custom params if you want to log extra information
60
+ #
61
+ # ==== Example
62
+ #
63
+ # begin
64
+ # my_iffy_method
65
+ # rescue Exception => e
66
+ # AppOpticsAPM::API.log_exception('rails', e, { user: user_id })
67
+ # raise
68
+ # end
69
+ #
70
+ # Returns nothing.
71
+ def log_exception(layer, exception, opts = {})
72
+ return AppOpticsAPM::Context.toString if !AppOpticsAPM.tracing? || exception.instance_variable_get(:@exn_logged)
73
+
74
+ unless exception
75
+ AppOpticsAPM.logger.debug '[appoptics_apm/debug] log_exception called with nil exception'
76
+ return AppOpticsAPM::Context.toString
77
+ end
78
+
79
+ exception.message << exception.class.name if exception.message.length < 4
80
+ opts.merge!(:Spec => 'error',
81
+ :ErrorClass => exception.class.name,
82
+ :ErrorMsg => exception.message)
83
+
84
+ if exception.respond_to?(:backtrace) && exception.backtrace
85
+ opts.merge!(:Backtrace => exception.backtrace.join("\r\n"))
86
+ end
87
+
88
+ exception.instance_variable_set(:@exn_logged, true)
89
+ log(layer, :error, opts)
90
+ end
91
+
92
+ ##
93
+ # Public: Start a trace depending on TransactionSettings
94
+ # or decide whether or not to start a trace, and report an entry event
95
+ # appropriately.
96
+ #
97
+ # ==== Arguments
98
+ #
99
+ # * +layer+ - The layer the reported event belongs to
100
+ # * +xtrace+ - An xtrace metadata string, or nil. Used for cross-application tracing.
101
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
102
+ # * +settings+ - An instance of TransactionSettings
103
+ #
104
+ # ==== Example
105
+ #
106
+ # AppOpticsAPM::API.log_start(:layer_name, nil, { :id => @user.id })
107
+ #
108
+ # Returns an xtrace metadata string if we are tracing
109
+ #
110
+ def log_start(layer, xtrace = nil, opts = {}, settings = nil)
111
+ return unless AppOpticsAPM.loaded
112
+
113
+ # check if tracing decision is already in effect and a Context created
114
+ return log_entry(layer, opts) if AppOpticsAPM::Context.isValid
115
+
116
+ # This is a bit ugly, but here is the best place to reset the layer_op thread local var.
117
+ AppOpticsAPM.layer_op = nil
118
+
119
+ xtrace = nil unless AppOpticsAPM::XTrace.valid?(xtrace)
120
+
121
+ settings ||= AppOpticsAPM::TransactionSettings.new(nil, xtrace)
122
+
123
+ if settings.do_sample
124
+ opts[:SampleRate] = settings.rate
125
+ opts[:SampleSource] = settings.source
126
+
127
+ AppOpticsAPM::XTrace.set_sampled(xtrace) if xtrace
128
+ event = create_start_event(xtrace)
129
+ log_event(layer, :entry, event, opts)
130
+ else
131
+ create_nontracing_context(xtrace)
132
+ AppOpticsAPM::Context.toString
133
+ end
134
+ end
135
+
136
+ ##
137
+ # Public: Report an exit event and potentially clear the tracing context.
138
+ #
139
+ # ==== Arguments
140
+ #
141
+ # * +layer+ - The layer the reported event belongs to
142
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
143
+ #
144
+ # ==== Example
145
+ #
146
+ # AppOpticsAPM::API.log_end(:layer_name, { :id => @user.id })
147
+ #
148
+ # Returns an xtrace metadata string if we are tracing
149
+ #
150
+ def log_end(layer, opts = {}, event = nil)
151
+ return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
152
+
153
+ event ||= AppOpticsAPM::Context.createEvent
154
+ log_event(layer, :exit, event, opts)
155
+ ensure
156
+ # FIXME has_incoming_context commented out, it has importance for JRuby only but breaks Ruby tests
157
+ AppOpticsAPM::Context.clear # unless AppOpticsAPM.has_incoming_context?
158
+ AppOpticsAPM.transaction_name = nil
159
+ end
160
+
161
+ ##
162
+ # Public: Log an entry event
163
+ #
164
+ # A helper method to create and log an entry event
165
+ #
166
+ # ==== Arguments
167
+ #
168
+ # * +layer+ - The layer the reported event belongs to
169
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
170
+ # * +op+ - To identify the current operation being traced. Used to avoid double tracing recursive calls.
171
+ #
172
+ # ==== Example
173
+ #
174
+ # AppOpticsAPM::API.log_entry(:layer_name, { :id => @user.id })
175
+ #
176
+ # Returns an xtrace metadata string if we are tracing
177
+ #
178
+ def log_entry(layer, opts = {}, op = nil) #, event = nil)
179
+ return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
180
+
181
+ if op
182
+ # check if re-entry but also add op to list for log_exit
183
+ re_entry = AppOpticsAPM.layer_op&.last == op.to_sym
184
+ AppOpticsAPM.layer_op = (AppOpticsAPM.layer_op || []) << op.to_sym
185
+ return AppOpticsAPM::Context.toString if re_entry
186
+ end
187
+
188
+ event ||= AppOpticsAPM::Context.createEvent
189
+ log_event(layer, :entry, event, opts)
190
+ end
191
+
192
+ ##
193
+ # Public: Log an info event
194
+ #
195
+ # A helper method to create and log an info event
196
+ #
197
+ # ==== Arguments
198
+ #
199
+ # * +layer+ - The layer the reported event belongs to
200
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
201
+ #
202
+ # ==== Example
203
+ #
204
+ # AppOpticsAPM::API.log_info(:layer_name, { :id => @user.id })
205
+ #
206
+ # Returns an xtrace metadata string if we are tracing
207
+ #
208
+ def log_info(layer, opts = {})
209
+ return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
210
+
211
+ opts[:Spec] = 'info'
212
+ log_event(layer, :info, AppOpticsAPM::Context.createEvent, opts)
213
+ end
214
+
215
+ ##
216
+ # Public: Log an exit event
217
+ #
218
+ # A helper method to create and log an exit event
219
+ #
220
+ # ==== Arguments
221
+ #
222
+ # * +layer+ - The layer the reported event belongs to
223
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
224
+ # * +op+ - Used to avoid double tracing recursive calls, needs to be the same in +log_exit+ that corresponds to a
225
+ # +log_entry+
226
+ #
227
+ # ==== Example
228
+ #
229
+ # AppOpticsAPM::API.log_exit(:layer_name, { :id => @user.id })
230
+ #
231
+ # Returns an xtrace metadata string if we are tracing
232
+ def log_exit(layer, opts = {}, op = nil)
233
+ return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
234
+
235
+ if op
236
+ if AppOpticsAPM.layer_op&.last == op.to_sym
237
+ AppOpticsAPM.layer_op.pop
238
+ else
239
+ AppOpticsAPM.logger.warn "[ruby/logging] op parameter of exit event doesn't correspond to an entry event op"
240
+ end
241
+ # check if the next op is the same, don't log event if so
242
+ return AppOpticsAPM::Context.toString if AppOpticsAPM.layer_op&.last == op.to_sym
243
+ end
244
+
245
+ log_event(layer, :exit, AppOpticsAPM::Context.createEvent, opts)
246
+ end
247
+
248
+ ##
249
+ # Public: Log an exit event from multiple requests
250
+ #
251
+ # A helper method to create and log an info event
252
+ # If we return from a request that faned out multiple requests
253
+ # we can add the collected X-Traces to the exit event
254
+ #
255
+ # ==== Arguments
256
+ #
257
+ # * +layer+ - The layer the reported event belongs to
258
+ # * +traces+ - An array with X-Trace strings returned from the requests
259
+ #
260
+ def log_multi_exit(layer, traces)
261
+ return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
262
+ task_id = AppOpticsAPM::XTrace.task_id(AppOpticsAPM::Context.toString)
263
+ event = AppOpticsAPM::Context.createEvent
264
+ traces.each do |trace|
265
+ event.addEdgeStr(trace) if AppOpticsAPM::XTrace.task_id(trace) == task_id
266
+ end
267
+ log_event(layer, :exit, event)
268
+ end
269
+
270
+ ##
271
+ #:nodoc:
272
+ # Internal: Reports agent init to the collector
273
+ #
274
+ # ==== Arguments
275
+ #
276
+ # * +layer+ - The layer the reported event belongs to
277
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event
278
+ def log_init(layer = :rack, opts = {})
279
+ context = AppOpticsAPM::Metadata.makeRandom
280
+ return AppOpticsAPM::Context.toString unless context.isValid
281
+
282
+ event = context.createEvent
283
+ event.addInfo(APPOPTICS_STR_LAYER, layer.to_s)
284
+ event.addInfo(APPOPTICS_STR_LABEL, 'single')
285
+ opts.each do |k, v|
286
+ event.addInfo(k, v.to_s)
287
+ end
288
+
289
+ AppOpticsAPM::Reporter.sendStatus(event, context)
290
+ AppOpticsAPM::Context.toString
291
+ end
292
+
293
+ private
294
+
295
+ ##
296
+ #:nodoc:
297
+ # @private
298
+ # Internal: Report an event.
299
+ #
300
+ # ==== Arguments
301
+ #
302
+ # * +layer+ - The layer the reported event belongs to
303
+ # * +label+ - The label for the reported event. See API documentation for reserved labels and usage.
304
+ # * +event+ - The pre-existing AppOpticsAPM context event. See AppOpticsAPM::Context.createEvent
305
+ # * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
306
+ #
307
+ # ==== Example
308
+ #
309
+ # entry = AppOpticsAPM::Context.createEvent
310
+ # AppOpticsAPM::API.log_event(:layer_name, 'entry', entry_event, { :id => @user.id })
311
+ #
312
+ # exit_event = AppOpticsAPM::Context.createEvent
313
+ # exit_event.addEdge(entry.getMetadata)
314
+ # AppOpticsAPM::API.log_event(:layer_name, 'exit', exit_event, { :id => @user.id })
315
+ #
316
+ def log_event(layer, label, event, opts = {})
317
+ event.addInfo(APPOPTICS_STR_LAYER, layer.to_s.freeze) if layer
318
+ event.addInfo(APPOPTICS_STR_LABEL, label.to_s.freeze)
319
+
320
+ AppOpticsAPM.layer = layer.to_sym if label == :entry
321
+ AppOpticsAPM.layer = nil if label == :exit
322
+
323
+ opts.each do |k, v|
324
+ value = nil
325
+
326
+ next unless valid_key? k
327
+
328
+ if @@ints_or_nil.include?(v.class)
329
+ value = v
330
+ elsif v.class == Set
331
+ value = v.to_a.to_s
332
+ else
333
+ value = v.to_s if v.respond_to?(:to_s)
334
+ end
335
+
336
+ begin
337
+ event.addInfo(k.to_s, value)
338
+ rescue ArgumentError => e
339
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] Couldn't add event KV: #{k} => #{v.class}"
340
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{e.message}"
341
+ end
342
+ end if !opts.nil? && opts.any?
343
+
344
+ AppOpticsAPM::Reporter.sendReport(event)
345
+ AppOpticsAPM::Context.toString
346
+ end
347
+
348
+ def create_start_event(xtrace = nil)
349
+ if AppOpticsAPM::XTrace.sampled?(xtrace)
350
+ md = AppOpticsAPM::Metadata.fromString(xtrace)
351
+ AppOpticsAPM::Context.fromString(xtrace)
352
+ md.createEvent
353
+ else
354
+ md = AppOpticsAPM::Metadata.makeRandom(true)
355
+ AppOpticsAPM::Context.set(md)
356
+ AppOpticsAPM::Event.startTrace(md)
357
+ end
358
+ end
359
+
360
+ public
361
+
362
+ def create_nontracing_context(xtrace)
363
+ if AppOpticsAPM::XTrace.valid?(xtrace)
364
+ # continue valid incoming xtrace
365
+ # use it for current context, ensuring sample bit is not set
366
+ AppOpticsAPM::XTrace.unset_sampled(xtrace)
367
+ AppOpticsAPM::Context.fromString(xtrace)
368
+ else
369
+ # discard invalid incoming xtrace
370
+ # create a new context, ensuring sample bit not set
371
+ md = AppOpticsAPM::Metadata.makeRandom(false)
372
+ AppOpticsAPM::Context.fromString(md.toString)
373
+ end
374
+ end
375
+
376
+ # need to set the context to public, otherwise the following `extends` will be private in api.rb
377
+ public
378
+
379
+ end
380
+ end
381
+ end
@@ -0,0 +1,37 @@
1
+ #--
2
+ # Copyright (c) 2016 SolarWinds, LLC.
3
+ # All rights reserved.
4
+ #++
5
+
6
+ # TODO remove Memcache from API and into some Util module to be included in Modules that need
7
+ # ____ these methods
8
+ module AppOpticsAPM
9
+ module API
10
+ ##
11
+ # Utility methods for the Memcache instrumentation
12
+ # currently used by dalli and memcached
13
+ module Memcache #:nodoc:
14
+ MEMCACHE_OPS = %w(add append cas decr decrement delete fetch get incr increment prepend replace set)
15
+
16
+ def memcache_hit?(result)
17
+ result.nil? ? 0 : 1
18
+ end
19
+
20
+ def remote_host(key)
21
+ return unless defined?(Lib.memcached_server_by_key) &&
22
+ defined?(@struct) && defined?(is_unix_socket?)
23
+
24
+ server_as_array = Lib.memcached_server_by_key(@struct, key.to_s)
25
+
26
+ return unless server_as_array.is_a?(Array)
27
+
28
+ server = server_as_array.first
29
+ if is_unix_socket?(server)
30
+ 'localhost'
31
+ elsif defined?(server.hostname)
32
+ server.hostname
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2019 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module API
6
+ module Metrics
7
+
8
+ ##
9
+ # Internal: method to send duration for a transaction
10
+ # it checks if it can send metrics with the current transaction name
11
+ # or a default transaction name and sets the transaction name accordingly
12
+ #
13
+ # === Arguments:
14
+ #
15
+ # * +span+ the name of the current span (used to construct a transaction name if none is defined)
16
+ # * +kvs+ A hash containing key/value pairs, only the value of :TransactionName will be relevant
17
+ #
18
+ # === Returns:
19
+ # The result of the block.
20
+ #
21
+ # === Assigns:
22
+ # The transaction_name to kvs[:TransactionName]
23
+
24
+ def send_metrics(span, kvs)
25
+ start = Time.now
26
+ yield
27
+ ensure
28
+ # TODO send_metrics is currently used in grpc, sdk
29
+ # ____ the error (0,1) would have to be returned from yield
30
+ error = 0
31
+ duration = (1000 * 1000 * (Time.now - start)).to_i
32
+ transaction_name = determine_transaction_name(span, kvs)
33
+ kvs[:TransactionName] = AppOpticsAPM::Span.createSpan(transaction_name, nil, duration, error)
34
+ AppOpticsAPM.transaction_name = nil
35
+ end
36
+
37
+ private
38
+
39
+ ##
40
+ # Determine the transaction name to be set on the trace.
41
+ #
42
+ # === Argument:
43
+ # * +span+ the name of the current span (used to construct a transaction name if none is defined)
44
+ # * +kvs+ (hash, optional) the hash that may have values for 'Controller' and 'Action'
45
+ #
46
+ # === Returns:
47
+ # (string) the determined transaction name
48
+ #
49
+ def determine_transaction_name(span, kvs = {})
50
+ if AppOpticsAPM.transaction_name
51
+ AppOpticsAPM.transaction_name
52
+ elsif kvs['Controller'] && kvs['Action']
53
+ [kvs['Controller'], kvs['Action']].join('.')
54
+ elsif kvs[:Controller] && kvs[:Action]
55
+ [kvs[:Controller], kvs[:Action]].join('.')
56
+ else
57
+ "custom-#{span}"
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,57 @@
1
+ #--
2
+ # Copyright (c) 2016 SolarWinds, LLC.
3
+ # All rights reserved.
4
+ #++
5
+
6
+ module AppOpticsAPM
7
+ module API
8
+ ##
9
+ # Provides the higher-level tracing interface for the API
10
+ #
11
+ # The tracing methods have been moved to AppOpticsAPM::SDK and AppOpticsAPM::API extends all methods from the SDK
12
+ # except for start_trace.
13
+ # AppOpticsAPM::API.start_trace is kept for backwards compatibility because it returns an array
14
+ # whereas AppOpticsAPM::SDK.start_trace will only return the result of the block.
15
+ #
16
+
17
+ module Tracing
18
+
19
+ # Public: Collect metrics and start tracing a given block of code. A
20
+ # trace will be started depending on configuration and probability.
21
+ # Detect any exceptions thrown by the block and report errors.
22
+ #
23
+ # When start_trace returns control to the calling context, the trace will be
24
+ # completed and the tracing context will be cleared.
25
+ #
26
+ # ==== Arguments
27
+ #
28
+ # * +span+ - name for the span to be used as label in the trace view
29
+ # * +xtrace+ - (optional) incoming X-Trace identifier to be continued
30
+ # * +opts+ - (optional) hash containing key/value pairs that will be reported along
31
+ # with the first event of this span
32
+ #
33
+ # ==== Example
34
+ #
35
+ # def handle_request(request, response)
36
+ # # ... code that modifies request and response ...
37
+ # end
38
+ #
39
+ # def handle_request_with_appoptics(request, response)
40
+ # start_trace('custom_span', nil, :TransactionName => 'handle_request') do
41
+ # handle_request(request, response)
42
+ # end
43
+ # end
44
+ #
45
+ # Returns an array with the result of the block and the last xtrace used
46
+ def start_trace(span, xtrace = nil, opts = {})
47
+ target = {}
48
+ [start_trace_with_target(span, xtrace, target, opts) { yield }, target['X-Trace']]
49
+ end
50
+
51
+ def profile_method(*args)
52
+ AppOpticsAPM.logger.warn("DEPRECATED: AppOpticsAPM::API.profile_method is deprecated. Use: AppOpticsAPM::SDK::trace_method")
53
+ AppOpticsAPM::SDK.trace_method(*args)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,120 @@
1
+ #--
2
+ # Copyright (c) 2016 SolarWinds, LLC.
3
+ # All rights reserved.
4
+ #++
5
+
6
+ require 'pp'
7
+
8
+ module AppOpticsAPM
9
+ module API
10
+ ##
11
+ # General utility methods for the gem
12
+ module Util #:nodoc:
13
+ BACKTRACE_CUTOFF = 200
14
+
15
+ # Internal: Check whether the provided key is reserved or not. Reserved
16
+ # keys are either keys that are handled by liboboe calls or the appoptics_apm gem.
17
+ #
18
+ # key - the key to check.
19
+ #
20
+ # Return a boolean indicating whether or not key is reserved.
21
+ def valid_key?(key)
22
+ ![:Label, :Layer, :Edge, :Timestamp, :Timestamp_u].include?(key.to_sym)
23
+ end
24
+
25
+ # Internal: Get the current backtrace.
26
+ #
27
+ # from - int, from position in array of backtraces
28
+ # to - int, end position in array of backtraces, can be negative to count from the end
29
+ #
30
+ # Returns a string with each frame of the backtrace separated by '\r\n'.
31
+ #
32
+ def backtrace(from = 0, to = -1)
33
+ bt = Kernel.caller
34
+ trim_backtrace(bt[from..to]).join("\r\n")
35
+ end
36
+
37
+ # Internal: Trim a backtrace to a manageable size
38
+ #
39
+ # backtrace - the backtrace (an array of stack frames/from Kernel.caller)
40
+ #
41
+ # Returns a trimmed backtrace
42
+ def trim_backtrace(backtrace)
43
+ return backtrace unless backtrace.is_a?(Array) && backtrace.size > BACKTRACE_CUTOFF
44
+
45
+ # Trim backtraces by getting the first 180 and last 20 lines
46
+ backtrace[0, 180] + ['...[snip]...'] + backtrace[backtrace.size - 20, 20]
47
+ end
48
+
49
+ # Internal: Check if a host is blacklisted from tracing
50
+ #
51
+ # addr_port - the addr_port from Net::HTTP although this method
52
+ # can be used from any component in reality
53
+ #
54
+ # Returns a boolean on blacklisted state
55
+ def blacklisted?(addr_port)
56
+ return false unless AppOpticsAPM::Config.blacklist
57
+
58
+ # Ensure that the blacklist is an array
59
+ unless AppOpticsAPM::Config.blacklist.is_a?(Array)
60
+ val = AppOpticsAPM::Config[:blacklist]
61
+ AppOpticsAPM::Config[:blacklist] = [val.to_s]
62
+ end
63
+
64
+ AppOpticsAPM::Config.blacklist.each do |h|
65
+ return true if addr_port.to_s.match(h.to_s)
66
+ end
67
+
68
+ false
69
+ end
70
+
71
+ # Internal: Pretty print a list of arguments for reporting
72
+ #
73
+ # args - the list of arguments to work on
74
+ #
75
+ # Returns a pretty string representation of arguments
76
+ def pps(*args)
77
+ old_out = $stdout
78
+ begin
79
+ s = StringIO.new
80
+ $stdout = s
81
+ pp(*args)
82
+ ensure
83
+ $stdout = old_out
84
+ end
85
+ s.string
86
+ end
87
+
88
+ # Internal: Determine a string to report representing klass
89
+ #
90
+ # args - an instance of a Class, a Class or a Module
91
+ #
92
+ # Returns a string representation of klass
93
+ def get_class_name(klass)
94
+ kv = {}
95
+
96
+ if klass.to_s =~ /::/
97
+ klass.class.to_s.rpartition('::').last
98
+ else
99
+ if klass.is_a?(Class) && klass.is_a?(Module)
100
+ # Class
101
+ kv['Class'] = klass.to_s
102
+
103
+ elsif !klass.is_a?(Class) && !klass.is_a?(Module)
104
+ # Class instance
105
+ kv['Class'] = klass.class.to_s
106
+
107
+ else
108
+ # Module
109
+ kv['Module'] = klass.to_s
110
+ end
111
+ end
112
+ kv
113
+ end
114
+
115
+ def xtrace_v2?(xtr)
116
+ xtr && xtr.start_with?('2B')
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+
6
+ module API
7
+ extend AppOpticsAPM::API::Logging
8
+ extend AppOpticsAPM::API::Metrics
9
+ extend AppOpticsAPM::API::LayerInit
10
+ extend AppOpticsAPM::API::Util
11
+
12
+ require_relative './sdk/tracing'
13
+ require_relative './sdk/custom_metrics'
14
+ require_relative './sdk/current_trace'
15
+ require_relative './sdk/logging' # to make sure it is loaded <- not very elegant
16
+
17
+ extend AppOpticsAPM::SDK::Tracing
18
+ extend AppOpticsAPM::SDK::CustomMetrics
19
+ extend AppOpticsAPM::API::Tracing
20
+ end
21
+ end