solarwinds_apm 6.0.0 → 6.0.1
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 +42 -41
- 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-lambda-aarch64.so.sha256 +1 -0
- data/ext/oboe_metal/lib/liboboe-1.0-lambda-x86_64.so.sha256 +1 -0
- 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 +3 -0
- data/ext/oboe_metal/src/oboe_api.cpp +1 -1
- data/lib/oboe_metal.rb +30 -27
- data/lib/rails/generators/solarwinds_apm/install_generator.rb +21 -19
- data/lib/solarwinds_apm/api/current_trace_info.rb +16 -9
- data/lib/solarwinds_apm/api/custom_metrics.rb +6 -4
- data/lib/solarwinds_apm/api/opentelemetry.rb +8 -4
- data/lib/solarwinds_apm/api/tracing.rb +6 -4
- data/lib/solarwinds_apm/api/transaction_name.rb +21 -11
- data/lib/solarwinds_apm/api.rb +7 -5
- data/lib/solarwinds_apm/config.rb +70 -46
- data/lib/solarwinds_apm/constants.rb +25 -23
- data/lib/solarwinds_apm/logger.rb +2 -0
- data/lib/solarwinds_apm/noop/api.rb +3 -1
- data/lib/solarwinds_apm/noop/context.rb +2 -0
- data/lib/solarwinds_apm/noop/metadata.rb +2 -0
- data/lib/solarwinds_apm/noop/span.rb +2 -0
- data/lib/solarwinds_apm/noop.rb +8 -6
- data/lib/solarwinds_apm/oboe_init_options.rb +47 -39
- data/lib/solarwinds_apm/opentelemetry/otlp_processor.rb +135 -0
- data/lib/solarwinds_apm/opentelemetry/solarwinds_exporter.rb +66 -41
- data/lib/solarwinds_apm/opentelemetry/solarwinds_processor.rb +49 -51
- data/lib/solarwinds_apm/opentelemetry/solarwinds_propagator.rb +30 -22
- data/lib/solarwinds_apm/opentelemetry/solarwinds_response_propagator.rb +29 -16
- data/lib/solarwinds_apm/opentelemetry/solarwinds_sampler.rb +135 -98
- data/lib/solarwinds_apm/opentelemetry.rb +8 -5
- data/lib/solarwinds_apm/otel_config.rb +32 -25
- data/lib/solarwinds_apm/otel_lambda_config.rb +53 -0
- data/lib/solarwinds_apm/patch.rb +2 -0
- data/lib/solarwinds_apm/support/logger_formatter.rb +4 -2
- data/lib/solarwinds_apm/support/logging_log_event.rb +2 -0
- data/lib/solarwinds_apm/support/lumberjack_formatter.rb +2 -0
- data/lib/solarwinds_apm/support/oboe_tracing_mode.rb +2 -0
- data/lib/solarwinds_apm/support/service_key_checker.rb +18 -6
- data/lib/solarwinds_apm/support/support_report.rb +5 -3
- data/lib/solarwinds_apm/support/swomarginalia/comment.rb +18 -17
- data/lib/solarwinds_apm/support/swomarginalia/load_swomarginalia.rb +13 -12
- data/lib/solarwinds_apm/support/swomarginalia/railtie.rb +4 -2
- data/lib/solarwinds_apm/support/swomarginalia/swomarginalia.rb +3 -1
- data/lib/solarwinds_apm/support/transaction_cache.rb +6 -4
- data/lib/solarwinds_apm/support/transaction_settings.rb +7 -3
- data/lib/solarwinds_apm/support/txn_name_manager.rb +8 -3
- data/lib/solarwinds_apm/support/utils.rb +12 -9
- data/lib/solarwinds_apm/support/x_trace_options.rb +23 -17
- data/lib/solarwinds_apm/support.rb +28 -24
- data/lib/solarwinds_apm/version.rb +3 -1
- data/lib/solarwinds_apm.rb +44 -34
- metadata +14 -23
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
4
|
+
#
|
5
|
+
# 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
|
6
|
+
#
|
7
|
+
# 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.
|
8
|
+
|
9
|
+
require 'solarwinds_apm/constants'
|
10
|
+
require 'solarwinds_apm/api'
|
11
|
+
require 'solarwinds_apm/support'
|
12
|
+
require 'solarwinds_apm/opentelemetry'
|
13
|
+
|
14
|
+
module SolarWindsAPM
|
15
|
+
# OTelLambdaConfig module
|
16
|
+
module OTelLambdaConfig
|
17
|
+
def self.initialize
|
18
|
+
return unless defined?(::OpenTelemetry::SDK::Configurator)
|
19
|
+
|
20
|
+
if ENV['OTEL_TRACES_EXPORTER'].to_s.empty?
|
21
|
+
ENV['OTEL_TRACES_EXPORTER'] = 'otlp'
|
22
|
+
elsif !ENV['OTEL_TRACES_EXPORTER'].include? 'otlp'
|
23
|
+
ENV['OTEL_TRACES_EXPORTER'] += ',otlp'
|
24
|
+
end
|
25
|
+
|
26
|
+
ENV['OTEL_RESOURCE_ATTRIBUTES'] = "sw.apm.version=#{SolarWindsAPM::Version::STRING},sw.data.module=apm,service.name=#{ENV['OTEL_SERVICE_NAME'] || ENV.fetch('AWS_LAMBDA_FUNCTION_NAME', nil)}," + ENV['OTEL_RESOURCE_ATTRIBUTES'].to_s
|
27
|
+
::OpenTelemetry::SDK.configure(&:use_all)
|
28
|
+
|
29
|
+
# append our propagators
|
30
|
+
::OpenTelemetry.propagation.instance_variable_get(:@propagators).append(SolarWindsAPM::OpenTelemetry::SolarWindsPropagator::TextMapPropagator.new)
|
31
|
+
|
32
|
+
# register metrics_exporter to meter_provider
|
33
|
+
::OpenTelemetry.meter_provider.add_metric_reader(::OpenTelemetry::Exporter::OTLP::MetricsExporter.new)
|
34
|
+
|
35
|
+
# append our processors
|
36
|
+
::OpenTelemetry.tracer_provider.add_span_processor(SolarWindsAPM::OpenTelemetry::OTLPProcessor.new)
|
37
|
+
|
38
|
+
# configure sampler afterwards
|
39
|
+
::OpenTelemetry.tracer_provider.sampler = ::OpenTelemetry::SDK::Trace::Samplers.parent_based(
|
40
|
+
root: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new,
|
41
|
+
remote_parent_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new,
|
42
|
+
remote_parent_not_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new
|
43
|
+
)
|
44
|
+
|
45
|
+
SolarWindsAPM.logger.warn do
|
46
|
+
"[#{name}/#{__method__}] SolarWindsAPM lambda configuration initialized \
|
47
|
+
\nOpenTelemetry.tracer_provider: #{::OpenTelemetry.tracer_provider.inspect}"
|
48
|
+
end
|
49
|
+
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/solarwinds_apm/patch.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -19,13 +21,13 @@ module SolarWindsAPM
|
|
19
21
|
private
|
20
22
|
|
21
23
|
def insert_trace_id(msg)
|
22
|
-
return msg if
|
24
|
+
return msg if msg.include?('trace_id=')
|
23
25
|
|
24
26
|
current_trace = SolarWindsAPM::API.current_trace_info
|
25
27
|
if current_trace.do_log
|
26
28
|
case msg
|
27
29
|
when ::String
|
28
|
-
msg =
|
30
|
+
msg = insert_before_empty_lines(msg, current_trace.for_log) unless msg.strip.empty?
|
29
31
|
when ::Exception
|
30
32
|
# conversion to String copied from Logger::Formatter private method #msg2str
|
31
33
|
msg = ("#{msg.message} (#{msg.class}) #{current_trace.for_log}\n" <<
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -8,29 +10,35 @@ module SolarWindsAPM
|
|
8
10
|
# ServiceKeyChecker
|
9
11
|
# It is a service that validate the service_key
|
10
12
|
class ServiceKeyChecker
|
11
|
-
def initialize(reporter)
|
13
|
+
def initialize(reporter, is_lambda)
|
12
14
|
@reporter = reporter
|
15
|
+
@is_lambda = is_lambda
|
13
16
|
end
|
14
17
|
|
15
18
|
def read_and_validate_service_key
|
16
19
|
return '' unless @reporter == 'ssl'
|
20
|
+
return '' if @is_lambda
|
17
21
|
|
18
22
|
service_key = fetch_service_key
|
19
23
|
if service_key.empty?
|
20
|
-
SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY not configured."}
|
24
|
+
SolarWindsAPM.logger.error { "[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY not configured." }
|
21
25
|
return ''
|
22
26
|
end
|
23
27
|
|
24
28
|
token, _, service_name = parse_service_key(service_key)
|
25
29
|
if token.empty? || !validate_token(token)
|
26
|
-
SolarWindsAPM.logger.error
|
30
|
+
SolarWindsAPM.logger.error do
|
31
|
+
"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY problem. API Token in wrong format. Masked token: #{token[0..3]}...#{token[-4..]}"
|
32
|
+
end
|
27
33
|
return ''
|
28
34
|
end
|
29
35
|
|
30
36
|
# if no service_name from service_key, then the SW_APM_SERVICE_KEY is not right format, return
|
31
37
|
if service_name.empty?
|
32
38
|
ENV.delete('OTEL_SERVICE_NAME')
|
33
|
-
SolarWindsAPM.logger.warn
|
39
|
+
SolarWindsAPM.logger.warn do
|
40
|
+
"[#{self.class}/#{__method__}] SW_APM_SERVICE_KEY format problem. Service Name is missing."
|
41
|
+
end
|
34
42
|
return ''
|
35
43
|
end
|
36
44
|
|
@@ -86,9 +94,13 @@ module SolarWindsAPM
|
|
86
94
|
name_.downcase!
|
87
95
|
name_.gsub!(/[^a-z0-9.:_-]/, '')
|
88
96
|
name_ = name_[0..254]
|
89
|
-
|
97
|
+
if name_ != service_name
|
98
|
+
SolarWindsAPM.logger.warn do
|
99
|
+
"[#{self.class}/#{__method__}] Service Name transformed from #{service_name} to #{name_}"
|
100
|
+
end
|
101
|
+
end
|
90
102
|
|
91
103
|
name_
|
92
104
|
end
|
93
105
|
end
|
94
|
-
end
|
106
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -29,8 +31,8 @@ module SolarWindsAPM
|
|
29
31
|
SolarWindsAPM.logger.warn '* Please email the output of this report to SWO-support@solarwinds.com'
|
30
32
|
SolarWindsAPM.logger.warn '********************************************************'
|
31
33
|
SolarWindsAPM.logger.warn "Ruby: #{RUBY_DESCRIPTION}"
|
32
|
-
SolarWindsAPM.logger.warn "PROGRAM_NAME: #{$PROGRAM_NAME}"
|
33
|
-
SolarWindsAPM.logger.warn "ARGV: #{ARGV.inspect}"
|
34
|
+
SolarWindsAPM.logger.warn "PROGRAM_NAME: #{$PROGRAM_NAME}" # replace $0 to get executing script
|
35
|
+
SolarWindsAPM.logger.warn "ARGV: #{ARGV.inspect}"
|
34
36
|
SolarWindsAPM.logger.warn "SolarWindsAPM.loaded == #{SolarWindsAPM.loaded}"
|
35
37
|
|
36
38
|
SolarWindsAPM.logger.warn "SolarWindsAPM::Ruby defined?: #{yesno(defined?(SolarWindsAPM::Ruby))}"
|
@@ -71,7 +73,7 @@ module SolarWindsAPM
|
|
71
73
|
SolarWindsAPM.logger.warn '* SolarWindsAPM::Config Values'
|
72
74
|
SolarWindsAPM.logger.warn '********************************************************'
|
73
75
|
SolarWindsAPM.logger.warn SolarWindsAPM::Config.print_config.to_s
|
74
|
-
|
76
|
+
|
75
77
|
SolarWindsAPM.logger.warn '********************************************************'
|
76
78
|
SolarWindsAPM.logger.warn '* SolarWindsAPM::OTelConfig Values'
|
77
79
|
SolarWindsAPM.logger.warn '********************************************************'
|
@@ -8,11 +8,11 @@ module SolarWindsAPM
|
|
8
8
|
module Comment
|
9
9
|
mattr_accessor :components, :lines_to_ignore, :prepend_comment
|
10
10
|
SWOMarginalia::Comment.components ||= [:traceparent]
|
11
|
-
# To add new components:
|
11
|
+
# To add new components:
|
12
12
|
# Create file and load after loading solarwinds_apm, and add following:
|
13
13
|
# SolarWindsAPM::SWOMarginalia::Comment.component = [:user_defined]
|
14
14
|
|
15
|
-
def self.update!(controller=nil)
|
15
|
+
def self.update!(controller = nil)
|
16
16
|
self.marginalia_controller = controller
|
17
17
|
end
|
18
18
|
|
@@ -78,11 +78,11 @@ module SolarWindsAPM
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def self.application
|
81
|
-
if defined?(::Rails.application)
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
81
|
+
SWOMarginalia.application_name ||= if defined?(::Rails.application)
|
82
|
+
::Rails.application.class.name.split('::').first
|
83
|
+
else
|
84
|
+
'rails'
|
85
|
+
end
|
86
86
|
|
87
87
|
SWOMarginalia.application_name
|
88
88
|
end
|
@@ -104,10 +104,10 @@ module SolarWindsAPM
|
|
104
104
|
end
|
105
105
|
|
106
106
|
def self.sidekiq_job
|
107
|
-
marginalia_job[
|
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}
|
111
111
|
|
112
112
|
def self.line
|
113
113
|
SWOMarginalia::Comment.lines_to_ignore ||= DEFAULT_LINES_TO_IGNORE_REGEX
|
@@ -116,13 +116,13 @@ module SolarWindsAPM
|
|
116
116
|
line !~ SWOMarginalia::Comment.lines_to_ignore
|
117
117
|
end
|
118
118
|
return unless last_line
|
119
|
-
|
119
|
+
|
120
120
|
root = if defined?(Rails) && Rails.respond_to?(:root)
|
121
121
|
Rails.root.to_s
|
122
122
|
elsif defined?(RAILS_ROOT)
|
123
123
|
RAILS_ROOT
|
124
124
|
else
|
125
|
-
|
125
|
+
''
|
126
126
|
end
|
127
127
|
last_line = last_line[root.length..] if last_line.start_with? root
|
128
128
|
last_line
|
@@ -139,7 +139,7 @@ module SolarWindsAPM
|
|
139
139
|
def self.request_id
|
140
140
|
return unless marginalia_controller.respond_to?(:request) && marginalia_controller.request.respond_to?(:uuid)
|
141
141
|
|
142
|
-
marginalia_controller.request.uuid
|
142
|
+
marginalia_controller.request.uuid
|
143
143
|
end
|
144
144
|
|
145
145
|
def self.socket
|
@@ -160,26 +160,27 @@ module SolarWindsAPM
|
|
160
160
|
connection_config[:database]
|
161
161
|
end
|
162
162
|
|
163
|
-
##
|
163
|
+
##
|
164
164
|
# Insert trace string as traceparent to sql statement
|
165
165
|
# Not insert if:
|
166
166
|
# there is no valid current trace context
|
167
167
|
# current trace context is not sampled
|
168
|
-
#
|
168
|
+
#
|
169
169
|
def self.traceparent
|
170
170
|
span_context = ::OpenTelemetry::Trace.current_span.context
|
171
171
|
return '' if span_context == ::OpenTelemetry::Trace::SpanContext::INVALID
|
172
172
|
|
173
|
-
trace_flag = span_context.trace_flags.sampled? ? '01': '00'
|
173
|
+
trace_flag = span_context.trace_flags.sampled? ? '01' : '00'
|
174
174
|
return '' if trace_flag == '00'
|
175
175
|
|
176
176
|
format(
|
177
177
|
'00-%<trace_id>s-%<span_id>s-%<trace_flags>.2d',
|
178
178
|
trace_id: span_context.hex_trace_id,
|
179
179
|
span_id: span_context.hex_span_id,
|
180
|
-
trace_flags: trace_flag
|
180
|
+
trace_flags: trace_flag
|
181
|
+
)
|
181
182
|
rescue NameError => e
|
182
|
-
SolarWindsAPM.logger.error {"[#{name}/#{__method__}] Couldn't find OpenTelemetry. Error: #{e.message}"}
|
183
|
+
SolarWindsAPM.logger.error { "[#{name}/#{__method__}] Couldn't find OpenTelemetry. Error: #{e.message}" }
|
183
184
|
end
|
184
185
|
|
185
186
|
if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('6.1')
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
6
|
#
|
5
7
|
# 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
8
|
|
7
|
-
require_relative '
|
9
|
+
require_relative 'swomarginalia'
|
8
10
|
|
9
11
|
module SolarWindsAPM
|
10
12
|
module SWOMarginalia
|
@@ -17,24 +19,22 @@ module SolarWindsAPM
|
|
17
19
|
|
18
20
|
def self.insert_into_active_job
|
19
21
|
return unless defined? ::ActiveJob::Base
|
20
|
-
|
22
|
+
|
21
23
|
::ActiveJob::Base.class_eval do
|
22
24
|
around_perform do |job, block|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
SWOMarginalia::Comment.clear_job!
|
28
|
-
end
|
25
|
+
SWOMarginalia::Comment.update_job! job
|
26
|
+
block.call
|
27
|
+
ensure
|
28
|
+
SWOMarginalia::Comment.clear_job!
|
29
29
|
end
|
30
30
|
end
|
31
|
-
end
|
31
|
+
end
|
32
32
|
|
33
33
|
def self.insert_into_action_controller
|
34
34
|
return unless defined? ::ActionController::Base
|
35
35
|
|
36
36
|
::ActionController::Base.include SWOMarginalia::ActionControllerInstrumentation
|
37
|
-
|
37
|
+
|
38
38
|
return unless defined? ::ActionController::API
|
39
39
|
|
40
40
|
::ActionController::API.include SWOMarginalia::ActionControllerInstrumentation
|
@@ -46,9 +46,10 @@ module SolarWindsAPM
|
|
46
46
|
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(SWOMarginalia::ActiveRecordInstrumentation) if defined? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
47
47
|
return unless defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter
|
48
48
|
|
49
|
-
|
49
|
+
return unless defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter
|
50
|
+
|
51
|
+
ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(SWOMarginalia::ActiveRecordInstrumentation)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
54
|
-
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails/railtie'
|
2
|
-
require_relative '
|
4
|
+
require_relative 'load_swomarginalia'
|
3
5
|
|
4
6
|
module SolarWindsAPM
|
5
7
|
module SWOMarginalia
|
@@ -19,4 +21,4 @@ module SolarWindsAPM
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
22
|
-
end
|
24
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -16,7 +18,7 @@ module SolarWindsAPM
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.get(key)
|
19
|
-
return nil unless @cache.
|
21
|
+
return nil unless @cache.key?(key)
|
20
22
|
|
21
23
|
@order.delete(key)
|
22
24
|
@order.push(key)
|
@@ -38,7 +40,7 @@ module SolarWindsAPM
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def self.set(key, value)
|
41
|
-
if @cache.
|
43
|
+
if @cache.key?(key)
|
42
44
|
@cache.delete(key)
|
43
45
|
elsif @order.size >= @capacity
|
44
46
|
evict_key = @order.shift
|
@@ -47,9 +49,9 @@ module SolarWindsAPM
|
|
47
49
|
|
48
50
|
@cache[key] = value
|
49
51
|
@order.push(key)
|
50
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] current TransactionCache #{@cache.inspect}"}
|
52
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] current TransactionCache #{@cache.inspect}" }
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
|
-
SolarWindsAPM::TransactionCache.initialize
|
57
|
+
SolarWindsAPM::TransactionCache.initialize
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -32,8 +34,8 @@ module SolarWindsAPM
|
|
32
34
|
enabled_regexps = SolarWindsAPM::Config[:enabled_regexps]
|
33
35
|
disabled_regexps = SolarWindsAPM::Config[:disabled_regexps]
|
34
36
|
|
35
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] enabled_regexps: #{enabled_regexps&.inspect}"}
|
36
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] disabled_regexps: #{disabled_regexps&.inspect}"}
|
37
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] enabled_regexps: #{enabled_regexps&.inspect}" }
|
38
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] disabled_regexps: #{disabled_regexps&.inspect}" }
|
37
39
|
|
38
40
|
return false if disabled_regexps.is_a?(Array) && disabled_regexps.any? { |regex| regex.match?(@url_path) }
|
39
41
|
return true if enabled_regexps.is_a?(Array) && enabled_regexps.any? { |regex| regex.match?(@url_path) }
|
@@ -42,7 +44,9 @@ module SolarWindsAPM
|
|
42
44
|
|
43
45
|
true
|
44
46
|
rescue StandardError => e
|
45
|
-
SolarWindsAPM.logger.warn
|
47
|
+
SolarWindsAPM.logger.warn do
|
48
|
+
"[#{self.class}/#{__method__}] Could not determine tracing status for #{kind}. #{e.inspect}. transaction_settings regexps/extensions igonred/unfiltered."
|
49
|
+
end
|
46
50
|
true
|
47
51
|
end
|
48
52
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -6,6 +8,7 @@
|
|
6
8
|
|
7
9
|
module SolarWindsAPM
|
8
10
|
# SolarWindsTxnNameManager
|
11
|
+
# Transaction Name Manager is sole for enabling solarwinds api to call set_transaction_name
|
9
12
|
class TxnNameManager
|
10
13
|
def initialize
|
11
14
|
@cache = {}
|
@@ -23,7 +26,7 @@ module SolarWindsAPM
|
|
23
26
|
|
24
27
|
def set(key, value)
|
25
28
|
@cache[key] = value
|
26
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] txn manager current cache #{@cache.inspect}"}
|
29
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] txn manager current cache #{@cache.inspect}" }
|
27
30
|
end
|
28
31
|
|
29
32
|
alias []= set
|
@@ -32,7 +35,9 @@ module SolarWindsAPM
|
|
32
35
|
@mutex.synchronize do
|
33
36
|
@root_context_h[key] = value
|
34
37
|
end
|
35
|
-
SolarWindsAPM.logger.debug
|
38
|
+
SolarWindsAPM.logger.debug do
|
39
|
+
"[#{self.class}/#{__method__}] txn manager current root_context_h #{@root_context_h.inspect}"
|
40
|
+
end
|
36
41
|
end
|
37
42
|
|
38
43
|
def get_root_context_h(key)
|
@@ -45,4 +50,4 @@ module SolarWindsAPM
|
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
48
|
-
end
|
53
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -7,24 +9,25 @@
|
|
7
9
|
module SolarWindsAPM
|
8
10
|
# Utils
|
9
11
|
class Utils
|
10
|
-
VERSION = '00'
|
12
|
+
VERSION = '00'
|
11
13
|
|
12
14
|
def self.trace_state_header(trace_state)
|
13
|
-
return nil if trace_state.nil?
|
15
|
+
return nil if trace_state.nil? || trace_state.empty?
|
14
16
|
|
15
|
-
arr
|
16
|
-
|
17
|
-
|
18
|
-
SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] generated trace_state_header: #{header}"}
|
17
|
+
arr = trace_state.to_h.map { |key, value| "#{key}=#{value}" }
|
18
|
+
header = arr.join(',')
|
19
|
+
SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] generated trace_state_header: #{header}" }
|
19
20
|
header
|
20
21
|
end
|
21
22
|
|
22
23
|
# Generates a liboboe W3C compatible trace_context from provided OTel span context.
|
23
24
|
def self.traceparent_from_context(span_context)
|
24
|
-
flag = span_context.trace_flags.sampled
|
25
|
+
flag = span_context.trace_flags.sampled? ? 1 : 0
|
25
26
|
xtr = "#{VERSION}-#{span_context.hex_trace_id}-#{span_context.hex_span_id}-0#{flag}"
|
26
|
-
SolarWindsAPM.logger.debug
|
27
|
+
SolarWindsAPM.logger.debug do
|
28
|
+
"[#{name}/#{__method__}] generated traceparent: #{xtr} from #{span_context.inspect}"
|
29
|
+
end
|
27
30
|
xtr
|
28
31
|
end
|
29
32
|
end
|
30
|
-
end
|
33
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# © 2023 SolarWinds Worldwide, LLC. All rights reserved.
|
2
4
|
#
|
3
5
|
# 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
|
@@ -7,9 +9,9 @@
|
|
7
9
|
module SolarWindsAPM
|
8
10
|
# XTraceOptions
|
9
11
|
class XTraceOptions
|
10
|
-
attr_reader :options, :signature, :trigger_trace, :timestamp,
|
12
|
+
attr_reader :options, :signature, :trigger_trace, :timestamp,
|
11
13
|
:sw_keys, :custom_kvs, :ignored
|
12
|
-
|
14
|
+
|
13
15
|
##
|
14
16
|
# use by Trigger Tracing
|
15
17
|
# TODO - refactor for w3c when ticket ready
|
@@ -36,10 +38,10 @@ module SolarWindsAPM
|
|
36
38
|
# - ts (unix timestamp)
|
37
39
|
# - other keys will be reported in the response options as ignored
|
38
40
|
|
39
|
-
SW_XTRACEOPTIONS_RESPONSE_KEY = 'xtrace_options_response'
|
41
|
+
SW_XTRACEOPTIONS_RESPONSE_KEY = 'xtrace_options_response'
|
40
42
|
|
41
43
|
def initialize(context)
|
42
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] x_trace_options context: #{context.inspect}"}
|
44
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] x_trace_options context: #{context.inspect}" }
|
43
45
|
@context = context.dup
|
44
46
|
@trigger_trace = false
|
45
47
|
@custom_kvs = {}
|
@@ -64,19 +66,19 @@ module SolarWindsAPM
|
|
64
66
|
end
|
65
67
|
when 'sw-keys'
|
66
68
|
if @sw_keys
|
67
|
-
SolarWindsAPM.logger.info {"[#{self.class}/#{__method__}] Duplicate key: #{k[0]}"}
|
69
|
+
SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] Duplicate key: #{k[0]}" }
|
68
70
|
else
|
69
71
|
@sw_keys = k[1].strip
|
70
72
|
end
|
71
73
|
when /^custom-[^\s]*$/
|
72
74
|
if @custom_kvs[k[0]]
|
73
|
-
SolarWindsAPM.logger.info {"[#{self.class}/#{__method__}] Duplicate key: #{k[0]}"}
|
75
|
+
SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] Duplicate key: #{k[0]}" }
|
74
76
|
else
|
75
77
|
@custom_kvs[k[0]] = k[1].strip
|
76
78
|
end
|
77
79
|
when 'ts'
|
78
|
-
if @timestamp
|
79
|
-
SolarWindsAPM.logger.info {"[#{self.class}/#{__method__}] Duplicate key: #{k[0]}"}
|
80
|
+
if @timestamp.positive?
|
81
|
+
SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] Duplicate key: #{k[0]}" }
|
80
82
|
else
|
81
83
|
@timestamp = k[1].to_i
|
82
84
|
end
|
@@ -84,13 +86,15 @@ module SolarWindsAPM
|
|
84
86
|
@ignored << k[0]
|
85
87
|
end
|
86
88
|
end
|
87
|
-
|
89
|
+
return if @ignored.empty?
|
90
|
+
|
91
|
+
SolarWindsAPM.logger.info("[#{self.class}/#{__method__}] Some keys were ignored: #{@ignored.join(',')}")
|
88
92
|
end
|
89
93
|
|
90
94
|
def add_kvs(kvs, settings)
|
91
95
|
return unless settings.auth_ok?
|
92
96
|
|
93
|
-
@custom_kvs.each { |k,v| kvs[k] = v } unless @custom_kvs.empty?
|
97
|
+
@custom_kvs.each { |k, v| kvs[k] = v } unless @custom_kvs.empty?
|
94
98
|
kvs['SWKeys'] = @sw_keys if @sw_keys
|
95
99
|
kvs['TriggeredTrace'] = true if settings.triggered_trace?
|
96
100
|
end
|
@@ -98,24 +102,26 @@ module SolarWindsAPM
|
|
98
102
|
def obtain_signature
|
99
103
|
# INTL_SWO_SIGNATURE_KEY = sw_signature
|
100
104
|
signature = obtain_sw_value(SolarWindsAPM::Constants::INTL_SWO_SIGNATURE_KEY)
|
101
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] x_trace_options option_signature: #{signature}"}
|
105
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] x_trace_options option_signature: #{signature}" }
|
102
106
|
signature
|
103
107
|
end
|
104
108
|
|
105
109
|
def options_header
|
106
|
-
# INTL_SWO_X_OPTIONS_KEY = sw_xtraceoptions
|
110
|
+
# INTL_SWO_X_OPTIONS_KEY = sw_xtraceoptions
|
107
111
|
header = obtain_sw_value(SolarWindsAPM::Constants::INTL_SWO_X_OPTIONS_KEY)
|
108
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] x_trace_options option_header: #{header}"}
|
112
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] x_trace_options option_header: #{header}" }
|
109
113
|
header
|
110
114
|
end
|
111
115
|
|
112
116
|
def obtain_sw_value(type)
|
113
117
|
sw_value = nil
|
114
|
-
instance_variable = @context&.instance_variable_get(
|
118
|
+
instance_variable = @context&.instance_variable_get('@entries')
|
115
119
|
instance_variable&.each do |key, value|
|
116
|
-
|
117
|
-
|
118
|
-
|
120
|
+
next unless key.instance_of?(::String)
|
121
|
+
|
122
|
+
sw_value = value if key == type
|
123
|
+
SolarWindsAPM.logger.debug do
|
124
|
+
"[#{self.class}/#{__method__}] obtained sw value: #{type} #{key}: #{value.inspect}"
|
119
125
|
end
|
120
126
|
end
|
121
127
|
sw_value
|