solarwinds_apm 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) 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 +112 -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 +155 -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 +161 -0
  12. data/.gitignore +39 -0
  13. data/.rubocop.yml +29 -0
  14. data/.yardopts +7 -0
  15. data/CHANGELOG.md +769 -0
  16. data/CONFIG.md +31 -0
  17. data/Gemfile +14 -0
  18. data/LICENSE +202 -0
  19. data/README.md +383 -0
  20. data/bin/solarwinds_apm_config +15 -0
  21. data/examples/prepend.rb +13 -0
  22. data/examples/sdk_examples.rb +158 -0
  23. data/ext/oboe_metal/README.md +69 -0
  24. data/ext/oboe_metal/extconf.rb +141 -0
  25. data/ext/oboe_metal/extconf_local.rb +75 -0
  26. data/ext/oboe_metal/lib/.keep +0 -0
  27. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
  28. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
  29. data/ext/oboe_metal/noop/noop.c +8 -0
  30. data/ext/oboe_metal/src/README.md +6 -0
  31. data/ext/oboe_metal/src/VERSION +2 -0
  32. data/ext/oboe_metal/src/bson/bson.h +220 -0
  33. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  34. data/ext/oboe_metal/src/frames.cc +247 -0
  35. data/ext/oboe_metal/src/frames.h +40 -0
  36. data/ext/oboe_metal/src/init_solarwinds_apm.cc +21 -0
  37. data/ext/oboe_metal/src/logging.cc +95 -0
  38. data/ext/oboe_metal/src/logging.h +35 -0
  39. data/ext/oboe_metal/src/oboe.h +1169 -0
  40. data/ext/oboe_metal/src/oboe_api.cpp +658 -0
  41. data/ext/oboe_metal/src/oboe_api.hpp +433 -0
  42. data/ext/oboe_metal/src/oboe_debug.h +59 -0
  43. data/ext/oboe_metal/src/oboe_swig_wrap.cc +7562 -0
  44. data/ext/oboe_metal/src/profiling.cc +435 -0
  45. data/ext/oboe_metal/src/profiling.h +78 -0
  46. data/ext/oboe_metal/test/CMakeLists.txt +53 -0
  47. data/ext/oboe_metal/test/FindGMock.cmake +43 -0
  48. data/ext/oboe_metal/test/README.md +56 -0
  49. data/ext/oboe_metal/test/frames_test.cc +164 -0
  50. data/ext/oboe_metal/test/profiling_test.cc +93 -0
  51. data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
  52. data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
  53. data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
  54. data/ext/oboe_metal/test/test.h +11 -0
  55. data/ext/oboe_metal/test/test_main.cc +32 -0
  56. data/init.rb +4 -0
  57. data/lib/oboe.rb +7 -0
  58. data/lib/oboe_metal.rb +172 -0
  59. data/lib/rails/generators/solarwinds_apm/install_generator.rb +47 -0
  60. data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +424 -0
  61. data/lib/solarwinds_apm/api/layerinit.rb +41 -0
  62. data/lib/solarwinds_apm/api/logging.rb +356 -0
  63. data/lib/solarwinds_apm/api/memcache.rb +37 -0
  64. data/lib/solarwinds_apm/api/metrics.rb +63 -0
  65. data/lib/solarwinds_apm/api/util.rb +98 -0
  66. data/lib/solarwinds_apm/api.rb +21 -0
  67. data/lib/solarwinds_apm/base.rb +160 -0
  68. data/lib/solarwinds_apm/config.rb +301 -0
  69. data/lib/solarwinds_apm/frameworks/grape.rb +96 -0
  70. data/lib/solarwinds_apm/frameworks/padrino.rb +78 -0
  71. data/lib/solarwinds_apm/frameworks/rails/inst/action_controller.rb +100 -0
  72. data/lib/solarwinds_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  73. data/lib/solarwinds_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  74. data/lib/solarwinds_apm/frameworks/rails/inst/action_view.rb +88 -0
  75. data/lib/solarwinds_apm/frameworks/rails/inst/active_record.rb +26 -0
  76. data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  77. data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +22 -0
  78. data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +103 -0
  79. data/lib/solarwinds_apm/frameworks/rails/inst/logger_formatters.rb +14 -0
  80. data/lib/solarwinds_apm/frameworks/rails.rb +100 -0
  81. data/lib/solarwinds_apm/frameworks/sinatra.rb +96 -0
  82. data/lib/solarwinds_apm/inst/bunny-client.rb +157 -0
  83. data/lib/solarwinds_apm/inst/bunny-consumer.rb +102 -0
  84. data/lib/solarwinds_apm/inst/curb.rb +288 -0
  85. data/lib/solarwinds_apm/inst/dalli.rb +89 -0
  86. data/lib/solarwinds_apm/inst/delayed_job.rb +100 -0
  87. data/lib/solarwinds_apm/inst/excon.rb +113 -0
  88. data/lib/solarwinds_apm/inst/faraday.rb +96 -0
  89. data/lib/solarwinds_apm/inst/graphql.rb +206 -0
  90. data/lib/solarwinds_apm/inst/grpc_client.rb +147 -0
  91. data/lib/solarwinds_apm/inst/grpc_server.rb +119 -0
  92. data/lib/solarwinds_apm/inst/httpclient.rb +181 -0
  93. data/lib/solarwinds_apm/inst/logger_formatter.rb +46 -0
  94. data/lib/solarwinds_apm/inst/logging_log_event.rb +24 -0
  95. data/lib/solarwinds_apm/inst/lumberjack_formatter.rb +9 -0
  96. data/lib/solarwinds_apm/inst/memcached.rb +86 -0
  97. data/lib/solarwinds_apm/inst/mongo.rb +246 -0
  98. data/lib/solarwinds_apm/inst/mongo2.rb +225 -0
  99. data/lib/solarwinds_apm/inst/moped.rb +466 -0
  100. data/lib/solarwinds_apm/inst/net_http.rb +60 -0
  101. data/lib/solarwinds_apm/inst/rack.rb +217 -0
  102. data/lib/solarwinds_apm/inst/rack_cache.rb +35 -0
  103. data/lib/solarwinds_apm/inst/redis.rb +273 -0
  104. data/lib/solarwinds_apm/inst/resque.rb +129 -0
  105. data/lib/solarwinds_apm/inst/rest-client.rb +43 -0
  106. data/lib/solarwinds_apm/inst/sequel.rb +241 -0
  107. data/lib/solarwinds_apm/inst/sidekiq-client.rb +63 -0
  108. data/lib/solarwinds_apm/inst/sidekiq-worker.rb +64 -0
  109. data/lib/solarwinds_apm/inst/typhoeus.rb +90 -0
  110. data/lib/solarwinds_apm/instrumentation.rb +22 -0
  111. data/lib/solarwinds_apm/loading.rb +65 -0
  112. data/lib/solarwinds_apm/logger.rb +14 -0
  113. data/lib/solarwinds_apm/noop/README.md +9 -0
  114. data/lib/solarwinds_apm/noop/context.rb +26 -0
  115. data/lib/solarwinds_apm/noop/metadata.rb +25 -0
  116. data/lib/solarwinds_apm/noop/profiling.rb +21 -0
  117. data/lib/solarwinds_apm/oboe_init_options.rb +191 -0
  118. data/lib/solarwinds_apm/ruby.rb +35 -0
  119. data/lib/solarwinds_apm/sdk/current_trace_info.rb +123 -0
  120. data/lib/solarwinds_apm/sdk/custom_metrics.rb +94 -0
  121. data/lib/solarwinds_apm/sdk/logging.rb +37 -0
  122. data/lib/solarwinds_apm/sdk/trace_context_headers.rb +69 -0
  123. data/lib/solarwinds_apm/sdk/tracing.rb +432 -0
  124. data/lib/solarwinds_apm/support/profiling.rb +22 -0
  125. data/lib/solarwinds_apm/support/trace_context.rb +53 -0
  126. data/lib/solarwinds_apm/support/trace_state.rb +69 -0
  127. data/lib/solarwinds_apm/support/trace_string.rb +89 -0
  128. data/lib/solarwinds_apm/support/transaction_metrics.rb +67 -0
  129. data/lib/solarwinds_apm/support/transaction_settings.rb +233 -0
  130. data/lib/solarwinds_apm/support/x_trace_options.rb +113 -0
  131. data/lib/solarwinds_apm/support.rb +12 -0
  132. data/lib/solarwinds_apm/support_report.rb +113 -0
  133. data/lib/solarwinds_apm/test.rb +165 -0
  134. data/lib/solarwinds_apm/thread_local.rb +26 -0
  135. data/lib/solarwinds_apm/util.rb +334 -0
  136. data/lib/solarwinds_apm/version.rb +17 -0
  137. data/lib/solarwinds_apm.rb +72 -0
  138. data/log/.keep +0 -0
  139. data/log/postgresql/.keep +0 -0
  140. data/solarwinds_apm.gemspec +52 -0
  141. data/yardoc_frontpage.md +24 -0
  142. metadata +228 -0
@@ -0,0 +1,356 @@
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
+ module SolarWindsAPM
14
+ module API
15
+ ##
16
+ # This modules provides the X-Trace logging facilities.
17
+ #
18
+ # These are the lower level methods, please see SolarWindsAPM::SDK
19
+ # for the higher level methods
20
+ #
21
+ # If using these directly make sure to always match a start/end and entry/exit to
22
+ # avoid broken traces.
23
+ module Logging
24
+ @@ints_or_nil = [Integer, Float, NilClass, String]
25
+
26
+ ##
27
+ # Public: Report an event in an active trace.
28
+ #
29
+ # ==== Arguments
30
+ #
31
+ # * +layer+ - The layer the reported event belongs to
32
+ # * +label+ - The label for the reported event. See SDK documentation for reserved labels and usage.
33
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
34
+ # * +event+ - An event to be used instead of generating a new one (see also start_trace_with_target)
35
+ #
36
+ # ==== Example
37
+ #
38
+ # SolarWindsAPM::API.log('logical_layer', 'entry')
39
+ # SolarWindsAPM::API.log('logical_layer', 'info', { :list_length => 20 })
40
+ # SolarWindsAPM::API.log('logical_layer', 'exit')
41
+ #
42
+ # Returns nothing.
43
+ def log(layer, label, kvs = {}, event = nil)
44
+ return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
45
+
46
+ event ||= SolarWindsAPM::Context.createEvent
47
+ log_event(layer, label, event, kvs)
48
+ end
49
+
50
+ ##
51
+ # Public: Report an exception.
52
+ #
53
+ # ==== Arguments
54
+ #
55
+ # * +layer+ - The layer the reported event belongs to
56
+ # * +exception+ - The exception to report, responds to :message and :backtrace(optional)
57
+ # * +kvs+ - Custom params if you want to log extra information
58
+ #
59
+ # ==== Example
60
+ #
61
+ # begin
62
+ # my_iffy_method
63
+ # rescue Exception => e
64
+ # SolarWindsAPM::API.log_exception('rails', e, { user: user_id })
65
+ # raise
66
+ # end
67
+ #
68
+ # Returns nothing.
69
+ def log_exception(layer, exception, kvs = {})
70
+ return SolarWindsAPM::Context.toString if !SolarWindsAPM.tracing? || exception.instance_variable_get(:@exn_logged)
71
+
72
+ unless exception
73
+ SolarWindsAPM.logger.debug '[solarwinds_apm/debug] log_exception called with nil exception'
74
+ return SolarWindsAPM::Context.toString
75
+ end
76
+
77
+ exception.message << exception.class.name if exception.message.length < 4
78
+ kvs.merge!(:Spec => 'error',
79
+ :ErrorClass => exception.class.name,
80
+ :ErrorMsg => exception.message)
81
+
82
+ if exception.respond_to?(:backtrace) && exception.backtrace
83
+ kvs.merge!(:Backtrace => exception.backtrace.join("\r\n"))
84
+ end
85
+
86
+ exception.instance_variable_set(:@exn_logged, true)
87
+ log(layer, :error, kvs)
88
+ end
89
+
90
+ ##
91
+ # Public: Start a trace depending on TransactionSettings
92
+ # or decide whether or not to start a trace, and report an entry event
93
+ # appropriately.
94
+ #
95
+ # ==== Arguments
96
+ #
97
+ # * +layer+ - The layer the reported event belongs to
98
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
99
+ # * +headers+ - the request headers, they may contain w3c trace_context data
100
+ # * +settings+ - An instance of TransactionSettings
101
+ # * +url+ - String of the current url, it may be configured to be excluded from tracing
102
+ #
103
+ # ==== Example
104
+ #
105
+ # SolarWindsAPM::API.log_start(:layer_name, { :id => @user.id })
106
+ #
107
+ # Returns a metadata string if we are tracing
108
+ #
109
+ def log_start(layer, kvs = {}, headers = {}, settings = nil, url = nil)
110
+ return unless SolarWindsAPM.loaded
111
+
112
+ # This is a bit ugly, but here is the best place to reset the layer_op thread local var.
113
+ SolarWindsAPM.layer_op = nil
114
+
115
+ settings ||= SolarWindsAPM::TransactionSettings.new(url, headers)
116
+ SolarWindsAPM.trace_context.add_traceinfo(kvs)
117
+ tracestring = SolarWindsAPM.trace_context.tracestring
118
+
119
+ if settings.do_sample
120
+ kvs[:SampleRate] = settings.rate
121
+ kvs[:SampleSource] = settings.source
122
+
123
+ SolarWindsAPM::TraceString.set_sampled(tracestring) if tracestring
124
+ event = create_start_event(tracestring)
125
+ log_event(layer, :entry, event, kvs)
126
+ else
127
+ create_nontracing_context(tracestring)
128
+ SolarWindsAPM::Context.toString
129
+ end
130
+ end
131
+
132
+ ##
133
+ # Public: Report an exit event and potentially clear the tracing context.
134
+ #
135
+ # ==== Arguments
136
+ #
137
+ # * +layer+ - The layer the reported event belongs to
138
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
139
+ #
140
+ # ==== Example
141
+ #
142
+ # SolarWindsAPM::API.log_end(:layer_name, { :id => @user.id })
143
+ #
144
+ # Returns a metadata string if we are tracing
145
+ #
146
+ def log_end(layer, kvs = {}, event = nil)
147
+ return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
148
+
149
+ event ||= SolarWindsAPM::Context.createEvent
150
+ log_event(layer, :exit, event, kvs)
151
+ ensure
152
+ SolarWindsAPM::Context.clear
153
+ SolarWindsAPM.trace_context = nil
154
+ SolarWindsAPM.transaction_name = nil
155
+ end
156
+
157
+ ##
158
+ # Public: Log an entry event
159
+ #
160
+ # A helper method to create and log an entry event
161
+ #
162
+ # ==== Arguments
163
+ #
164
+ # * +layer+ - The layer the reported event belongs to
165
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
166
+ # * +op+ - To identify the current operation being traced. Used to avoid double tracing recursive calls.
167
+ #
168
+ # ==== Example
169
+ #
170
+ # SolarWindsAPM::API.log_entry(:layer_name, { :id => @user.id })
171
+ #
172
+ # Returns a metadata string
173
+ #
174
+ def log_entry(layer, kvs = {}, op = nil)
175
+ return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
176
+
177
+ if op
178
+ # check if re-entry but also add op to list for log_exit
179
+ re_entry = SolarWindsAPM.layer_op&.last == op.to_sym
180
+ SolarWindsAPM.layer_op = (SolarWindsAPM.layer_op || []) << op.to_sym
181
+ return SolarWindsAPM::Context.toString if re_entry
182
+ end
183
+
184
+ event ||= SolarWindsAPM::Context.createEvent
185
+ log_event(layer, :entry, event, kvs)
186
+ end
187
+
188
+ ##
189
+ # Public: Log an info event
190
+ #
191
+ # A helper method to create and log an info event
192
+ #
193
+ # ==== Arguments
194
+ #
195
+ # * +layer+ - The layer the reported event belongs to
196
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
197
+ #
198
+ # ==== Example
199
+ #
200
+ # SolarWindsAPM::API.log_info(:layer_name, { :id => @user.id })
201
+ #
202
+ # Returns a metadata string if we are tracing
203
+ #
204
+ def log_info(layer, kvs = {})
205
+ return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
206
+
207
+ kvs[:Spec] = 'info'
208
+ log_event(layer, :info, SolarWindsAPM::Context.createEvent, kvs)
209
+ end
210
+
211
+ ##
212
+ # Public: Log an exit event
213
+ #
214
+ # A helper method to create and log an exit event
215
+ #
216
+ # ==== Arguments
217
+ #
218
+ # * +layer+ - The layer the reported event belongs to
219
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
220
+ # * +op+ - Used to avoid double tracing recursive calls, needs to be the same in +log_exit+ that corresponds to a
221
+ # +log_entry+
222
+ #
223
+ # ==== Example
224
+ #
225
+ # SolarWindsAPM::API.log_exit(:layer_name, { :id => @user.id })
226
+ #
227
+ # Returns a metadata string if we are tracing
228
+ def log_exit(layer, kvs = {}, op = nil)
229
+ return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
230
+
231
+ if op
232
+ if SolarWindsAPM.layer_op&.last == op.to_sym
233
+ SolarWindsAPM.layer_op.pop
234
+ else
235
+ SolarWindsAPM.logger.warn "[ruby/logging] op parameter of exit event doesn't correspond to an entry event op"
236
+ end
237
+ # check if the next op is the same, don't log event if so
238
+ return SolarWindsAPM::Context.toString if SolarWindsAPM.layer_op&.last == op.to_sym
239
+ end
240
+
241
+ log_event(layer, :exit, SolarWindsAPM::Context.createEvent, kvs)
242
+ end
243
+
244
+ ##
245
+ #:nodoc:
246
+ # Internal: Reports agent init to the collector
247
+ #
248
+ # ==== Arguments
249
+ #
250
+ # * +layer+ - The layer the reported event belongs to
251
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event
252
+ def log_init(layer = :rack, kvs = {})
253
+ context = SolarWindsAPM::Metadata.makeRandom
254
+ return SolarWindsAPM::Context.toString unless context.isValid
255
+
256
+ event = context.createEvent
257
+ event.addInfo(SW_APM_STR_LAYER, layer.to_s)
258
+ event.addInfo(SW_APM_STR_LABEL, 'single')
259
+ kvs.each do |k, v|
260
+ event.addInfo(k, v.to_s)
261
+ end
262
+
263
+ SolarWindsAPM::Reporter.sendStatus(event, context)
264
+ SolarWindsAPM::Context.toString
265
+ end
266
+
267
+ private
268
+
269
+ ##
270
+ #:nodoc:
271
+ # @private
272
+ # Internal: Report an event.
273
+ #
274
+ # ==== Arguments
275
+ #
276
+ # * +layer+ - The layer the reported event belongs to
277
+ # * +label+ - The label for the reported event. See API documentation for reserved labels and usage.
278
+ # * +event+ - The pre-existing SolarWindsAPM context event. See SolarWindsAPM::Context.createEvent
279
+ # * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
280
+ #
281
+ # ==== Example
282
+ #
283
+ # entry = SolarWindsAPM::Context.createEvent
284
+ # SolarWindsAPM::API.log_event(:layer_name, 'entry', entry_event, { :id => @user.id })
285
+ #
286
+ # exit_event = SolarWindsAPM::Context.createEvent
287
+ # exit_event.addEdge(entry.getMetadata)
288
+ # SolarWindsAPM::API.log_event(:layer_name, 'exit', exit_event, { :id => @user.id })
289
+ #
290
+ def log_event(layer, label, event, kvs = {})
291
+ event.addInfo(SW_APM_STR_LAYER, layer.to_s.freeze) if layer
292
+ event.addInfo(SW_APM_STR_LABEL, label.to_s.freeze)
293
+
294
+ SolarWindsAPM.layer = layer.to_sym if label == :entry
295
+ SolarWindsAPM.layer = nil if label == :exit
296
+
297
+ kvs.each do |k, v|
298
+ value = nil
299
+
300
+ next unless valid_key? k
301
+
302
+ if @@ints_or_nil.include?(v.class)
303
+ value = v
304
+ elsif v.class == Set
305
+ value = v.to_a.to_s
306
+ else
307
+ value = v.to_s if v.respond_to?(:to_s)
308
+ end
309
+
310
+ begin
311
+ event.addInfo(k.to_s, value)
312
+ rescue ArgumentError => e
313
+ SolarWindsAPM.logger.debug "[solarwinds_apm/debug] Couldn't add event KV: #{k} => #{v.class}"
314
+ SolarWindsAPM.logger.debug "[solarwinds_apm/debug] #{e.message}"
315
+ end
316
+ end if !kvs.nil? && kvs.any?
317
+
318
+ SolarWindsAPM::Reporter.sendReport(event)
319
+ SolarWindsAPM::Context.toString
320
+ end
321
+
322
+ def create_start_event(tracestring = nil)
323
+ if SolarWindsAPM::TraceString.sampled?(tracestring)
324
+ md = SolarWindsAPM::Metadata.fromString(tracestring)
325
+ SolarWindsAPM::Context.fromString(tracestring)
326
+ md.createEvent
327
+ else
328
+ md = SolarWindsAPM::Metadata.makeRandom(true)
329
+ SolarWindsAPM::Context.set(md)
330
+ SolarWindsAPM::Event.startTrace(md)
331
+ end
332
+ end
333
+
334
+ public
335
+
336
+ def create_nontracing_context(tracestring)
337
+ if SolarWindsAPM::TraceString.valid?(tracestring)
338
+ # continue valid incoming tracestring
339
+ # use it for current context, ensuring sample bit is not set
340
+ SolarWindsAPM::TraceString.unset_sampled(tracestring)
341
+ SolarWindsAPM::Context.fromString(tracestring)
342
+ else
343
+ # discard invalid incoming tracestring
344
+ # create a new context, ensuring sample bit not set
345
+ md = SolarWindsAPM::Metadata.makeRandom(false)
346
+ SolarWindsAPM::Context.fromString(md.toString)
347
+ end
348
+ end
349
+
350
+ # need to set the module context to public, otherwise the following `extends` will be private in api.rb
351
+
352
+ public
353
+
354
+ end
355
+ end
356
+ 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 SolarWindsAPM
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 SolarWindsAPM
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] = SolarWindsAPM::Span.createSpan(transaction_name, nil, duration, error)
34
+ SolarWindsAPM.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 SolarWindsAPM.transaction_name
51
+ SolarWindsAPM.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,98 @@
1
+ #--
2
+ # Copyright (c) 2016 SolarWinds, LLC.
3
+ # All rights reserved.
4
+ #++
5
+
6
+ require 'pp'
7
+
8
+ module SolarWindsAPM
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 solarwinds_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, :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: Pretty print a list of arguments for reporting
50
+ #
51
+ # args - the list of arguments to work on
52
+ #
53
+ # Returns a pretty string representation of arguments
54
+ def pps(*args)
55
+ old_out = $stdout
56
+ begin
57
+ s = StringIO.new
58
+ $stdout = s
59
+ pp(*args)
60
+ ensure
61
+ $stdout = old_out
62
+ end
63
+ s.string
64
+ end
65
+
66
+ # Internal: Determine a string to report representing klass
67
+ #
68
+ # args - an instance of a Class, a Class or a Module
69
+ #
70
+ # Returns a string representation of klass
71
+ def get_class_name(klass)
72
+ kv = {}
73
+
74
+ if klass.to_s =~ /::/
75
+ klass.class.to_s.rpartition('::').last
76
+ else
77
+ if klass.is_a?(Class) && klass.is_a?(Module)
78
+ # Class
79
+ kv['Class'] = klass.to_s
80
+
81
+ elsif !klass.is_a?(Class) && !klass.is_a?(Module)
82
+ # Class instance
83
+ kv['Class'] = klass.class.to_s
84
+
85
+ else
86
+ # Module
87
+ kv['Module'] = klass.to_s
88
+ end
89
+ end
90
+ kv
91
+ end
92
+
93
+ def xtrace_v2?(xtr)
94
+ xtr && xtr.start_with?('2B')
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module SolarWindsAPM
5
+
6
+ module API
7
+ extend SolarWindsAPM::API::Logging
8
+ extend SolarWindsAPM::API::Metrics
9
+ extend SolarWindsAPM::API::LayerInit
10
+ extend SolarWindsAPM::API::Util
11
+
12
+ require_relative './sdk/trace_context_headers'
13
+ require_relative './sdk/tracing'
14
+ require_relative './sdk/custom_metrics'
15
+ require_relative './sdk/current_trace_info'
16
+ require_relative './sdk/logging' # to make sure it is loaded <- not very elegant
17
+
18
+ extend SolarWindsAPM::SDK::Tracing
19
+ extend SolarWindsAPM::SDK::CustomMetrics
20
+ end
21
+ end