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,67 @@
1
+ # Copyright (c) 2018 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module SolarWindsAPM
5
+ ##
6
+ # This module sends the duration of the call and
7
+ # sets the transaction_name
8
+ #
9
+ class TransactionMetrics
10
+ class << self
11
+
12
+ ##
13
+ # sends the duration of the call and
14
+ # sets the transaction_name
15
+ def metrics(env, settings)
16
+ if settings.do_metrics
17
+ req = ::Rack::Request.new(env)
18
+ # TODO rails 3x is not supported anymore ...
19
+ url = req.url # saving it here because rails3.2 overrides it when there is a 500 error
20
+ start = Time.now
21
+
22
+ begin
23
+ status, headers, response = yield
24
+
25
+ SolarWindsAPM.transaction_name = send_metrics(env, req, url, start, status)
26
+ rescue
27
+ SolarWindsAPM.transaction_name = send_metrics(env, req, url, start, status || '500')
28
+ raise
29
+ end
30
+ else
31
+ status, headers, response = yield
32
+ SolarWindsAPM.transaction_name = "#{domain(req)}#{transaction_name(env)}" if settings.do_sample
33
+ end
34
+
35
+ [status, headers, response]
36
+ end
37
+
38
+ private
39
+
40
+ def send_metrics(env, req, url, start, status)
41
+ name = transaction_name(env)
42
+
43
+ status = status.to_i
44
+ error = status.between?(500,599) ? 1 : 0
45
+ duration =(1000 * 1000 * (Time.now - start)).round(0)
46
+ method = req.request_method
47
+ # SolarWindsAPM.logger.warn "%%% Sending metrics: #{name}, #{url}, #{status} %%%"
48
+ SolarWindsAPM::Span.createHttpSpan(name, url, domain(req), duration, status, method, error) || ''
49
+ end
50
+
51
+ def domain(req)
52
+ if SolarWindsAPM::Config['transaction_name']['prepend_domain']
53
+ [80, 443].include?(req.port) ? req.host : "#{req.host}:#{req.port}"
54
+ end
55
+ end
56
+
57
+ def transaction_name(env)
58
+ return SolarWindsAPM.transaction_name if SolarWindsAPM.transaction_name
59
+
60
+ if env['solarwinds_apm.controller'] && env['solarwinds_apm.action']
61
+ [env['solarwinds_apm.controller'], env['solarwinds_apm.action']].join('.')
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,233 @@
1
+ # Copyright (c) 2018 SolarWinds, LLC.
2
+ # All rights reserved.
3
+ #
4
+
5
+ AO_TRACING_ENABLED = 1
6
+ AO_TRACING_DISABLED = 0
7
+ AO_TRACING_UNSET = -1
8
+
9
+ AO_TRACING_DECISIONS_OK = 0
10
+
11
+ OBOE_SETTINGS_UNSET = -1
12
+
13
+ module SolarWindsAPM
14
+ ##
15
+ # This module helps with setting up the transaction filters and applying them
16
+ #
17
+ class TransactionSettings
18
+
19
+ attr_accessor :do_sample, :do_metrics
20
+ attr_reader :auth_msg, :do_propagate, :status_msg, :type, :source, :rate, :tracestring, :sw_member_value
21
+
22
+ def initialize(url = '', headers = {}, options = nil)
23
+ @do_metrics = false
24
+ @do_sample = false
25
+ @do_propagate = true
26
+
27
+ SolarWindsAPM.trace_context = SolarWindsAPM::TraceContext.new(headers)
28
+ @tracestring = SolarWindsAPM.trace_context.tracestring
29
+ @sw_member_value = SolarWindsAPM.trace_context.sw_member_value
30
+ tracing_mode = AO_TRACING_ENABLED
31
+
32
+ # TODO
33
+ # NH-11132 will address this
34
+ # incoming tracing info has priority over existing context
35
+ # if SolarWindsAPM::Context.isValid && !@sw_member_value
36
+ # @do_sample = SolarWindsAPM.tracing?
37
+ # return
38
+ # end
39
+
40
+ if url && asset?(url)
41
+ @do_propagate = false
42
+ return
43
+ end
44
+
45
+ if tracing_mode_disabled? && !tracing_enabled?(url) ||
46
+ tracing_disabled?(url)
47
+
48
+ tracing_mode = AO_TRACING_DISABLED
49
+ end
50
+
51
+ # args (all optional)
52
+ # 0 char const *in_xtrace
53
+ # 1 char const *tracestate
54
+ # 2 int custom_tracing_mode
55
+ # 3 int custom_sample_rate
56
+ # 4 int request_type
57
+ # 5 int custom_trigger_mode
58
+ # 6 char const *header_options
59
+ # 7 char const *header_signature
60
+ # 8 long header_timestamp
61
+ args = [@tracestring, @sw_member_value] #0,1
62
+ args << tracing_mode #2
63
+ args << (SolarWindsAPM::Config[:sample_rate] || OBOE_SETTINGS_UNSET) #3
64
+
65
+ if options && (options.options || options.signature)
66
+ args << (options.trigger_trace ? 1 : 0) #4
67
+ args << (trigger_tracing_mode_disabled? ? 0 : 1) #5
68
+ args << options.options #6
69
+ args << options.signature #7
70
+ args << options.timestamp #8
71
+ end
72
+
73
+ metrics, sample, @rate, @source, @bucket_rate, @bucket_cap, @type, @auth, @status_msg, @auth_msg, @status =
74
+ SolarWindsAPM::Context.getDecisions(*args)
75
+
76
+ if @status > AO_TRACING_DECISIONS_OK
77
+ SolarWindsAPM.logger.warn "[solarwinds_apm/sample] Problem getting the sampling decisions: #{@status_msg} code: #{@status}"
78
+ end
79
+
80
+ @do_metrics = metrics > 0
81
+ @do_sample = sample > 0
82
+ end
83
+
84
+ def to_s
85
+ "do_propagate: #{do_propagate}, do_sample: #{do_sample}, do_metrics: #{do_metrics} rate: #{rate}, source: #{source}"
86
+ end
87
+
88
+ def add_kvs(kvs)
89
+ kvs[:SampleRate] = @rate
90
+ kvs[:SampleSource] = @source
91
+ end
92
+
93
+ def triggered_trace?
94
+ @type == 1
95
+ end
96
+
97
+ def auth_ok?
98
+ # @auth is undefined if initialize is called with an existing context
99
+ !@auth || @auth < 1
100
+ end
101
+
102
+ private
103
+
104
+ ##
105
+ # check the config setting for :tracing_mode
106
+ def tracing_mode_disabled?
107
+ SolarWindsAPM::Config[:tracing_mode] &&
108
+ [:disabled, :never].include?(SolarWindsAPM::Config[:tracing_mode])
109
+ end
110
+
111
+ ##
112
+ # tracing_enabled?
113
+ #
114
+ # Given a path, this method determines whether it matches any of the
115
+ # regexps to exclude it from metrics and traces
116
+ #
117
+ def tracing_enabled?(url)
118
+ return false unless SolarWindsAPM::Config[:url_enabled_regexps].is_a? Array
119
+ # once we only support Ruby >= 2.4.0 use `match?` instead of `=~`
120
+ return SolarWindsAPM::Config[:url_enabled_regexps].any? { |regex| regex =~ url }
121
+ rescue => e
122
+ SolarWindsAPM.logger.warn "[SolarWindsAPM/filter] Could not apply :enabled filter to path. #{e.inspect}"
123
+ true
124
+ end
125
+
126
+ ##
127
+ # tracing_disabled?
128
+ #
129
+ # Given a path, this method determines whether it matches any of the
130
+ # regexps to exclude it from metrics and traces
131
+ #
132
+ def tracing_disabled?(url)
133
+ return false unless SolarWindsAPM::Config[:url_disabled_regexps].is_a? Array
134
+ # once we only support Ruby >= 2.4.0 use `match?` instead of `=~`
135
+ return SolarWindsAPM::Config[:url_disabled_regexps].any? { |regex| regex =~ url }
136
+ rescue => e
137
+ SolarWindsAPM.logger.warn "[SolarWindsAPM/filter] Could not apply :disabled filter to path. #{e.inspect}"
138
+ false
139
+ end
140
+
141
+ def trigger_tracing_mode_disabled?
142
+ SolarWindsAPM::Config[:trigger_tracing_mode] &&
143
+ SolarWindsAPM::Config[:trigger_tracing_mode] == :disabled
144
+ end
145
+
146
+ ##
147
+ # asset?
148
+ #
149
+ # Given a path, this method determines whether it is a static asset
150
+ #
151
+ def asset?(path)
152
+ return false unless SolarWindsAPM::Config[:dnt_compiled]
153
+ # once we only support Ruby >= 2.4.0 use `match?` instead of `=~`
154
+ return SolarWindsAPM::Config[:dnt_compiled] =~ path
155
+ rescue => e
156
+ SolarWindsAPM.logger.warn "[SolarWindsAPM/filter] Could not apply do-not-trace filter to path. #{e.inspect}"
157
+ false
158
+ end
159
+
160
+ public
161
+
162
+ class << self
163
+
164
+ def asset?(path)
165
+ return false unless SolarWindsAPM::Config[:dnt_compiled]
166
+ # once we only support Ruby >= 2.4.0 use `match?` instead of `=~`
167
+ return SolarWindsAPM::Config[:dnt_compiled] =~ path
168
+ rescue => e
169
+ SolarWindsAPM.logger.warn "[SolarWindsAPM/filter] Could not apply do-not-trace filter to path. #{e.inspect}"
170
+ false
171
+ end
172
+
173
+ def compile_url_settings(settings)
174
+ if !settings.is_a?(Array) || settings.empty?
175
+ reset_url_regexps
176
+ return
177
+ end
178
+
179
+ # `tracing: disabled` is the default
180
+ disabled = settings.select { |v| !v.has_key?(:tracing) || v[:tracing] == :disabled }
181
+ enabled = settings.select { |v| v[:tracing] == :enabled }
182
+
183
+ SolarWindsAPM::Config[:url_enabled_regexps] = compile_regexp(enabled)
184
+ SolarWindsAPM::Config[:url_disabled_regexps] = compile_regexp(disabled)
185
+ end
186
+
187
+ def compile_regexp(settings)
188
+ regexp_regexp = compile_url_settings_regexp(settings)
189
+ extensions_regexp = compile_url_settings_extensions(settings)
190
+
191
+ regexps = [regexp_regexp, extensions_regexp].flatten.compact
192
+
193
+ regexps.empty? ? nil : regexps
194
+ end
195
+
196
+ def compile_url_settings_regexp(value)
197
+ regexps = value.select do |v|
198
+ v.key?(:regexp) &&
199
+ !(v[:regexp].is_a?(String) && v[:regexp].empty?) &&
200
+ !(v[:regexp].is_a?(Regexp) && v[:regexp].inspect == '//')
201
+ end
202
+
203
+ regexps.map! do |v|
204
+ begin
205
+ v[:regexp].is_a?(String) ? Regexp.new(v[:regexp], v[:opts]) : Regexp.new(v[:regexp])
206
+ rescue
207
+ SolarWindsAPM.logger.warn "[solarwinds_apm/config] Problem compiling transaction_settings item #{v}, will ignore."
208
+ nil
209
+ end
210
+ end
211
+ regexps.keep_if { |v| !v.nil? }
212
+ regexps.empty? ? nil : regexps
213
+ end
214
+
215
+ def compile_url_settings_extensions(value)
216
+ extensions = value.select do |v|
217
+ v.key?(:extensions) &&
218
+ v[:extensions].is_a?(Array) &&
219
+ !v[:extensions].empty?
220
+ end
221
+ extensions = extensions.map { |v| v[:extensions] }.flatten
222
+ extensions.keep_if { |v| v.is_a?(String) }
223
+
224
+ extensions.empty? ? nil : Regexp.new("(#{Regexp.union(extensions).source})(\\?.+){0,1}$")
225
+ end
226
+
227
+ def reset_url_regexps
228
+ SolarWindsAPM::Config[:url_enabled_regexps] = nil
229
+ SolarWindsAPM::Config[:url_disabled_regexps] = nil
230
+ end
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,113 @@
1
+ # Copyright (c) 2019 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module SolarWindsAPM
5
+ class XTraceOptions
6
+
7
+ attr_reader :options, :signature, :trigger_trace, :timestamp
8
+ attr_reader :sw_keys, :custom_kvs, :ignored # used in tests
9
+
10
+ ##
11
+ # use by Trigger Tracing
12
+ # TODO - refactor for w3c when ticket ready
13
+ #
14
+ # Params:
15
+ # +options+ : An X-Trace-Options @options string
16
+ # +signature+ : hmac signature to pass on for verification
17
+ #
18
+ # populates:
19
+ # - @force_trace (true|false)
20
+ # - @app_id (as given by Pingdom)
21
+ # - @probe_id (as given by Pingdom)
22
+ # - @loc (2 characters given by Pingdom)
23
+ # - @custom_kvs (hash)
24
+ # - @ignored (array)
25
+ #
26
+ # split it up by ';' separator
27
+ # kv assignment by '='
28
+ # currently valid keys:
29
+ # - force_trace (valid: 0,1) unless we use just a kv
30
+ # - application_id (format defined by pingdom (no validation))
31
+ # - probe_id
32
+ # - custom_* (';=' not allowed in key), value (validate max. length)
33
+ # - ts (unix timestamp)
34
+ # - other keys will be reported in the response options as ignored
35
+
36
+ def initialize(options, signature = nil)
37
+ @options = options.dup
38
+ @signature = signature.dup
39
+ @trigger_trace = false
40
+ @custom_kvs = {}
41
+ @sw_keys = nil
42
+ @ignored = []
43
+ @timestamp = 0
44
+
45
+ options&.split(/;+/)&.each do |val|
46
+ k = val.split('=', 2)
47
+
48
+ next unless k[0] # it can be nil, eg when the header starts with ';'
49
+
50
+ k[0]&.strip!
51
+ case k[0]
52
+ when 'trigger-trace'
53
+ if k[1]
54
+ @ignored << 'trigger-trace'
55
+ else
56
+ @trigger_trace = true
57
+ end
58
+ when 'sw-keys'
59
+ if @sw_keys
60
+ SolarWindsAPM.logger.info "[solarwinds_apm/x-trace-options] Duplicate key: #{k[0]}"
61
+ else
62
+ @sw_keys = k[1].strip
63
+ end
64
+ when /^custom-[^\s]*$/
65
+ if @custom_kvs[k[0]]
66
+ SolarWindsAPM.logger.info "[solarwinds_apm/x-trace-options] Duplicate key: #{k[0]}"
67
+ else
68
+ @custom_kvs[k[0]] = k[1].strip
69
+ end
70
+ when 'ts'
71
+ if @timestamp > 0
72
+ SolarWindsAPM.logger.info "[solarwinds_apm/x-trace-options] Duplicate key: #{k[0]}"
73
+ else
74
+ @timestamp = k[1].to_i
75
+ end
76
+ else
77
+ @ignored << k[0]
78
+ end
79
+ end
80
+ unless @ignored.empty?
81
+ msg = "[solarwinds_apm/x-trace-options] Some keys were ignored: #{@ignored.join(',')}"
82
+ SolarWindsAPM.logger.info(msg)
83
+ end
84
+ end
85
+
86
+ def add_kvs(kvs, settings)
87
+ return unless settings.auth_ok?
88
+
89
+ @custom_kvs.each { |k,v| kvs[k] = v } unless @custom_kvs.empty?
90
+ kvs['SWKeys'] = @sw_keys if @sw_keys
91
+ kvs['TriggeredTrace'] = true if settings.triggered_trace?
92
+ end
93
+
94
+ def add_response_header(headers, settings)
95
+ return unless options
96
+
97
+ response = []
98
+ response << "auth=#{settings.auth_msg}" if @signature
99
+ if settings.auth_ok?
100
+ if @trigger_trace
101
+ trigger_msg = settings.tracestring && settings.type == 0 ? 'ignored' : settings.status_msg
102
+ else
103
+ trigger_msg = 'not-requested'
104
+ end
105
+ response << "trigger-trace=#{trigger_msg}"
106
+ response << "ignored=#{@ignored.join(',')}" unless @ignored.empty?
107
+ end
108
+
109
+ headers['X-Trace-Options-Response'] = response.join(';')
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,12 @@
1
+ # Copyright (c) SolarWinds, LLC.
2
+ # All rights reserved
3
+
4
+ pattern = File.join(File.dirname(__FILE__), 'support', '*.rb')
5
+ Dir.glob(pattern) do |f|
6
+ begin
7
+ require f
8
+ rescue => e
9
+ SolarWindsAPM.logger.error "[solarwinds_apm/loading] Error loading support file '#{f}' : #{e}"
10
+ SolarWindsAPM.logger.debug "[solarwinds_apm/loading] #{e.backtrace.first}"
11
+ end
12
+ end
@@ -0,0 +1,113 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ require 'rbconfig'
5
+ require 'logger'
6
+
7
+ module SolarWindsAPM
8
+ ##
9
+ # This module is used to debug problematic setups and/or environments.
10
+ # Depending on the environment, output may be to stdout or the framework
11
+ # log file (e.g. log/production.log)
12
+
13
+ ##
14
+ # yesno
15
+ #
16
+ # Utility method to translate value/nil to "yes"/"no" strings
17
+ def self.yesno(x)
18
+ x ? 'yes' : 'no'
19
+ end
20
+
21
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
22
+ def self.support_report
23
+ @logger_level = SolarWindsAPM.logger.level
24
+ SolarWindsAPM.logger.level = ::Logger::DEBUG
25
+
26
+ SolarWindsAPM.logger.warn '********************************************************'
27
+ SolarWindsAPM.logger.warn '* BEGIN SolarWindsAPM Support Report'
28
+ SolarWindsAPM.logger.warn '* Please email the output of this report to technicalsupport@solarwinds.com'
29
+ SolarWindsAPM.logger.warn '********************************************************'
30
+ SolarWindsAPM.logger.warn "Ruby: #{RUBY_DESCRIPTION}"
31
+ SolarWindsAPM.logger.warn "$0: #{$0}"
32
+ SolarWindsAPM.logger.warn "$1: #{$1}" unless $1.nil?
33
+ SolarWindsAPM.logger.warn "$2: #{$2}" unless $2.nil?
34
+ SolarWindsAPM.logger.warn "$3: #{$3}" unless $3.nil?
35
+ SolarWindsAPM.logger.warn "$4: #{$4}" unless $4.nil?
36
+ SolarWindsAPM.logger.warn "SolarWindsAPM.loaded == #{SolarWindsAPM.loaded}"
37
+
38
+ on_heroku = SolarWindsAPM.heroku?
39
+ SolarWindsAPM.logger.warn "On Heroku?: #{yesno(on_heroku)}"
40
+ if on_heroku
41
+ SolarWindsAPM.logger.warn "SW_APM_URL: #{ENV['SW_APM_URL']}"
42
+ end
43
+
44
+ SolarWindsAPM.logger.warn "SolarWindsAPM::Ruby defined?: #{yesno(defined?(SolarWindsAPM::Ruby))}"
45
+ SolarWindsAPM.logger.warn "SolarWindsAPM.reporter: #{SolarWindsAPM.reporter}"
46
+
47
+ SolarWindsAPM.logger.warn '********************************************************'
48
+ SolarWindsAPM.logger.warn '* Frameworks'
49
+ SolarWindsAPM.logger.warn '********************************************************'
50
+
51
+ using_rails = defined?(::Rails)
52
+ SolarWindsAPM.logger.warn "Using Rails?: #{yesno(using_rails)}"
53
+ if using_rails
54
+ SolarWindsAPM.logger.warn "SolarWindsAPM::Rails loaded?: #{yesno(defined?(SolarWindsAPM::Rails))}"
55
+ if defined?(SolarWindsAPM::Rack)
56
+ SolarWindsAPM.logger.warn "SolarWindsAPM::Rack middleware loaded?: #{yesno(::Rails.configuration.middleware.include? SolarWindsAPM::Rack)}"
57
+ end
58
+ end
59
+
60
+ using_sinatra = defined?(::Sinatra)
61
+ SolarWindsAPM.logger.warn "Using Sinatra?: #{yesno(using_sinatra)}"
62
+
63
+ using_padrino = defined?(::Padrino)
64
+ SolarWindsAPM.logger.warn "Using Padrino?: #{yesno(using_padrino)}"
65
+
66
+ using_grape = defined?(::Grape)
67
+ SolarWindsAPM.logger.warn "Using Grape?: #{yesno(using_grape)}"
68
+
69
+ SolarWindsAPM.logger.warn '********************************************************'
70
+ SolarWindsAPM.logger.warn '* ActiveRecord Adapter'
71
+ SolarWindsAPM.logger.warn '********************************************************'
72
+ if defined?(::ActiveRecord)
73
+ if defined?(::ActiveRecord::Base.connection.adapter_name)
74
+ SolarWindsAPM.logger.warn "ActiveRecord adapter: #{::ActiveRecord::Base.connection.adapter_name}"
75
+ end
76
+ else
77
+ SolarWindsAPM.logger.warn 'No ActiveRecord'
78
+ end
79
+
80
+ SolarWindsAPM.logger.warn '********************************************************'
81
+ SolarWindsAPM.logger.warn '* SolarWindsAPM::Config Values'
82
+ SolarWindsAPM.logger.warn '********************************************************'
83
+ SolarWindsAPM::Config.print_config
84
+
85
+ SolarWindsAPM.logger.warn '********************************************************'
86
+ SolarWindsAPM.logger.warn '* OS, Platform + Env'
87
+ SolarWindsAPM.logger.warn '********************************************************'
88
+ SolarWindsAPM.logger.warn "host_os: " + RbConfig::CONFIG['host_os']
89
+ SolarWindsAPM.logger.warn "sitearch: " + RbConfig::CONFIG['sitearch']
90
+ SolarWindsAPM.logger.warn "arch: " + RbConfig::CONFIG['arch']
91
+ SolarWindsAPM.logger.warn RUBY_PLATFORM
92
+ SolarWindsAPM.logger.warn "RACK_ENV: #{ENV['RACK_ENV']}"
93
+ SolarWindsAPM.logger.warn "RAILS_ENV: #{ENV['RAILS_ENV']}" if using_rails
94
+
95
+ SolarWindsAPM.logger.warn '********************************************************'
96
+ SolarWindsAPM.logger.warn '* Raw __Init KVs'
97
+ SolarWindsAPM.logger.warn '********************************************************'
98
+ platform_info = SolarWindsAPM::Util.build_init_report
99
+ platform_info.each { |k,v|
100
+ SolarWindsAPM.logger.warn "#{k}: #{v}"
101
+ }
102
+
103
+ SolarWindsAPM.logger.warn '********************************************************'
104
+ SolarWindsAPM.logger.warn '* END SolarWindsAPM Support Report'
105
+ SolarWindsAPM.logger.warn '* Support Email: technicalsupport@solarwinds.com'
106
+ SolarWindsAPM.logger.warn '* Github: https://github.com/librato/ruby-solarwinds'
107
+ SolarWindsAPM.logger.warn '********************************************************'
108
+
109
+ SolarWindsAPM.logger.level = @logger_level
110
+ nil
111
+ end
112
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
113
+ end