solarwinds_apm 6.0.0.preV5 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/oboe_metal/extconf.rb +5 -4
- data/ext/oboe_metal/lib/liboboe-1.0-aarch64.so.sha256 +1 -1
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-aarch64.so.sha256 +1 -1
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.sha256 +1 -1
- data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.sha256 +1 -1
- data/ext/oboe_metal/src/VERSION +1 -1
- data/ext/oboe_metal/src/oboe.h +56 -13
- data/ext/oboe_metal/src/oboe_api.cpp +105 -6
- data/ext/oboe_metal/src/oboe_api.h +121 -2
- data/ext/oboe_metal/src/oboe_debug.h +4 -315
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +2987 -549
- data/lib/oboe_metal.rb +23 -64
- data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +1 -1
- data/lib/solarwinds_apm/api/current_trace_info.rb +2 -3
- data/lib/solarwinds_apm/api/opentelemetry.rb +2 -2
- data/lib/solarwinds_apm/api/tracing.rb +1 -1
- data/lib/solarwinds_apm/api.rb +1 -1
- data/lib/solarwinds_apm/config.rb +56 -17
- data/lib/solarwinds_apm/constants.rb +5 -7
- data/lib/solarwinds_apm/noop/README.md +1 -1
- data/lib/solarwinds_apm/noop/api.rb +83 -0
- data/lib/solarwinds_apm/noop/context.rb +13 -2
- data/lib/solarwinds_apm/noop/metadata.rb +5 -2
- data/lib/solarwinds_apm/{thread_local.rb → noop/span.rb} +14 -20
- data/lib/solarwinds_apm/{base.rb → noop.rb} +22 -27
- data/lib/solarwinds_apm/oboe_init_options.rb +23 -82
- data/lib/solarwinds_apm/opentelemetry/solarwinds_exporter.rb +1 -1
- data/lib/solarwinds_apm/opentelemetry/solarwinds_processor.rb +2 -2
- data/lib/solarwinds_apm/opentelemetry/solarwinds_sampler.rb +4 -3
- data/lib/solarwinds_apm/opentelemetry.rb +1 -1
- data/lib/solarwinds_apm/otel_config.rb +14 -43
- data/lib/solarwinds_apm/patch/dummy_patch.rb +12 -0
- data/lib/solarwinds_apm/patch.rb +11 -0
- data/lib/solarwinds_apm/support/logger_formatter.rb +1 -1
- data/lib/solarwinds_apm/support/oboe_tracing_mode.rb +20 -22
- data/lib/solarwinds_apm/support/service_key_checker.rb +94 -0
- data/lib/solarwinds_apm/{support_report.rb → support/support_report.rb} +11 -8
- data/lib/solarwinds_apm/support/swomarginalia/comment.rb +2 -2
- data/lib/solarwinds_apm/support/swomarginalia/swomarginalia.rb +1 -1
- data/lib/solarwinds_apm/support/transaction_settings.rb +1 -5
- data/lib/solarwinds_apm/support.rb +1 -0
- data/lib/solarwinds_apm/version.rb +1 -1
- data/lib/solarwinds_apm.rb +70 -55
- metadata +12 -7
@@ -7,6 +7,8 @@
|
|
7
7
|
require 'singleton'
|
8
8
|
require 'uri'
|
9
9
|
|
10
|
+
require_relative './support/service_key_checker'
|
11
|
+
|
10
12
|
module SolarWindsAPM
|
11
13
|
# OboeInitOptions
|
12
14
|
class OboeInitOptions
|
@@ -21,7 +23,7 @@ module SolarWindsAPM
|
|
21
23
|
@debug_level = (ENV['SW_APM_DEBUG_LEVEL'] || SolarWindsAPM::Config[:debug_level] || 3).to_i
|
22
24
|
# file name including path for log file
|
23
25
|
# TODO eventually find better way to combine ruby and oboe logs
|
24
|
-
@log_file_path = ENV['
|
26
|
+
@log_file_path = ENV['SW_APM_LOG_FILEPATH'] || ''
|
25
27
|
# maximum number of transaction names to track
|
26
28
|
@max_transactions = (ENV['SW_APM_MAX_TRANSACTIONS'] || -1).to_i
|
27
29
|
# maximum wait time for flushing data before terminating in milli seconds
|
@@ -50,7 +52,7 @@ module SolarWindsAPM
|
|
50
52
|
# custom token bucket rate
|
51
53
|
@token_bucket_rate = (ENV['SW_APM_TOKEN_BUCKET_RATE'] || -1).to_i
|
52
54
|
# use single files in file reporter for each event
|
53
|
-
@file_single = ENV['SW_APM_REPORTER_FILE_SINGLE'].to_s.
|
55
|
+
@file_single = ENV['SW_APM_REPORTER_FILE_SINGLE'].to_s.casecmp('true').zero? ? 1 : 0
|
54
56
|
# timeout for ec2 metadata
|
55
57
|
@ec2_md_timeout = read_and_validate_ec2_md_timeout
|
56
58
|
@grpc_proxy = read_and_validate_proxy
|
@@ -59,6 +61,8 @@ module SolarWindsAPM
|
|
59
61
|
# hardcoded arg for trace id format to use w3c format
|
60
62
|
# flag for format of metric (0 = Both; 1 = AppOptics only; 2 = SWO only; default = 0)
|
61
63
|
@metric_format = determine_the_metric_model
|
64
|
+
# log type (0 = stderr; 1 = stdout; 2 = file; 3 = null; 4 = disabled; default = 0)
|
65
|
+
@log_type = determine_oboe_log_type
|
62
66
|
end
|
63
67
|
|
64
68
|
# for testing with changed ENV vars
|
@@ -75,7 +79,6 @@ module SolarWindsAPM
|
|
75
79
|
@max_flush_wait_time, # 4
|
76
80
|
@events_flush_interval, # 5
|
77
81
|
@event_flush_batch_size, # 6
|
78
|
-
|
79
82
|
@reporter, # 7
|
80
83
|
@host, # 8
|
81
84
|
@service_key, # 9
|
@@ -89,7 +92,8 @@ module SolarWindsAPM
|
|
89
92
|
@ec2_md_timeout, #17
|
90
93
|
@grpc_proxy, #18
|
91
94
|
0, #19 arg for lambda (no lambda for ruby yet)
|
92
|
-
@metric_format
|
95
|
+
@metric_format, #20
|
96
|
+
@log_type #21
|
93
97
|
]
|
94
98
|
end
|
95
99
|
|
@@ -123,81 +127,10 @@ module SolarWindsAPM
|
|
123
127
|
end
|
124
128
|
|
125
129
|
def read_and_validate_service_key
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY not configured."}
|
131
|
-
return ''
|
132
|
-
end
|
133
|
-
|
134
|
-
match = service_key.match(/([^:]+)(:{0,1})(.*)/)
|
135
|
-
token = match[1]
|
136
|
-
service_name = match[3]
|
137
|
-
|
138
|
-
return '' unless validate_token(token) # return if token is not even valid
|
139
|
-
|
140
|
-
if service_name.empty?
|
141
|
-
ENV.delete('OTEL_SERVICE_NAME')
|
142
|
-
SolarWindsAPM.logger.warn {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY format problem. Service Name is missing."}
|
143
|
-
return ''
|
144
|
-
end
|
145
|
-
|
146
|
-
# check OTEL_RESOURCE_ATTRIBUTES
|
147
|
-
otel_resource_service_name = nil
|
148
|
-
ENV['OTEL_RESOURCE_ATTRIBUTES']&.split(',')&.each do |pair|
|
149
|
-
key, value = pair.split('=')
|
150
|
-
if key == 'service.name'
|
151
|
-
otel_resource_service_name = value
|
152
|
-
break
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] provided otel_resource_service_name #{otel_resource_service_name}"} if otel_resource_service_name
|
157
|
-
service_name = otel_resource_service_name if otel_resource_service_name && validate_transform_service_name(otel_resource_service_name)
|
158
|
-
|
159
|
-
# check OTEL_SERVICE_NAME
|
160
|
-
otel_service_name = ENV['OTEL_SERVICE_NAME']
|
161
|
-
if otel_service_name && validate_transform_service_name(otel_service_name)
|
162
|
-
service_name = otel_service_name
|
163
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] provided otel_service_name #{otel_service_name}"}
|
164
|
-
elsif ENV['OTEL_SERVICE_NAME'].nil?
|
165
|
-
ENV['OTEL_SERVICE_NAME'] = service_name
|
166
|
-
end
|
167
|
-
|
168
|
-
return '' unless validate_transform_service_name(service_name)
|
169
|
-
|
170
|
-
"#{token}:#{service_name}"
|
171
|
-
end
|
172
|
-
|
173
|
-
def validate_token(token)
|
174
|
-
if (token !~ /^[0-9a-zA-Z_-]{71}$/) && ENV['SW_APM_COLLECTOR'] !~ /java-collector:1222/
|
175
|
-
masked = "#{token[0..3]}...#{token[-4..]}"
|
176
|
-
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY problem. API Token in wrong format. Masked token: #{masked}"}
|
177
|
-
return false
|
178
|
-
end
|
179
|
-
|
180
|
-
true
|
181
|
-
end
|
182
|
-
|
183
|
-
def validate_transform_service_name(service_name)
|
184
|
-
service_name = 'test_ssl_collector' if ENV['SW_APM_COLLECTOR'] =~ /java-collector:1222/
|
185
|
-
if service_name.empty?
|
186
|
-
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY problem. Service Name is missing"}
|
187
|
-
return false
|
188
|
-
end
|
189
|
-
|
190
|
-
name = service_name.dup
|
191
|
-
name.downcase!
|
192
|
-
name.gsub!(/[^a-z0-9.:_-]/, '')
|
193
|
-
name = name[0..254]
|
194
|
-
|
195
|
-
if name != service_name
|
196
|
-
SolarWindsAPM.logger.warn {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY problem. Service Name transformed from #{service_name} to #{name}"}
|
197
|
-
service_name = name
|
198
|
-
end
|
199
|
-
@service_name = service_name # instance variable used in testing
|
200
|
-
true
|
130
|
+
service_key_checker = SolarWindsAPM::ServiceKeyChecker.new(@reporter)
|
131
|
+
service_key = service_key_checker.read_and_validate_service_key
|
132
|
+
@service_name = service_key.split(':',2).last # instance variable used in testing
|
133
|
+
service_key
|
201
134
|
end
|
202
135
|
|
203
136
|
def read_and_validate_ec2_md_timeout
|
@@ -212,7 +145,7 @@ module SolarWindsAPM
|
|
212
145
|
proxy = ENV['SW_APM_PROXY'] || SolarWindsAPM::Config[:http_proxy] || ''
|
213
146
|
return proxy if proxy == ''
|
214
147
|
|
215
|
-
unless
|
148
|
+
unless /http:\/\/.*:\d+$/.match?(proxy)
|
216
149
|
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_PROXY/http_proxy doesn't start with 'http://', #{proxy}"}
|
217
150
|
return '' # try without proxy, it may work, shouldn't crash but may not report
|
218
151
|
end
|
@@ -221,14 +154,15 @@ module SolarWindsAPM
|
|
221
154
|
end
|
222
155
|
|
223
156
|
def read_certificates
|
157
|
+
certificate = ''
|
158
|
+
|
224
159
|
file = appoptics_collector?? "#{__dir__}/cert/star.appoptics.com.issuer.crt" : ENV['SW_APM_TRUSTEDPATH']
|
225
|
-
return
|
160
|
+
return certificate if file.nil? || file&.empty?
|
226
161
|
|
227
162
|
begin
|
228
163
|
certificate = File.open(file,"r").read
|
229
164
|
rescue StandardError => e
|
230
165
|
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] certificates: #{file} doesn't exist or caused by #{e.message}."}
|
231
|
-
certificate = String.new
|
232
166
|
end
|
233
167
|
|
234
168
|
certificate
|
@@ -256,5 +190,12 @@ module SolarWindsAPM
|
|
256
190
|
end
|
257
191
|
""
|
258
192
|
end
|
193
|
+
|
194
|
+
def determine_oboe_log_type
|
195
|
+
log_type = 0
|
196
|
+
log_type = 2 unless ENV['SW_APM_LOG_FILEPATH'].to_s.empty?
|
197
|
+
log_type = 4 if @debug_level == -1
|
198
|
+
log_type
|
199
|
+
end
|
259
200
|
end
|
260
201
|
end
|
@@ -133,7 +133,7 @@ module SolarWindsAPM
|
|
133
133
|
# helper function that extract gem library version for func add_instrumented_framework
|
134
134
|
def check_framework_version(framework)
|
135
135
|
framework_version = nil
|
136
|
-
if @version_cache.
|
136
|
+
if @version_cache.has_key?(framework)
|
137
137
|
|
138
138
|
framework_version = @version_cache[framework]
|
139
139
|
else
|
@@ -131,7 +131,7 @@ module SolarWindsAPM
|
|
131
131
|
|
132
132
|
# This span from inbound HTTP request if from a SERVER by some http.method
|
133
133
|
def span_http?(span)
|
134
|
-
|
134
|
+
span.kind == ::OpenTelemetry::Trace::SpanKind::SERVER && !span.attributes[HTTP_METHOD].nil?
|
135
135
|
end
|
136
136
|
|
137
137
|
# Calculate if this span instance has_error
|
@@ -173,4 +173,4 @@ module SolarWindsAPM
|
|
173
173
|
end
|
174
174
|
end
|
175
175
|
end
|
176
|
-
end
|
176
|
+
end
|
@@ -102,7 +102,7 @@ module SolarWindsAPM
|
|
102
102
|
end
|
103
103
|
|
104
104
|
sw_member_value = parent_span_context.tracestate[SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY]
|
105
|
-
trigger_trace_mode = OboeTracingMode.get_oboe_trigger_trace_mode(@config["trigger_trace"])
|
105
|
+
trigger_trace_mode = SolarWindsAPM::OboeTracingMode.get_oboe_trigger_trace_mode(@config["trigger_trace"])
|
106
106
|
sample_rate = UNSET
|
107
107
|
options = xtraceoptions&.options
|
108
108
|
trigger_trace = xtraceoptions&.intify_trigger_trace || 0
|
@@ -272,7 +272,8 @@ module SolarWindsAPM
|
|
272
272
|
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] trace_state_no_response #{trace_state_no_response.inspect}"}
|
273
273
|
|
274
274
|
trace_state_no_response = parent_span_context.tracestate.delete(XTraceOptions.sw_xtraceoptions_response_key)
|
275
|
-
no_sw_count = trace_state_no_response.to_h.
|
275
|
+
no_sw_count = trace_state_no_response.to_h.count { |k, _v| k != 'sw' }
|
276
|
+
|
276
277
|
new_attributes[SW_TRACESTATE_CAPTURE_KEY] = Utils.trace_state_header(trace_state_no_response) if no_sw_count > 0
|
277
278
|
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] new_attributes after add_tracestate_capture_to_new_attributes: #{new_attributes.inspect}"}
|
278
279
|
|
@@ -290,4 +291,4 @@ module SolarWindsAPM
|
|
290
291
|
end
|
291
292
|
end
|
292
293
|
end
|
293
|
-
end
|
294
|
+
end
|
@@ -11,4 +11,4 @@ require_relative './opentelemetry/solarwinds_propagator'
|
|
11
11
|
require_relative './opentelemetry/solarwinds_processor'
|
12
12
|
require_relative './opentelemetry/solarwinds_sampler'
|
13
13
|
require_relative './opentelemetry/solarwinds_exporter'
|
14
|
-
require_relative './opentelemetry/solarwinds_response_propagator'
|
14
|
+
require_relative './opentelemetry/solarwinds_response_propagator'
|
@@ -22,27 +22,13 @@ module SolarWindsAPM
|
|
22
22
|
SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Agent disabled. No Trace exported."}
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.validate_service_key
|
26
|
-
return unless (ENV['SW_APM_REPORTER'] || 'ssl') == 'ssl'
|
27
|
-
|
28
|
-
disable_agent unless ENV['SW_APM_SERVICE_KEY'] || SolarWindsAPM::Config[:service_key]
|
29
|
-
end
|
30
|
-
|
31
25
|
def self.resolve_sampler
|
32
|
-
|
33
|
-
resolve_sampler_config
|
26
|
+
sampler_config = {"trigger_trace" => SolarWindsAPM::Config[:trigger_tracing_mode]}
|
34
27
|
@@config[:sampler] =
|
35
28
|
::OpenTelemetry::SDK::Trace::Samplers.parent_based(
|
36
|
-
root: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(
|
37
|
-
remote_parent_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(
|
38
|
-
remote_parent_not_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.resolve_sampler_config
|
42
|
-
sampler_config = {}
|
43
|
-
sampler_config["trigger_trace"] = "enabled"
|
44
|
-
sampler_config["trigger_trace"] = nil if ENV["SW_APM_TRIGGER_TRACING_MODE"] == 'disabled'
|
45
|
-
@@config[:sampler_config] = sampler_config
|
29
|
+
root: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config),
|
30
|
+
remote_parent_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config),
|
31
|
+
remote_parent_not_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config))
|
46
32
|
end
|
47
33
|
|
48
34
|
#
|
@@ -65,31 +51,18 @@ module SolarWindsAPM
|
|
65
51
|
end
|
66
52
|
end
|
67
53
|
|
68
|
-
def self.obfuscate_helper(instrumentation)
|
69
|
-
if @@config_map[instrumentation] # user provided the option
|
70
|
-
@@config_map[instrumentation][:db_statement] = :obfuscate unless @@config_map[instrumentation][:db_statement] # user provided the db_statement, ignore our default setting
|
71
|
-
else
|
72
|
-
@@config_map[instrumentation] = {db_statement: :obfuscate}
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.obfuscate_query
|
77
|
-
obfuscate_helper("OpenTelemetry::Instrumentation::Dalli")
|
78
|
-
obfuscate_helper("OpenTelemetry::Instrumentation::Mysql2")
|
79
|
-
obfuscate_helper("OpenTelemetry::Instrumentation::PG")
|
80
|
-
end
|
81
|
-
|
82
54
|
def self.[](key)
|
83
55
|
@@config[key.to_sym]
|
84
56
|
end
|
85
57
|
|
86
58
|
def self.print_config
|
87
|
-
@@config.each do |
|
88
|
-
SolarWindsAPM.logger.
|
59
|
+
@@config.each do |k,v|
|
60
|
+
SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] Config Key/Value: #{k}, #{v.class}"}
|
89
61
|
end
|
90
|
-
@@config_map.each do |
|
91
|
-
SolarWindsAPM.logger.
|
62
|
+
@@config_map.each do |k,v|
|
63
|
+
SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] Config Key/Value: #{k}, #{v}"}
|
92
64
|
end
|
65
|
+
nil
|
93
66
|
end
|
94
67
|
|
95
68
|
def self.resolve_solarwinds_processor
|
@@ -122,21 +95,19 @@ module SolarWindsAPM
|
|
122
95
|
return
|
123
96
|
end
|
124
97
|
|
125
|
-
validate_service_key
|
126
|
-
|
127
|
-
return unless @@agent_enabled
|
128
|
-
|
129
98
|
resolve_sampler
|
130
|
-
|
131
99
|
resolve_solarwinds_propagator
|
132
100
|
resolve_solarwinds_processor
|
133
101
|
resolve_response_propagator
|
134
102
|
|
135
|
-
obfuscate_query
|
136
|
-
|
137
103
|
print_config if SolarWindsAPM.logger.level.zero?
|
138
104
|
|
105
|
+
# resolve OTEL environmental variables
|
139
106
|
ENV['OTEL_TRACES_EXPORTER'] = 'none' if ENV['OTEL_TRACES_EXPORTER'].to_s.empty?
|
107
|
+
if ENV['OTEL_LOG_LEVEL'].to_s.empty?
|
108
|
+
log_level = (ENV['SW_APM_DEBUG_LEVEL'] || SolarWindsAPM::Config[:debug_level] || 3).to_i
|
109
|
+
ENV['OTEL_LOG_LEVEL'] = SolarWindsAPM::Config::SW_LOG_LEVEL_MAPPING.dig(log_level, :otel)
|
110
|
+
end
|
140
111
|
|
141
112
|
::OpenTelemetry::SDK.configure { |c| c.use_all(@@config_map) }
|
142
113
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at:http://www.apache.org/licenses/LICENSE-2.0
|
4
|
+
#
|
5
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
6
|
+
|
7
|
+
# This file is for loading any customized patch for upstream
|
8
|
+
|
9
|
+
# e.g.
|
10
|
+
# require_relative './patch/dummy_patch'
|
11
|
+
# OpenTelemetry::Instrumentation::Registry.prepend(SolarWindsAPM::Patch::DummyPatch) if defined? OpenTelemetry::Instrumentation::Registry && OpenTelemetry::Instrumentation::Registry::VERSION <= '0.3.0'
|
@@ -5,29 +5,27 @@
|
|
5
5
|
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
6
6
|
|
7
7
|
module SolarWindsAPM
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
OBOE_TRIGGER_ENABLED = 1
|
8
|
+
# OboeTracingMode
|
9
|
+
# Used in solarwinds_sampler
|
10
|
+
class OboeTracingMode
|
11
|
+
OBOE_SETTINGS_UNSET = -1
|
12
|
+
OBOE_TRACE_DISABLED = 0
|
13
|
+
OBOE_TRACE_ENABLED = 1
|
14
|
+
OBOE_TRIGGER_DISABLED = 0
|
15
|
+
OBOE_TRIGGER_ENABLED = 1
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
def self.get_oboe_trace_mode(tracing_mode)
|
18
|
+
mode = OBOE_SETTINGS_UNSET
|
19
|
+
mode = OBOE_TRACE_ENABLED if tracing_mode == :enabled
|
20
|
+
mode = OBOE_TRACE_DISABLED if tracing_mode == :disabled
|
21
|
+
mode
|
22
|
+
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
24
|
+
def self.get_oboe_trigger_trace_mode(trigger_trace_mode)
|
25
|
+
mode = OBOE_SETTINGS_UNSET
|
26
|
+
mode = OBOE_TRIGGER_ENABLED if trigger_trace_mode == :enabled
|
27
|
+
mode = OBOE_TRIGGER_DISABLED if trigger_trace_mode == :disabled
|
28
|
+
mode
|
31
29
|
end
|
32
30
|
end
|
33
|
-
end
|
31
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at:http://www.apache.org/licenses/LICENSE-2.0
|
4
|
+
#
|
5
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
6
|
+
|
7
|
+
module SolarWindsAPM
|
8
|
+
# ServiceKeyChecker
|
9
|
+
# It is a service that validate the service_key
|
10
|
+
class ServiceKeyChecker
|
11
|
+
def initialize(reporter)
|
12
|
+
@reporter = reporter
|
13
|
+
end
|
14
|
+
|
15
|
+
def read_and_validate_service_key
|
16
|
+
return '' unless @reporter == 'ssl'
|
17
|
+
|
18
|
+
service_key = fetch_service_key
|
19
|
+
if service_key.empty?
|
20
|
+
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY not configured."}
|
21
|
+
return ''
|
22
|
+
end
|
23
|
+
|
24
|
+
token, _, service_name = parse_service_key(service_key)
|
25
|
+
if token.empty? || !validate_token(token)
|
26
|
+
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY problem. API Token in wrong format. Masked token: #{token[0..3]}...#{token[-4..]}"}
|
27
|
+
return ''
|
28
|
+
end
|
29
|
+
|
30
|
+
# if no service_name from service_key, then the SW_APM_SERVICE_KEY is not right format, return
|
31
|
+
if service_name.empty?
|
32
|
+
ENV.delete('OTEL_SERVICE_NAME')
|
33
|
+
SolarWindsAPM.logger.warn {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY format problem. Service Name is missing."}
|
34
|
+
return ''
|
35
|
+
end
|
36
|
+
|
37
|
+
service_name = transform_service_name(service_name)
|
38
|
+
|
39
|
+
# check if otel_resource_service or otel_service_name has service name to override the original service name
|
40
|
+
otel_resource_service_name = fetch_otel_resource_service_name
|
41
|
+
service_name = transform_service_name(otel_resource_service_name) unless otel_resource_service_name.empty?
|
42
|
+
|
43
|
+
otel_service_name = fetch_otel_service_name
|
44
|
+
if otel_service_name.empty?
|
45
|
+
ENV['OTEL_SERVICE_NAME'] = service_name
|
46
|
+
else
|
47
|
+
service_name = transform_service_name(otel_service_name)
|
48
|
+
end
|
49
|
+
|
50
|
+
"#{token}:#{service_name}"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# since oboe_init_options init afte config, so [:service_key] will be present at this point
|
56
|
+
def fetch_service_key
|
57
|
+
ENV['SW_APM_SERVICE_KEY'] || SolarWindsAPM::Config[:service_key] || ''
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_service_key(service_key)
|
61
|
+
match = service_key.match(/([^:]+)(:{0,1})(.*)/)
|
62
|
+
return ['', '', ''] if match.nil?
|
63
|
+
|
64
|
+
[match[1], match[2], match[3]]
|
65
|
+
end
|
66
|
+
|
67
|
+
# precedence: OTEL_SERVICE_NAME > OTEL_RESOURCE_ATTRIBUTES > service_key
|
68
|
+
def fetch_otel_service_name
|
69
|
+
ENV['OTEL_SERVICE_NAME'] || ''
|
70
|
+
end
|
71
|
+
|
72
|
+
def fetch_otel_resource_service_name
|
73
|
+
ENV['OTEL_RESOURCE_ATTRIBUTES']&.split(',')&.find do |pair|
|
74
|
+
key, value = pair.split('=')
|
75
|
+
break value if key == 'service.name'
|
76
|
+
end || ''
|
77
|
+
end
|
78
|
+
|
79
|
+
# In case of java-collector, please provide a dummy service key
|
80
|
+
def validate_token(token)
|
81
|
+
/^[0-9a-zA-Z_-]{71}$/.match?(token)
|
82
|
+
end
|
83
|
+
|
84
|
+
def transform_service_name(service_name)
|
85
|
+
name_ = service_name.dup
|
86
|
+
name_.downcase!
|
87
|
+
name_.gsub!(/[^a-z0-9.:_-]/, '')
|
88
|
+
name_ = name_[0..254]
|
89
|
+
SolarWindsAPM.logger.warn {"[#{self.class}/#{__method__}] Service Name transformed from #{service_name} to #{name_}"} if name_ != service_name
|
90
|
+
|
91
|
+
name_
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -7,12 +7,11 @@
|
|
7
7
|
require 'rbconfig'
|
8
8
|
require 'logger'
|
9
9
|
|
10
|
+
##
|
11
|
+
# This module is used to debug problematic setups and/or environments.
|
12
|
+
# Depending on the environment, output may be to stdout or the framework
|
13
|
+
# log file (e.g. log/production.log)
|
10
14
|
module SolarWindsAPM
|
11
|
-
##
|
12
|
-
# This module is used to debug problematic setups and/or environments.
|
13
|
-
# Depending on the environment, output may be to stdout or the framework
|
14
|
-
# log file (e.g. log/production.log)
|
15
|
-
|
16
15
|
##
|
17
16
|
# yesno
|
18
17
|
#
|
@@ -71,6 +70,12 @@ module SolarWindsAPM
|
|
71
70
|
SolarWindsAPM.logger.warn '********************************************************'
|
72
71
|
SolarWindsAPM.logger.warn '* SolarWindsAPM::Config Values'
|
73
72
|
SolarWindsAPM.logger.warn '********************************************************'
|
73
|
+
SolarWindsAPM.logger.warn SolarWindsAPM::Config.print_config.to_s
|
74
|
+
|
75
|
+
SolarWindsAPM.logger.warn '********************************************************'
|
76
|
+
SolarWindsAPM.logger.warn '* SolarWindsAPM::OTelConfig Values'
|
77
|
+
SolarWindsAPM.logger.warn '********************************************************'
|
78
|
+
SolarWindsAPM.logger.warn SolarWindsAPM::OTelConfig.print_config.to_s
|
74
79
|
|
75
80
|
SolarWindsAPM.logger.warn '********************************************************'
|
76
81
|
SolarWindsAPM.logger.warn '* OS, Platform + Env'
|
@@ -78,9 +83,7 @@ module SolarWindsAPM
|
|
78
83
|
SolarWindsAPM.logger.warn "host_os: #{RbConfig::CONFIG['host_os']}"
|
79
84
|
SolarWindsAPM.logger.warn "sitearch: #{RbConfig::CONFIG['sitearch']}"
|
80
85
|
SolarWindsAPM.logger.warn "arch: #{RbConfig::CONFIG['arch']}"
|
81
|
-
SolarWindsAPM.logger.warn RUBY_PLATFORM
|
82
|
-
SolarWindsAPM.logger.warn "RACK_ENV: #{ENV['RACK_ENV']}"
|
83
|
-
SolarWindsAPM.logger.warn "RAILS_ENV: #{ENV['RAILS_ENV']}" if using_rails
|
86
|
+
SolarWindsAPM.logger.warn "Platform: #{RUBY_PLATFORM}"
|
84
87
|
|
85
88
|
SolarWindsAPM.logger.warn '********************************************************'
|
86
89
|
SolarWindsAPM.logger.warn '* END SolarWindsAPM Support Report'
|
@@ -25,7 +25,7 @@ module SolarWindsAPM
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.construct_comment
|
28
|
-
ret =
|
28
|
+
ret = +''
|
29
29
|
components.each do |c|
|
30
30
|
component_value = send(c)
|
31
31
|
ret << "#{c}='#{component_value}'," if component_value.present?
|
@@ -107,7 +107,7 @@ module SolarWindsAPM
|
|
107
107
|
marginalia_job["class"] if marginalia_job.respond_to?(:[])
|
108
108
|
end
|
109
109
|
|
110
|
-
DEFAULT_LINES_TO_IGNORE_REGEX = %r{\.rvm|/ruby/gems/|vendor/|marginalia|rbenv|monitor\.rb.*mon_synchronize}
|
110
|
+
DEFAULT_LINES_TO_IGNORE_REGEX = %r{\.rvm|/ruby/gems/|vendor/|marginalia|rbenv|monitor\.rb.*mon_synchronize}.freeze # rubocop:disable Style/RedundantFreeze
|
111
111
|
|
112
112
|
def self.line
|
113
113
|
SWOMarginalia::Comment.lines_to_ignore ||= DEFAULT_LINES_TO_IGNORE_REGEX
|
@@ -21,15 +21,11 @@ module SolarWindsAPM
|
|
21
21
|
# calculate trace mode to set either 1 or 0 based on url_path and name+kind
|
22
22
|
# first check if url_path match, if not match, then match the name+kind
|
23
23
|
def calculate_trace_mode
|
24
|
-
|
24
|
+
SolarWindsAPM::Config[:tracing_mode] == :enabled && tracing_enabled? ? SWO_TRACING_ENABLED : SWO_TRACING_DISABLED
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
-
def tracing_mode_enabled?
|
30
|
-
SolarWindsAPM::Config[:tracing_mode] && ![:disabled, :never].include?(SolarWindsAPM::Config[:tracing_mode])
|
31
|
-
end
|
32
|
-
|
33
29
|
def tracing_enabled?
|
34
30
|
span_layer = "#{@kind}:#{@name}"
|
35
31
|
|
@@ -15,6 +15,7 @@ require_relative './support/oboe_tracing_mode'
|
|
15
15
|
require_relative './support/txn_name_manager'
|
16
16
|
require_relative './support/utils'
|
17
17
|
require_relative './support/x_trace_options'
|
18
|
+
require_relative './support/support_report'
|
18
19
|
|
19
20
|
if SolarWindsAPM::Config[:tag_sql]
|
20
21
|
if defined?(::Rails)
|
@@ -12,7 +12,7 @@ module SolarWindsAPM
|
|
12
12
|
MAJOR = 6 # breaking,
|
13
13
|
MINOR = 0 # feature,
|
14
14
|
PATCH = 0 # fix => BFF
|
15
|
-
PRE =
|
15
|
+
PRE = nil
|
16
16
|
|
17
17
|
STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
|
18
18
|
end
|