solarwinds_apm 6.1.2 → 7.0.0.prev1
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 +4 -4
- data/README.md +4 -2
- data/lib/solarwinds_apm/api/current_trace_info.rb +10 -6
- data/lib/solarwinds_apm/api/custom_metrics.rb +8 -25
- data/lib/solarwinds_apm/api/tracing.rb +12 -27
- data/lib/solarwinds_apm/api/transaction_name.rb +6 -10
- data/lib/solarwinds_apm/config.rb +1 -1
- data/lib/solarwinds_apm/constants.rb +1 -0
- data/lib/solarwinds_apm/noop/api.rb +5 -2
- data/lib/solarwinds_apm/noop.rb +0 -24
- data/lib/solarwinds_apm/opentelemetry/otlp_processor.rb +90 -69
- data/lib/solarwinds_apm/opentelemetry/solarwinds_propagator.rb +0 -2
- data/lib/solarwinds_apm/opentelemetry/solarwinds_response_propagator.rb +5 -4
- data/lib/solarwinds_apm/opentelemetry.rb +5 -7
- data/lib/solarwinds_apm/otel_native_config.rb +177 -0
- data/lib/solarwinds_apm/patch/README.md +15 -0
- data/lib/solarwinds_apm/{noop/metadata.rb → sampling/dice.rb} +19 -17
- data/lib/solarwinds_apm/sampling/http_sampler.rb +87 -0
- data/lib/solarwinds_apm/sampling/json_sampler.rb +52 -0
- data/lib/solarwinds_apm/sampling/metrics.rb +38 -0
- data/lib/solarwinds_apm/sampling/oboe_sampler.rb +348 -0
- data/lib/solarwinds_apm/sampling/sampler.rb +197 -0
- data/lib/solarwinds_apm/sampling/sampling_constants.rb +127 -0
- data/lib/solarwinds_apm/sampling/sampling_patch.rb +49 -0
- data/lib/solarwinds_apm/sampling/setting_example.txt +1 -0
- data/lib/solarwinds_apm/{noop/context.rb → sampling/settings.rb} +14 -25
- data/lib/solarwinds_apm/sampling/token_bucket.rb +126 -0
- data/lib/solarwinds_apm/sampling/trace_options.rb +100 -0
- data/lib/solarwinds_apm/{patch.rb → sampling.rb} +20 -4
- data/lib/solarwinds_apm/{noop/span.rb → support/aws_resource_detector.rb} +5 -18
- data/lib/solarwinds_apm/support/logger_formatter.rb +1 -1
- data/lib/solarwinds_apm/support/logging_log_event.rb +1 -1
- data/lib/solarwinds_apm/support/lumberjack_formatter.rb +1 -1
- data/lib/solarwinds_apm/support/otlp_endpoint.rb +99 -0
- data/lib/solarwinds_apm/support/resource_detector/aws/beanstalk.rb +51 -0
- data/lib/solarwinds_apm/support/resource_detector/aws/ec2.rb +145 -0
- data/lib/solarwinds_apm/support/resource_detector/aws/ecs.rb +173 -0
- data/lib/solarwinds_apm/support/resource_detector/aws/eks.rb +174 -0
- data/lib/solarwinds_apm/support/resource_detector/aws/lambda.rb +66 -0
- data/lib/solarwinds_apm/support/resource_detector.rb +192 -0
- data/lib/solarwinds_apm/support/service_key_checker.rb +12 -6
- data/lib/solarwinds_apm/support/transaction_settings.rb +6 -0
- data/lib/solarwinds_apm/support/txn_name_manager.rb +54 -9
- data/lib/solarwinds_apm/support/utils.rb +9 -0
- data/lib/solarwinds_apm/support.rb +3 -4
- data/lib/solarwinds_apm/version.rb +4 -4
- data/lib/solarwinds_apm.rb +27 -73
- metadata +99 -40
- data/ext/oboe_metal/extconf.rb +0 -168
- data/ext/oboe_metal/lib/liboboe-1.0-aarch64.so.sha256 +0 -1
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-aarch64.so.sha256 +0 -1
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.sha256 +0 -1
- data/ext/oboe_metal/lib/liboboe-1.0-lambda-aarch64.so.sha256 +0 -1
- data/ext/oboe_metal/lib/liboboe-1.0-lambda-x86_64.so.sha256 +0 -1
- data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.sha256 +0 -1
- data/ext/oboe_metal/src/VERSION +0 -1
- data/ext/oboe_metal/src/bson/bson.h +0 -220
- data/ext/oboe_metal/src/bson/platform_hacks.h +0 -91
- data/ext/oboe_metal/src/init_solarwinds_apm.cc +0 -18
- data/ext/oboe_metal/src/oboe.h +0 -930
- data/ext/oboe_metal/src/oboe_api.cpp +0 -793
- data/ext/oboe_metal/src/oboe_api.h +0 -621
- data/ext/oboe_metal/src/oboe_debug.h +0 -17
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +0 -11045
- data/lib/oboe_metal.rb +0 -187
- data/lib/solarwinds_apm/cert/star.appoptics.com.issuer.crt +0 -24
- data/lib/solarwinds_apm/oboe_init_options.rb +0 -222
- data/lib/solarwinds_apm/opentelemetry/solarwinds_exporter.rb +0 -239
- data/lib/solarwinds_apm/opentelemetry/solarwinds_processor.rb +0 -174
- data/lib/solarwinds_apm/opentelemetry/solarwinds_sampler.rb +0 -333
- data/lib/solarwinds_apm/otel_config.rb +0 -174
- data/lib/solarwinds_apm/otel_lambda_config.rb +0 -56
- data/lib/solarwinds_apm/patch/dummy_patch.rb +0 -12
- data/lib/solarwinds_apm/support/oboe_tracing_mode.rb +0 -33
- data/lib/solarwinds_apm/support/support_report.rb +0 -99
- data/lib/solarwinds_apm/support/transaction_cache.rb +0 -57
- data/lib/solarwinds_apm/support/x_trace_options.rb +0 -138
@@ -1,174 +0,0 @@
|
|
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
|
-
module SolarWindsAPM
|
10
|
-
module OpenTelemetry
|
11
|
-
# reference: OpenTelemetry::SDK::Trace::SpanProcessor
|
12
|
-
class SolarWindsProcessor
|
13
|
-
HTTP_METHOD = 'http.method'
|
14
|
-
HTTP_ROUTE = 'http.route'
|
15
|
-
HTTP_STATUS_CODE = 'http.status_code'
|
16
|
-
HTTP_URL = 'http.url'
|
17
|
-
LIBOBOE_HTTP_SPAN_STATUS_UNAVAILABLE = 0
|
18
|
-
|
19
|
-
attr_reader :txn_manager
|
20
|
-
|
21
|
-
def initialize(txn_manager)
|
22
|
-
@txn_manager = txn_manager
|
23
|
-
end
|
24
|
-
|
25
|
-
# Called when a {Span} is started, if the {Span#recording?}
|
26
|
-
# returns true.
|
27
|
-
#
|
28
|
-
# @param [Span] span the {Span} that just started.
|
29
|
-
# @param [Context] parent_context the parent {Context} of the newly
|
30
|
-
# started span.
|
31
|
-
def on_start(span, parent_context)
|
32
|
-
SolarWindsAPM.logger.debug do
|
33
|
-
"[#{self.class}/#{__method__}] processor on_start span: #{span.to_span_data.inspect}, parent_context: #{parent_context.inspect}"
|
34
|
-
end
|
35
|
-
|
36
|
-
return if non_entry_span(parent_context: parent_context)
|
37
|
-
|
38
|
-
trace_flags = span.context.trace_flags.sampled? ? '01' : '00'
|
39
|
-
@txn_manager.set_root_context_h(span.context.hex_trace_id, "#{span.context.hex_span_id}-#{trace_flags}")
|
40
|
-
span.add_attributes({ 'sw.is_entry_span' => true })
|
41
|
-
rescue StandardError => e
|
42
|
-
SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] processor on_start error: #{e.message}" }
|
43
|
-
end
|
44
|
-
|
45
|
-
# Called when a {Span} is ended, if the {Span#recording?}
|
46
|
-
# returns true.
|
47
|
-
#
|
48
|
-
# @param [Span] span the {Span} that just ended.
|
49
|
-
def on_finish(span)
|
50
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] processor on_finish span: #{span.to_span_data.inspect}" }
|
51
|
-
|
52
|
-
return if non_entry_span(span: span)
|
53
|
-
|
54
|
-
span_time = calculate_span_time(start_time: span.start_timestamp, end_time: span.end_timestamp)
|
55
|
-
domain = nil
|
56
|
-
has_error = error?(span)
|
57
|
-
trans_name = calculate_transaction_names(span)
|
58
|
-
if span_http?(span)
|
59
|
-
status_code = get_http_status_code(span)
|
60
|
-
request_method = span.attributes[HTTP_METHOD]
|
61
|
-
url_tran = span.attributes[HTTP_URL]
|
62
|
-
|
63
|
-
SolarWindsAPM.logger.debug do
|
64
|
-
"[#{self.class}/#{__method__}] createHttpSpan with\n
|
65
|
-
trans_name: #{trans_name}\n
|
66
|
-
url_tran: #{url_tran}\n
|
67
|
-
domain: #{domain}\n
|
68
|
-
span_time: #{span_time}\n
|
69
|
-
status_code: #{status_code}\n
|
70
|
-
request_method: #{request_method}\n
|
71
|
-
has_error: #{has_error}"
|
72
|
-
end
|
73
|
-
|
74
|
-
liboboe_txn_name = SolarWindsAPM::Span.createHttpSpan(trans_name, url_tran, domain, span_time, status_code,
|
75
|
-
request_method, has_error)
|
76
|
-
|
77
|
-
else
|
78
|
-
|
79
|
-
SolarWindsAPM.logger.debug do
|
80
|
-
"[#{self.class}/#{__method__}] createSpan with \n
|
81
|
-
trans_name: #{trans_name}\n
|
82
|
-
domain: #{domain}\n
|
83
|
-
span_time: #{span_time}\n
|
84
|
-
has_error: #{has_error}"
|
85
|
-
end
|
86
|
-
|
87
|
-
liboboe_txn_name = SolarWindsAPM::Span.createSpan(trans_name, domain, span_time, has_error)
|
88
|
-
end
|
89
|
-
|
90
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] liboboe_txn_name: #{liboboe_txn_name}" }
|
91
|
-
if span.context.trace_flags.sampled?
|
92
|
-
@txn_manager["#{span.context.hex_trace_id}-#{span.context.hex_span_id}"] =
|
93
|
-
liboboe_txn_name
|
94
|
-
end
|
95
|
-
@txn_manager.delete_root_context_h(span.context.hex_trace_id)
|
96
|
-
rescue StandardError => e
|
97
|
-
SolarWindsAPM.logger.info do
|
98
|
-
"[#{self.class}/#{__method__}] solarwinds_processor on_finish error: #{e.message}"
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# @param [optional Numeric] timeout An optional timeout in seconds.
|
103
|
-
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
104
|
-
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
105
|
-
def force_flush(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
|
106
|
-
::OpenTelemetry::SDK::Trace::Export::SUCCESS
|
107
|
-
end
|
108
|
-
|
109
|
-
# @param [optional Numeric] timeout An optional timeout in seconds.
|
110
|
-
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
111
|
-
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
112
|
-
def shutdown(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
|
113
|
-
::OpenTelemetry::SDK::Trace::Export::SUCCESS
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
# This span from inbound HTTP request if from a SERVER by some http.method
|
119
|
-
def span_http?(span)
|
120
|
-
span.kind == ::OpenTelemetry::Trace::SpanKind::SERVER && !span.attributes[HTTP_METHOD].nil?
|
121
|
-
end
|
122
|
-
|
123
|
-
# Calculate if this span instance has_error
|
124
|
-
# return [Integer]
|
125
|
-
def error?(span)
|
126
|
-
span.status.code == ::OpenTelemetry::Trace::Status::ERROR ? 1 : 0
|
127
|
-
end
|
128
|
-
|
129
|
-
# Calculate HTTP status_code from span or default to UNAVAILABLE
|
130
|
-
# Something went wrong in OTel or instrumented service crashed early
|
131
|
-
# if no status_code in attributes of HTTP span
|
132
|
-
def get_http_status_code(span)
|
133
|
-
span.attributes[HTTP_STATUS_CODE] || LIBOBOE_HTTP_SPAN_STATUS_UNAVAILABLE
|
134
|
-
end
|
135
|
-
|
136
|
-
# check if it's entry span based on no parent or parent is remote
|
137
|
-
def non_entry_span(span: nil, parent_context: nil)
|
138
|
-
if parent_context
|
139
|
-
parent_span = ::OpenTelemetry::Trace.current_span(parent_context)
|
140
|
-
parent_span && parent_span.context != ::OpenTelemetry::Trace::SpanContext::INVALID && parent_span.context.remote? == false
|
141
|
-
elsif span
|
142
|
-
span.attributes['sw.is_entry_span'] != true
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# Get trans_name and url_tran of this span instance.
|
147
|
-
# Predecessor order: custom SDK > env var SW_APM_TRANSACTION_NAME > automatic naming
|
148
|
-
def calculate_transaction_names(span)
|
149
|
-
trace_span_id = "#{span.context.hex_trace_id}-#{span.context.hex_span_id}"
|
150
|
-
trans_name = @txn_manager.get(trace_span_id)
|
151
|
-
if trans_name
|
152
|
-
SolarWindsAPM.logger.debug do
|
153
|
-
"[#{self.class}/#{__method__}] found trans name from txn_manager: #{trans_name} by #{trace_span_id}"
|
154
|
-
end
|
155
|
-
@txn_manager.del(trace_span_id)
|
156
|
-
elsif ENV.key?('SW_APM_TRANSACTION_NAME') && ENV['SW_APM_TRANSACTION_NAME'] != ''
|
157
|
-
trans_name = ENV.fetch('SW_APM_TRANSACTION_NAME', nil)
|
158
|
-
else
|
159
|
-
trans_name = span.attributes[HTTP_ROUTE] || nil
|
160
|
-
trans_name = span.name if span.name && (trans_name.nil? || trans_name.empty?)
|
161
|
-
end
|
162
|
-
trans_name
|
163
|
-
end
|
164
|
-
|
165
|
-
# Calculate span time in microseconds (us) using start and end time
|
166
|
-
# in nanoseconds (ns). OTel span start/end_time are optional.
|
167
|
-
def calculate_span_time(start_time: nil, end_time: nil)
|
168
|
-
return 0 if start_time.nil? || end_time.nil?
|
169
|
-
|
170
|
-
((end_time.to_i - start_time.to_i) / 1e3).round
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
@@ -1,333 +0,0 @@
|
|
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
|
-
module SolarWindsAPM
|
10
|
-
module OpenTelemetry
|
11
|
-
# SolarWindsSampler
|
12
|
-
class SolarWindsSampler
|
13
|
-
INTERNAL_BUCKET_CAPACITY = 'BucketCapacity'
|
14
|
-
INTERNAL_BUCKET_RATE = 'BucketRate'
|
15
|
-
INTERNAL_SAMPLE_RATE = 'SampleRate'
|
16
|
-
INTERNAL_SAMPLE_SOURCE = 'SampleSource'
|
17
|
-
INTERNAL_SW_KEYS = 'SWKeys'
|
18
|
-
LIBOBOE_CONTINUED = -1
|
19
|
-
SW_TRACESTATE_CAPTURE_KEY = 'sw.w3c.tracestate'
|
20
|
-
SW_TRACESTATE_ROOT_KEY = 'sw.tracestate_parent_id'
|
21
|
-
UNSET = -1
|
22
|
-
SWO_TRACING_ENABLED = 1
|
23
|
-
SWO_TRACING_DISABLED = 0
|
24
|
-
SWO_TRACING_UNSET = -1
|
25
|
-
XTRACEOPTIONS_RESP_AUTH = 'auth'
|
26
|
-
XTRACEOPTIONS_RESP_IGNORED = 'ignored'
|
27
|
-
XTRACEOPTIONS_RESP_TRIGGER_IGNORED = 'ignored'
|
28
|
-
XTRACEOPTIONS_RESP_TRIGGER_NOT_REQUESTED = 'not-requested'
|
29
|
-
XTRACEOPTIONS_RESP_TRIGGER_TRACE = 'trigger-trace'
|
30
|
-
|
31
|
-
attr_reader :description
|
32
|
-
|
33
|
-
def initialize(config = {})
|
34
|
-
@config = config
|
35
|
-
end
|
36
|
-
|
37
|
-
def ==(other)
|
38
|
-
@decision == other.decision && @description == other.description
|
39
|
-
end
|
40
|
-
|
41
|
-
# @api private
|
42
|
-
#
|
43
|
-
# See {Samplers}.
|
44
|
-
# trace_id
|
45
|
-
# parent_context: OpenTelemetry::Context
|
46
|
-
def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
|
47
|
-
SolarWindsAPM.logger.debug do
|
48
|
-
"[#{self.class}/#{__method__}] should_sample? start parameters \n
|
49
|
-
trace_id: #{trace_id.unpack1('H*')}\n
|
50
|
-
parent_context: #{parent_context}\n
|
51
|
-
parent_context.inspect: #{parent_context.inspect}\n
|
52
|
-
links: #{links}\n
|
53
|
-
name: #{name}\n
|
54
|
-
kind: #{kind}\n
|
55
|
-
attributes: #{attributes}"
|
56
|
-
end
|
57
|
-
|
58
|
-
SolarWindsAPM::Reporter.send(:report_init) # This only happens if after_fork enabled
|
59
|
-
|
60
|
-
parent_span_context = ::OpenTelemetry::Trace.current_span(parent_context).context
|
61
|
-
xtraceoptions = ::SolarWindsAPM::XTraceOptions.new(parent_context)
|
62
|
-
SolarWindsAPM.logger.debug do
|
63
|
-
"[#{self.class}/#{__method__}] parent_span_context: #{parent_span_context.inspect}\n xtraceoptions: #{xtraceoptions.inspect}"
|
64
|
-
end
|
65
|
-
|
66
|
-
liboboe_decision = calculate_liboboe_decision(parent_span_context, xtraceoptions, name, kind, attributes)
|
67
|
-
otel_decision = otel_decision_from_liboboe(liboboe_decision)
|
68
|
-
new_trace_state = calculate_trace_state(liboboe_decision, parent_span_context, xtraceoptions)
|
69
|
-
new_attributes = if otel_sampled?(otel_decision)
|
70
|
-
calculate_attributes(attributes, liboboe_decision,
|
71
|
-
new_trace_state, parent_span_context, xtraceoptions)
|
72
|
-
end
|
73
|
-
sampling_result = ::OpenTelemetry::SDK::Trace::Samplers::Result.new(decision: otel_decision,
|
74
|
-
attributes: new_attributes,
|
75
|
-
tracestate: new_trace_state)
|
76
|
-
|
77
|
-
SolarWindsAPM.logger.debug do
|
78
|
-
"[#{self.class}/#{__method__}] should_sample? end with sampling_result: #{sampling_result.inspect} from otel_decision: #{otel_decision.inspect} and new_attributes: #{new_attributes.inspect}"
|
79
|
-
end
|
80
|
-
sampling_result
|
81
|
-
rescue StandardError => e
|
82
|
-
SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] sampler error: #{e.message}" }
|
83
|
-
::OpenTelemetry::SDK::Trace::Samplers::Result.new(decision: ::OpenTelemetry::SDK::Trace::Samplers::Decision::DROP,
|
84
|
-
attributes: attributes,
|
85
|
-
tracestate: ::OpenTelemetry::Trace::Tracestate::DEFAULT)
|
86
|
-
end
|
87
|
-
|
88
|
-
protected
|
89
|
-
|
90
|
-
attr_reader :decision
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
##
|
95
|
-
# use parent_span_context and xtraceoptions object to feed to liboboe function getDecisions that get liboboe_decision
|
96
|
-
# name, kind and attributes are used for transaction filter caching (to avoid continous calculate_trace_mode calculation)
|
97
|
-
# return decision Hash
|
98
|
-
def calculate_liboboe_decision(parent_span_context, xtraceoptions, name, kind, attributes)
|
99
|
-
tracestring = Utils.traceparent_from_context(parent_span_context) if parent_span_context.valid? && parent_span_context.remote?
|
100
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] tracestring: #{tracestring}" }
|
101
|
-
|
102
|
-
# otel-ruby contrib use different key to store url info, currently it's using http.target for path
|
103
|
-
url_path = attributes.nil? ? '' : attributes['http.target']
|
104
|
-
transaction_naming_key = "#{url_path}-#{name}-#{kind}"
|
105
|
-
tracing_mode = SolarWindsAPM::TransactionCache.get(transaction_naming_key)
|
106
|
-
SolarWindsAPM.logger.debug do
|
107
|
-
"[#{self.class}/#{__method__}] transaction cache: #{transaction_naming_key}; tracing_mode: #{tracing_mode}."
|
108
|
-
end
|
109
|
-
|
110
|
-
unless tracing_mode
|
111
|
-
trans_settings = SolarWindsAPM::TransactionSettings.new(url_path: url_path, name: name, kind: kind)
|
112
|
-
tracing_mode = trans_settings.calculate_trace_mode == 1 ? SWO_TRACING_ENABLED : SWO_TRACING_DISABLED
|
113
|
-
SolarWindsAPM::TransactionCache.set(transaction_naming_key, tracing_mode)
|
114
|
-
end
|
115
|
-
|
116
|
-
sw_member_value = parent_span_context.tracestate[SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY]
|
117
|
-
trigger_trace_mode = SolarWindsAPM::OboeTracingMode.get_oboe_trigger_trace_mode(@config['trigger_trace'])
|
118
|
-
sample_rate = UNSET
|
119
|
-
options = xtraceoptions&.options
|
120
|
-
trigger_trace = xtraceoptions&.intify_trigger_trace || 0
|
121
|
-
signature = xtraceoptions&.signature
|
122
|
-
timestamp = xtraceoptions&.timestamp
|
123
|
-
|
124
|
-
SolarWindsAPM.logger.debug do
|
125
|
-
"[#{self.class}/#{__method__}] get liboboe decision parameters: \n
|
126
|
-
tracestring: #{tracestring}\n
|
127
|
-
sw_member_value: #{sw_member_value}\n
|
128
|
-
tracing_mode: #{tracing_mode}\n
|
129
|
-
sample_rate: #{sample_rate}\n
|
130
|
-
trigger_trace: #{trigger_trace}\n
|
131
|
-
trigger_trace_mode: #{trigger_trace_mode}\n
|
132
|
-
options: #{options}\n
|
133
|
-
signature: #{signature}\n
|
134
|
-
timestamp: #{timestamp}"
|
135
|
-
end
|
136
|
-
|
137
|
-
args = [tracestring, sw_member_value, tracing_mode, sample_rate,
|
138
|
-
trigger_trace, trigger_trace_mode, options, signature, timestamp]
|
139
|
-
|
140
|
-
if SolarWindsAPM::OboeInitOptions.instance.lambda_env
|
141
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] get decision from oboe_api" }
|
142
|
-
# trigger trace disabled at this point (https://swicloud.atlassian.net/wiki/spaces/NIT/pages/3753116438/AWS+Lambda+Instrumentation+POC#Concerns)
|
143
|
-
do_metrics, do_sample, rate, source, bucket_rate,
|
144
|
-
bucket_cap, decision_type, auth, status_msg, auth_msg,
|
145
|
-
status = SolarWindsAPM.oboe_api.getTracingDecision(*args)
|
146
|
-
else
|
147
|
-
do_metrics, do_sample, rate, source, bucket_rate,
|
148
|
-
bucket_cap, decision_type, auth, status_msg, auth_msg,
|
149
|
-
status = SolarWindsAPM::Context.getDecisions(*args)
|
150
|
-
end
|
151
|
-
|
152
|
-
{
|
153
|
-
'do_metrics' => do_metrics.positive?,
|
154
|
-
'do_sample' => do_sample.positive?,
|
155
|
-
'rate' => rate,
|
156
|
-
'source' => source,
|
157
|
-
'bucket_rate' => bucket_rate,
|
158
|
-
'bucket_cap' => bucket_cap,
|
159
|
-
'decision_type' => decision_type,
|
160
|
-
'auth' => auth,
|
161
|
-
'status_msg' => status_msg,
|
162
|
-
'auth_msg' => auth_msg,
|
163
|
-
'status' => status
|
164
|
-
}
|
165
|
-
end
|
166
|
-
|
167
|
-
def otel_decision_from_liboboe(liboboe_decision)
|
168
|
-
decision = ::OpenTelemetry::SDK::Trace::Samplers::Decision::DROP
|
169
|
-
if liboboe_decision['do_sample']
|
170
|
-
decision = ::OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_AND_SAMPLE # even if not do_metrics
|
171
|
-
elsif liboboe_decision['do_metrics']
|
172
|
-
decision = ::OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_ONLY
|
173
|
-
end
|
174
|
-
SolarWindsAPM.logger.debug { "otel decision: #{decision} created from liboboe_decision: #{liboboe_decision}" }
|
175
|
-
decision
|
176
|
-
end
|
177
|
-
|
178
|
-
##
|
179
|
-
# add sw=value and xtrace_options_response=value into the old/new tracestate
|
180
|
-
# the returned value tracestate will be used in propagating to next services
|
181
|
-
def calculate_trace_state(liboboe_decision, parent_span_context, xtraceoptions)
|
182
|
-
if !parent_span_context.valid? || parent_span_context.tracestate.nil?
|
183
|
-
trace_state = create_new_trace_state(parent_span_context, liboboe_decision)
|
184
|
-
else
|
185
|
-
trace_state = parent_span_context.tracestate.set_value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY,
|
186
|
-
sw_from_span_and_decision(parent_span_context,
|
187
|
-
liboboe_decision))
|
188
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] updated trace_state: #{trace_state.inspect}" }
|
189
|
-
end
|
190
|
-
|
191
|
-
# for setting up the xtrace_options_response
|
192
|
-
if xtraceoptions&.options
|
193
|
-
trace_state = trace_state.set_value(XTraceOptions.sw_xtraceoptions_response_key.to_s,
|
194
|
-
create_xtraceoptions_response_value(liboboe_decision,
|
195
|
-
parent_span_context, xtraceoptions))
|
196
|
-
end
|
197
|
-
trace_state
|
198
|
-
end
|
199
|
-
|
200
|
-
##
|
201
|
-
#
|
202
|
-
def create_new_trace_state(parent_span_context, liboboe_decision)
|
203
|
-
decision = sw_from_span_and_decision(parent_span_context, liboboe_decision)
|
204
|
-
trace_state = ::OpenTelemetry::Trace::Tracestate.from_hash({ SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY => decision }) # e.g. sw=3e222c863a04123a-01
|
205
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] created new trace_state: #{trace_state.inspect}" }
|
206
|
-
trace_state
|
207
|
-
end
|
208
|
-
|
209
|
-
##
|
210
|
-
#
|
211
|
-
def create_xtraceoptions_response_value(liboboe_decision, parent_span_context, xtraceoptions)
|
212
|
-
response = []
|
213
|
-
w3c_sanitized = SolarWindsAPM::Constants::INTL_SWO_EQUALS_W3C_SANITIZED
|
214
|
-
w3c_sanitized_comma = SolarWindsAPM::Constants::INTL_SWO_COMMA_W3C_SANITIZED
|
215
|
-
if xtraceoptions.signature && liboboe_decision['auth_msg']
|
216
|
-
response << [XTRACEOPTIONS_RESP_AUTH,
|
217
|
-
liboboe_decision['auth_msg']].join(w3c_sanitized)
|
218
|
-
end
|
219
|
-
|
220
|
-
if !liboboe_decision['auth'] || liboboe_decision['auth'] < 1
|
221
|
-
if xtraceoptions.trigger_trace
|
222
|
-
# If a traceparent header was provided then oboe does not generate the message
|
223
|
-
tracestring = Utils.traceparent_from_context(parent_span_context) if parent_span_context.valid? && parent_span_context.remote?
|
224
|
-
trigger_msg = tracestring && (liboboe_decision['decision_type']).zero? ? XTRACEOPTIONS_RESP_TRIGGER_IGNORED : liboboe_decision['status_msg']
|
225
|
-
SolarWindsAPM.logger.debug do
|
226
|
-
"[#{self.class}/#{__method__}] tracestring: #{tracestring}; trigger_msg: #{trigger_msg}"
|
227
|
-
end
|
228
|
-
else
|
229
|
-
trigger_msg = XTRACEOPTIONS_RESP_TRIGGER_NOT_REQUESTED
|
230
|
-
end
|
231
|
-
|
232
|
-
response << [XTRACEOPTIONS_RESP_TRIGGER_TRACE, trigger_msg].join(w3c_sanitized) # e.g. response << trigger-trace####ok
|
233
|
-
end
|
234
|
-
|
235
|
-
# appending ignored value from xtraceoptions to response. e.g. response << ignored####invalidkeys,invalidkeys,invalidkeys
|
236
|
-
unless xtraceoptions.ignored.empty?
|
237
|
-
response << [XTRACEOPTIONS_RESP_IGNORED,
|
238
|
-
xtraceoptions.ignored.join(w3c_sanitized_comma)].join(w3c_sanitized)
|
239
|
-
end
|
240
|
-
joined_response = response.join(';')
|
241
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] final response_value: #{joined_response}" }
|
242
|
-
joined_response
|
243
|
-
end
|
244
|
-
|
245
|
-
##
|
246
|
-
# calculate_attributes is used for getting the otel Result class in last step of sampler should_sample?
|
247
|
-
# e.g. result = Result.new(decision: otel_decision, attributes: new_attributes, tracestate: new_trace_state)
|
248
|
-
# calculate_attributes use new_trace_state that is derived from current span information and old tracestate from parent_span_context.tracestate
|
249
|
-
# the sw.w3c.tracestate should perserve the old tracestate value for debugging purpose
|
250
|
-
def calculate_attributes(attributes, liboboe_decision, trace_state, parent_span_context, xtraceoptions)
|
251
|
-
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] new_trace_state: #{trace_state.inspect}" }
|
252
|
-
new_attributes = attributes.dup || {}
|
253
|
-
|
254
|
-
# Always (root or is_remote) set _INTERNAL_SW_KEYS if injected
|
255
|
-
new_attributes[INTERNAL_SW_KEYS] = xtraceoptions.sw_keys if xtraceoptions.sw_keys
|
256
|
-
|
257
|
-
# Always (root or is_remote) set custom KVs if extracted from x-trace-options
|
258
|
-
xtraceoptions.custom_kvs&.each { |k, v| new_attributes[k] = v }
|
259
|
-
|
260
|
-
# Always (root or is_remote) set service entry internal KVs
|
261
|
-
new_attributes[INTERNAL_BUCKET_CAPACITY] = liboboe_decision['bucket_cap'].to_s
|
262
|
-
new_attributes[INTERNAL_BUCKET_RATE] = liboboe_decision['bucket_rate'].to_s
|
263
|
-
new_attributes[INTERNAL_SAMPLE_RATE] = liboboe_decision['rate']
|
264
|
-
new_attributes[INTERNAL_SAMPLE_SOURCE] = liboboe_decision['source']
|
265
|
-
|
266
|
-
# set sw.tracestate_parent_id if its tracestate contains "sw"
|
267
|
-
sw_value = parent_span_context.tracestate.value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY)
|
268
|
-
new_attributes[SW_TRACESTATE_ROOT_KEY] = sw_value.split('-')[0] if sw_value && parent_span_context.remote?
|
269
|
-
|
270
|
-
# If unsigned or signed TT (root or is_remote), set TriggeredTrace
|
271
|
-
new_attributes[SolarWindsAPM::Constants::INTERNAL_TRIGGERED_TRACE] = true if xtraceoptions.trigger_trace
|
272
|
-
|
273
|
-
# Trace's root span has no valid traceparent nor tracestate so we can't calculate remaining attributes
|
274
|
-
if !parent_span_context.valid? || trace_state.nil?
|
275
|
-
SolarWindsAPM.logger.debug do
|
276
|
-
"[#{self.class}/#{__method__}] No valid traceparent or no tracestate - returning attributes: #{new_attributes}"
|
277
|
-
end
|
278
|
-
return new_attributes.freeze || nil
|
279
|
-
end
|
280
|
-
|
281
|
-
new_attributes = add_tracestate_capture_to_new_attributes(new_attributes, liboboe_decision, trace_state,
|
282
|
-
parent_span_context)
|
283
|
-
new_attributes.freeze
|
284
|
-
end
|
285
|
-
|
286
|
-
##
|
287
|
-
#
|
288
|
-
def add_tracestate_capture_to_new_attributes(new_attributes, liboboe_decision, trace_state, parent_span_context)
|
289
|
-
tracestate_capture = new_attributes[SW_TRACESTATE_CAPTURE_KEY]
|
290
|
-
SolarWindsAPM.logger.debug do
|
291
|
-
"[#{self.class}/#{__method__}] tracestate_capture #{tracestate_capture.inspect}; new_attributes #{new_attributes.inspect}"
|
292
|
-
end
|
293
|
-
|
294
|
-
if tracestate_capture.nil?
|
295
|
-
trace_state_no_response = trace_state.delete(XTraceOptions.sw_xtraceoptions_response_key)
|
296
|
-
else
|
297
|
-
# retain all potential tracestate pairs for attributes and generate new sw=key for tracestate based on root parent_span_id
|
298
|
-
attr_trace_state = ::OpenTelemetry::Trace::Tracestate.from_string(tracestate_capture)
|
299
|
-
new_attr_trace_state = attr_trace_state.set_value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY,
|
300
|
-
sw_from_span_and_decision(parent_span_context,
|
301
|
-
liboboe_decision))
|
302
|
-
trace_state_no_response = new_attr_trace_state.delete(XTraceOptions.sw_xtraceoptions_response_key)
|
303
|
-
end
|
304
|
-
SolarWindsAPM.logger.debug do
|
305
|
-
"[#{self.class}/#{__method__}] trace_state_no_response #{trace_state_no_response.inspect}"
|
306
|
-
end
|
307
|
-
|
308
|
-
trace_state_no_response = parent_span_context.tracestate.delete(XTraceOptions.sw_xtraceoptions_response_key)
|
309
|
-
no_sw_count = trace_state_no_response.to_h.count { |k, _v| k != 'sw' }
|
310
|
-
|
311
|
-
if no_sw_count.positive?
|
312
|
-
new_attributes[SW_TRACESTATE_CAPTURE_KEY] =
|
313
|
-
Utils.trace_state_header(trace_state_no_response)
|
314
|
-
end
|
315
|
-
SolarWindsAPM.logger.debug do
|
316
|
-
"[#{self.class}/#{__method__}] new_attributes after add_tracestate_capture_to_new_attributes: #{new_attributes.inspect}"
|
317
|
-
end
|
318
|
-
|
319
|
-
new_attributes
|
320
|
-
end
|
321
|
-
|
322
|
-
# formats tracestate sw value from span_id and liboboe decision as 16-byte span_id with 8-bit trace_flags e.g. 1a2b3c4d5e6f7g8h-01
|
323
|
-
def sw_from_span_and_decision(parent_span_context, liboboe_decision)
|
324
|
-
trace_flag = liboboe_decision['do_sample'] == true ? '01' : '00'
|
325
|
-
[parent_span_context.hex_span_id, trace_flag].join('-')
|
326
|
-
end
|
327
|
-
|
328
|
-
def otel_sampled?(otel_decision)
|
329
|
-
otel_decision == ::OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_AND_SAMPLE
|
330
|
-
end
|
331
|
-
end
|
332
|
-
end
|
333
|
-
end
|
@@ -1,174 +0,0 @@
|
|
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
|
-
module SolarWindsAPM
|
10
|
-
# OTelConfig module
|
11
|
-
# For configure otel component: configurable: propagator, exporter
|
12
|
-
# non-config: sampler, processor, response_propagator
|
13
|
-
# Level of this configuration: SolarWindsOTel::Config -> OboeOption -> SolarWindsOTel::OTelConfig
|
14
|
-
module OTelConfig
|
15
|
-
@@config = {}
|
16
|
-
@@config_map = {}
|
17
|
-
|
18
|
-
@@agent_enabled = true
|
19
|
-
|
20
|
-
def self.disable_agent(reason: nil)
|
21
|
-
return unless @@agent_enabled # only show the msg once
|
22
|
-
|
23
|
-
@@agent_enabled = false
|
24
|
-
SolarWindsAPM.logger.warn { "[#{name}/#{__method__}] SolarWindsAPM disabled. No Trace exported. Reason: #{reason}" }
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.resolve_sampler
|
28
|
-
sampler_config = { 'trigger_trace' => SolarWindsAPM::Config[:trigger_tracing_mode] }
|
29
|
-
@@config[:sampler] =
|
30
|
-
::OpenTelemetry::SDK::Trace::Samplers.parent_based(
|
31
|
-
root: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config),
|
32
|
-
remote_parent_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config),
|
33
|
-
remote_parent_not_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config)
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
#
|
38
|
-
# append/add solarwinds_response_propagator into rack instrumentation
|
39
|
-
#
|
40
|
-
def self.resolve_response_propagator
|
41
|
-
response_propagator = SolarWindsAPM::OpenTelemetry::SolarWindsResponsePropagator::TextMapPropagator.new
|
42
|
-
rack_setting = @@config_map['OpenTelemetry::Instrumentation::Rack']
|
43
|
-
|
44
|
-
if rack_setting
|
45
|
-
if rack_setting[:response_propagators].instance_of?(Array)
|
46
|
-
rack_setting[:response_propagators].append(response_propagator)
|
47
|
-
elsif rack_setting[:response_propagators].nil?
|
48
|
-
rack_setting[:response_propagators] = [response_propagator]
|
49
|
-
else
|
50
|
-
SolarWindsAPM.logger.warn do
|
51
|
-
"[#{name}/#{__method__}] Rack response propagator resolve failed. Provided type #{rack_setting[:response_propagators].class}, please provide Array e.g. [#{rack_setting[:response_propagators]}]"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
else
|
55
|
-
@@config_map['OpenTelemetry::Instrumentation::Rack'] = { response_propagators: [response_propagator] }
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.[](key)
|
60
|
-
@@config[key.to_sym]
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.print_config
|
64
|
-
@@config.each do |k, v|
|
65
|
-
SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] Config Key/Value: #{k}, #{v.class}" }
|
66
|
-
end
|
67
|
-
@@config_map.each do |k, v|
|
68
|
-
SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] Config Key/Value: #{k}, #{v}" }
|
69
|
-
end
|
70
|
-
nil
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.resolve_solarwinds_processor
|
74
|
-
txn_manager = SolarWindsAPM::TxnNameManager.new
|
75
|
-
exporter = SolarWindsAPM::OpenTelemetry::SolarWindsExporter.new(txn_manager: txn_manager)
|
76
|
-
@@config[:metrics_processor] = SolarWindsAPM::OpenTelemetry::SolarWindsProcessor.new(txn_manager)
|
77
|
-
@@config[:span_processor] = ::OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(exporter)
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.resolve_solarwinds_propagator
|
81
|
-
@@config[:propagators] = SolarWindsAPM::OpenTelemetry::SolarWindsPropagator::TextMapPropagator.new
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.validate_propagator(propagators)
|
85
|
-
if propagators.nil?
|
86
|
-
disable_agent(reason: 'propagators are invaliad.')
|
87
|
-
return
|
88
|
-
end
|
89
|
-
|
90
|
-
SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] propagators: #{propagators.map(&:class)}" }
|
91
|
-
disable_agent(reason: 'Missing tracecontext propagator.') unless ([::OpenTelemetry::Trace::Propagation::TraceContext::TextMapPropagator, ::OpenTelemetry::Baggage::Propagation::TextMapPropagator] - propagators.map(&:class)).empty?
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.initialize
|
95
|
-
unless defined?(::OpenTelemetry::SDK::Configurator)
|
96
|
-
disable_agent(reason: 'missing OpenTelemetry::SDK::Configurator; opentelemetry seems not loaded.')
|
97
|
-
return
|
98
|
-
end
|
99
|
-
|
100
|
-
resolve_sampler
|
101
|
-
resolve_solarwinds_propagator
|
102
|
-
resolve_solarwinds_processor
|
103
|
-
resolve_response_propagator
|
104
|
-
|
105
|
-
print_config if SolarWindsAPM.logger.level.zero?
|
106
|
-
|
107
|
-
# resolve OTEL environmental variables
|
108
|
-
ENV['OTEL_TRACES_EXPORTER'] = 'none' if ENV['OTEL_TRACES_EXPORTER'].to_s.empty?
|
109
|
-
if ENV['OTEL_LOG_LEVEL'].to_s.empty?
|
110
|
-
log_level = (ENV['SW_APM_DEBUG_LEVEL'] || SolarWindsAPM::Config[:debug_level] || 3).to_i
|
111
|
-
ENV['OTEL_LOG_LEVEL'] = SolarWindsAPM::Config::SW_LOG_LEVEL_MAPPING.dig(log_level, :otel)
|
112
|
-
end
|
113
|
-
|
114
|
-
# for dbo, traceparent injection as comments
|
115
|
-
require_relative 'patch/tag_sql_patch' if SolarWindsAPM::Config[:tag_sql]
|
116
|
-
|
117
|
-
::OpenTelemetry::SDK.configure { |c| c.use_all(@@config_map) }
|
118
|
-
|
119
|
-
validate_propagator(::OpenTelemetry.propagation.instance_variable_get(:@propagators))
|
120
|
-
|
121
|
-
return unless @@agent_enabled
|
122
|
-
|
123
|
-
# append our propagators
|
124
|
-
::OpenTelemetry.propagation.instance_variable_get(:@propagators).append(@@config[:propagators])
|
125
|
-
|
126
|
-
# append our processors (with our exporter)
|
127
|
-
::OpenTelemetry.tracer_provider.add_span_processor(@@config[:metrics_processor])
|
128
|
-
::OpenTelemetry.tracer_provider.add_span_processor(@@config[:span_processor])
|
129
|
-
|
130
|
-
# configure sampler afterwards
|
131
|
-
::OpenTelemetry.tracer_provider.sampler = @@config[:sampler]
|
132
|
-
|
133
|
-
if ENV['SW_APM_AUTO_CONFIGURE'] == 'false'
|
134
|
-
SolarWindsAPM.logger.info '==================================================================='
|
135
|
-
SolarWindsAPM.logger.info "\e[1mSolarWindsAPM manual initialization was successful.\e[0m"
|
136
|
-
SolarWindsAPM.logger.info '==================================================================='
|
137
|
-
end
|
138
|
-
|
139
|
-
nil
|
140
|
-
end
|
141
|
-
|
142
|
-
#
|
143
|
-
# Allow initialize after set new value to SolarWindsAPM::Config[:key]=value
|
144
|
-
#
|
145
|
-
# Usage:
|
146
|
-
#
|
147
|
-
# Default using the use_all to load all instrumentation
|
148
|
-
# But with specific instrumentation disabled, use {:enabled: false} in config
|
149
|
-
# SolarWindsAPM::OTelConfig.initialize_with_config do |config|
|
150
|
-
# config["OpenTelemetry::Instrumentation::Rack"] = {"a" => "b"}
|
151
|
-
# config["OpenTelemetry::Instrumentation::Dalli"] = {:enabled: false}
|
152
|
-
# end
|
153
|
-
#
|
154
|
-
def self.initialize_with_config
|
155
|
-
unless block_given?
|
156
|
-
SolarWindsAPM.logger.warn do
|
157
|
-
"[#{name}/#{__method__}] Block not given while doing in-code configuration. Agent disabled."
|
158
|
-
end
|
159
|
-
return
|
160
|
-
end
|
161
|
-
|
162
|
-
yield @@config_map
|
163
|
-
|
164
|
-
if @@config_map.empty?
|
165
|
-
SolarWindsAPM.logger.warn do
|
166
|
-
"[#{name}/#{__method__}] No configuration given for in-code configuration. Agent disabled."
|
167
|
-
end
|
168
|
-
return
|
169
|
-
end
|
170
|
-
|
171
|
-
initialize
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|