solarwinds_apm 5.0.0

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 (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