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