solarwinds_apm 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.dockerignore +5 -0
- data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
- data/.github/workflows/build_and_release_gem.yml +112 -0
- data/.github/workflows/build_for_packagecloud.yml +70 -0
- data/.github/workflows/docker-images.yml +47 -0
- data/.github/workflows/run_cpluplus_tests.yml +73 -0
- data/.github/workflows/run_tests.yml +155 -0
- data/.github/workflows/scripts/test_install.rb +23 -0
- data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
- data/.github/workflows/test_on_4_linux.yml +161 -0
- data/.gitignore +39 -0
- data/.rubocop.yml +29 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +31 -0
- data/Gemfile +14 -0
- data/LICENSE +202 -0
- data/README.md +383 -0
- data/bin/solarwinds_apm_config +15 -0
- data/examples/prepend.rb +13 -0
- data/examples/sdk_examples.rb +158 -0
- data/ext/oboe_metal/README.md +69 -0
- data/ext/oboe_metal/extconf.rb +141 -0
- data/ext/oboe_metal/extconf_local.rb +75 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/noop/noop.c +8 -0
- data/ext/oboe_metal/src/README.md +6 -0
- data/ext/oboe_metal/src/VERSION +2 -0
- data/ext/oboe_metal/src/bson/bson.h +220 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/frames.cc +247 -0
- data/ext/oboe_metal/src/frames.h +40 -0
- data/ext/oboe_metal/src/init_solarwinds_apm.cc +21 -0
- data/ext/oboe_metal/src/logging.cc +95 -0
- data/ext/oboe_metal/src/logging.h +35 -0
- data/ext/oboe_metal/src/oboe.h +1169 -0
- data/ext/oboe_metal/src/oboe_api.cpp +658 -0
- data/ext/oboe_metal/src/oboe_api.hpp +433 -0
- data/ext/oboe_metal/src/oboe_debug.h +59 -0
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +7562 -0
- data/ext/oboe_metal/src/profiling.cc +435 -0
- data/ext/oboe_metal/src/profiling.h +78 -0
- data/ext/oboe_metal/test/CMakeLists.txt +53 -0
- data/ext/oboe_metal/test/FindGMock.cmake +43 -0
- data/ext/oboe_metal/test/README.md +56 -0
- data/ext/oboe_metal/test/frames_test.cc +164 -0
- data/ext/oboe_metal/test/profiling_test.cc +93 -0
- data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
- data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
- data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
- data/ext/oboe_metal/test/test.h +11 -0
- data/ext/oboe_metal/test/test_main.cc +32 -0
- data/init.rb +4 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +172 -0
- data/lib/rails/generators/solarwinds_apm/install_generator.rb +47 -0
- data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +424 -0
- data/lib/solarwinds_apm/api/layerinit.rb +41 -0
- data/lib/solarwinds_apm/api/logging.rb +356 -0
- data/lib/solarwinds_apm/api/memcache.rb +37 -0
- data/lib/solarwinds_apm/api/metrics.rb +63 -0
- data/lib/solarwinds_apm/api/util.rb +98 -0
- data/lib/solarwinds_apm/api.rb +21 -0
- data/lib/solarwinds_apm/base.rb +160 -0
- data/lib/solarwinds_apm/config.rb +301 -0
- data/lib/solarwinds_apm/frameworks/grape.rb +96 -0
- data/lib/solarwinds_apm/frameworks/padrino.rb +78 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller.rb +100 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller5.rb +50 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_view.rb +88 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/active_record.rb +26 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +22 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +103 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/logger_formatters.rb +14 -0
- data/lib/solarwinds_apm/frameworks/rails.rb +100 -0
- data/lib/solarwinds_apm/frameworks/sinatra.rb +96 -0
- data/lib/solarwinds_apm/inst/bunny-client.rb +157 -0
- data/lib/solarwinds_apm/inst/bunny-consumer.rb +102 -0
- data/lib/solarwinds_apm/inst/curb.rb +288 -0
- data/lib/solarwinds_apm/inst/dalli.rb +89 -0
- data/lib/solarwinds_apm/inst/delayed_job.rb +100 -0
- data/lib/solarwinds_apm/inst/excon.rb +113 -0
- data/lib/solarwinds_apm/inst/faraday.rb +96 -0
- data/lib/solarwinds_apm/inst/graphql.rb +206 -0
- data/lib/solarwinds_apm/inst/grpc_client.rb +147 -0
- data/lib/solarwinds_apm/inst/grpc_server.rb +119 -0
- data/lib/solarwinds_apm/inst/httpclient.rb +181 -0
- data/lib/solarwinds_apm/inst/logger_formatter.rb +46 -0
- data/lib/solarwinds_apm/inst/logging_log_event.rb +24 -0
- data/lib/solarwinds_apm/inst/lumberjack_formatter.rb +9 -0
- data/lib/solarwinds_apm/inst/memcached.rb +86 -0
- data/lib/solarwinds_apm/inst/mongo.rb +246 -0
- data/lib/solarwinds_apm/inst/mongo2.rb +225 -0
- data/lib/solarwinds_apm/inst/moped.rb +466 -0
- data/lib/solarwinds_apm/inst/net_http.rb +60 -0
- data/lib/solarwinds_apm/inst/rack.rb +217 -0
- data/lib/solarwinds_apm/inst/rack_cache.rb +35 -0
- data/lib/solarwinds_apm/inst/redis.rb +273 -0
- data/lib/solarwinds_apm/inst/resque.rb +129 -0
- data/lib/solarwinds_apm/inst/rest-client.rb +43 -0
- data/lib/solarwinds_apm/inst/sequel.rb +241 -0
- data/lib/solarwinds_apm/inst/sidekiq-client.rb +63 -0
- data/lib/solarwinds_apm/inst/sidekiq-worker.rb +64 -0
- data/lib/solarwinds_apm/inst/typhoeus.rb +90 -0
- data/lib/solarwinds_apm/instrumentation.rb +22 -0
- data/lib/solarwinds_apm/loading.rb +65 -0
- data/lib/solarwinds_apm/logger.rb +14 -0
- data/lib/solarwinds_apm/noop/README.md +9 -0
- data/lib/solarwinds_apm/noop/context.rb +26 -0
- data/lib/solarwinds_apm/noop/metadata.rb +25 -0
- data/lib/solarwinds_apm/noop/profiling.rb +21 -0
- data/lib/solarwinds_apm/oboe_init_options.rb +191 -0
- data/lib/solarwinds_apm/ruby.rb +35 -0
- data/lib/solarwinds_apm/sdk/current_trace_info.rb +123 -0
- data/lib/solarwinds_apm/sdk/custom_metrics.rb +94 -0
- data/lib/solarwinds_apm/sdk/logging.rb +37 -0
- data/lib/solarwinds_apm/sdk/trace_context_headers.rb +69 -0
- data/lib/solarwinds_apm/sdk/tracing.rb +432 -0
- data/lib/solarwinds_apm/support/profiling.rb +22 -0
- data/lib/solarwinds_apm/support/trace_context.rb +53 -0
- data/lib/solarwinds_apm/support/trace_state.rb +69 -0
- data/lib/solarwinds_apm/support/trace_string.rb +89 -0
- data/lib/solarwinds_apm/support/transaction_metrics.rb +67 -0
- data/lib/solarwinds_apm/support/transaction_settings.rb +233 -0
- data/lib/solarwinds_apm/support/x_trace_options.rb +113 -0
- data/lib/solarwinds_apm/support.rb +12 -0
- data/lib/solarwinds_apm/support_report.rb +113 -0
- data/lib/solarwinds_apm/test.rb +165 -0
- data/lib/solarwinds_apm/thread_local.rb +26 -0
- data/lib/solarwinds_apm/util.rb +334 -0
- data/lib/solarwinds_apm/version.rb +17 -0
- data/lib/solarwinds_apm.rb +72 -0
- data/log/.keep +0 -0
- data/log/postgresql/.keep +0 -0
- data/solarwinds_apm.gemspec +52 -0
- data/yardoc_frontpage.md +24 -0
- 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
|