solarwinds_apm 6.0.0.prev6 → 6.0.1
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/ext/oboe_metal/extconf.rb +43 -42
- 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 +46 -84
- 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 +10 -6
- data/lib/solarwinds_apm/api/tracing.rb +7 -5
- data/lib/solarwinds_apm/api/transaction_name.rb +21 -11
- data/lib/solarwinds_apm/api.rb +8 -6
- data/lib/solarwinds_apm/config.rb +72 -47
- data/lib/solarwinds_apm/constants.rb +26 -26
- data/lib/solarwinds_apm/logger.rb +2 -0
- data/lib/solarwinds_apm/noop/README.md +1 -1
- data/lib/solarwinds_apm/noop/api.rb +85 -0
- data/lib/solarwinds_apm/noop/context.rb +15 -2
- data/lib/solarwinds_apm/noop/metadata.rb +7 -2
- data/lib/solarwinds_apm/{base.rb → noop/span.rb} +16 -15
- data/lib/solarwinds_apm/noop.rb +33 -0
- data/lib/solarwinds_apm/oboe_init_options.rb +50 -111
- 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 +50 -52
- 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 +136 -99
- data/lib/solarwinds_apm/opentelemetry.rb +8 -5
- data/lib/solarwinds_apm/otel_config.rb +38 -43
- data/lib/solarwinds_apm/otel_lambda_config.rb +53 -0
- data/lib/solarwinds_apm/patch/dummy_patch.rb +12 -0
- data/lib/solarwinds_apm/{thread_local.rb → patch.rb} +6 -22
- 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 +22 -22
- data/lib/solarwinds_apm/support/service_key_checker.rb +106 -0
- data/lib/solarwinds_apm/{support_report.rb → support/support_report.rb} +15 -10
- 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 -23
- data/lib/solarwinds_apm/version.rb +4 -2
- data/lib/solarwinds_apm.rb +82 -52
- metadata +23 -28
@@ -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,56 +10,46 @@ module SolarWindsAPM
|
|
8
10
|
module OpenTelemetry
|
9
11
|
# reference: OpenTelemetry::SDK::Trace::SpanProcessor
|
10
12
|
class SolarWindsProcessor
|
11
|
-
HTTP_METHOD =
|
12
|
-
HTTP_ROUTE =
|
13
|
-
HTTP_STATUS_CODE =
|
14
|
-
HTTP_URL =
|
13
|
+
HTTP_METHOD = 'http.method'
|
14
|
+
HTTP_ROUTE = 'http.route'
|
15
|
+
HTTP_STATUS_CODE = 'http.status_code'
|
16
|
+
HTTP_URL = 'http.url'
|
15
17
|
LIBOBOE_HTTP_SPAN_STATUS_UNAVAILABLE = 0
|
16
18
|
|
17
19
|
attr_reader :txn_manager
|
18
20
|
|
19
|
-
def initialize(
|
20
|
-
@exporter = exporter
|
21
|
+
def initialize(txn_manager)
|
21
22
|
@txn_manager = txn_manager
|
22
23
|
end
|
23
24
|
|
24
25
|
# Called when a {Span} is started, if the {Span#recording?}
|
25
26
|
# returns true.
|
26
27
|
#
|
27
|
-
# This method is called synchronously on the execution thread, should
|
28
|
-
# not throw or block the execution thread.
|
29
|
-
#
|
30
28
|
# @param [Span] span the {Span} that just started.
|
31
29
|
# @param [Context] parent_context the parent {Context} of the newly
|
32
30
|
# started span.
|
33
31
|
def on_start(span, parent_context)
|
32
|
+
SolarWindsAPM.logger.debug do
|
33
|
+
"[#{self.class}/#{__method__}] processor on_start span: #{span.inspect}, parent_context: #{parent_context.inspect}"
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
parent_span = ::OpenTelemetry::Trace.current_span(parent_context)
|
38
|
-
return if parent_span && parent_span.context != ::OpenTelemetry::Trace::SpanContext::INVALID && parent_span.context.remote? == false
|
36
|
+
return if non_entry_span(parent_context: parent_context)
|
39
37
|
|
40
38
|
trace_flags = span.context.trace_flags.sampled? ? '01' : '00'
|
41
|
-
@txn_manager.set_root_context_h(span.context.hex_trace_id,"#{span.context.hex_span_id}-#{trace_flags}")
|
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 })
|
42
41
|
rescue StandardError => e
|
43
|
-
SolarWindsAPM.logger.info {"[#{self.class}/#{__method__}] processor on_start error: #{e.message}"}
|
42
|
+
SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] processor on_start error: #{e.message}" }
|
44
43
|
end
|
45
44
|
|
46
45
|
# Called when a {Span} is ended, if the {Span#recording?}
|
47
46
|
# returns true.
|
48
47
|
#
|
49
|
-
# This method is called synchronously on the execution thread, should
|
50
|
-
# not throw or block the execution thread.
|
51
|
-
# Only calculate inbound metrics for service root spans
|
52
|
-
#
|
53
48
|
# @param [Span] span the {Span} that just ended.
|
54
49
|
def on_finish(span)
|
55
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] processor on_finish span: #{span.inspect}"}
|
50
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] processor on_finish span: #{span.inspect}" }
|
56
51
|
|
57
|
-
if span
|
58
|
-
@exporter&.export([span.to_span_data]) if span.context.trace_flags.sampled?
|
59
|
-
return
|
60
|
-
end
|
52
|
+
return if non_entry_span(span: span)
|
61
53
|
|
62
54
|
span_time = calculate_span_time(start_time: span.start_timestamp, end_time: span.end_timestamp)
|
63
55
|
domain = nil
|
@@ -68,7 +60,7 @@ module SolarWindsAPM
|
|
68
60
|
request_method = span.attributes[HTTP_METHOD]
|
69
61
|
url_tran = span.attributes[HTTP_URL]
|
70
62
|
|
71
|
-
SolarWindsAPM.logger.debug do
|
63
|
+
SolarWindsAPM.logger.debug do
|
72
64
|
"[#{self.class}/#{__method__}] createHttpSpan with\n
|
73
65
|
trans_name: #{trans_name}\n
|
74
66
|
url_tran: #{url_tran}\n
|
@@ -79,11 +71,12 @@ module SolarWindsAPM
|
|
79
71
|
has_error: #{has_error}"
|
80
72
|
end
|
81
73
|
|
82
|
-
liboboe_txn_name = SolarWindsAPM::Span.createHttpSpan(trans_name,url_tran,domain,span_time,status_code,
|
83
|
-
|
74
|
+
liboboe_txn_name = SolarWindsAPM::Span.createHttpSpan(trans_name, url_tran, domain, span_time, status_code,
|
75
|
+
request_method, has_error)
|
76
|
+
|
84
77
|
else
|
85
|
-
|
86
|
-
SolarWindsAPM.logger.debug do
|
78
|
+
|
79
|
+
SolarWindsAPM.logger.debug do
|
87
80
|
"[#{self.class}/#{__method__}] createSpan with \n
|
88
81
|
trans_name: #{trans_name}\n
|
89
82
|
domain: #{domain}\n
|
@@ -94,37 +87,30 @@ module SolarWindsAPM
|
|
94
87
|
liboboe_txn_name = SolarWindsAPM::Span.createSpan(trans_name, domain, span_time, has_error)
|
95
88
|
end
|
96
89
|
|
97
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] liboboe_txn_name: #{liboboe_txn_name}"}
|
98
|
-
|
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
|
99
95
|
@txn_manager.delete_root_context_h(span.context.hex_trace_id)
|
100
|
-
@exporter&.export([span.to_span_data]) if span.context.trace_flags.sampled?
|
101
96
|
rescue StandardError => e
|
102
|
-
SolarWindsAPM.logger.info
|
103
|
-
|
97
|
+
SolarWindsAPM.logger.info do
|
98
|
+
"[#{self.class}/#{__method__}] solarwinds_processor on_finish error: #{e.message}"
|
99
|
+
end
|
104
100
|
end
|
105
101
|
|
106
|
-
# Export all ended spans to the configured `Exporter` that have not yet
|
107
|
-
# been exported.
|
108
|
-
#
|
109
|
-
# This method should only be called in cases where it is absolutely
|
110
|
-
# necessary, such as when using some FaaS providers that may suspend
|
111
|
-
# the process after an invocation, but before the `Processor` exports
|
112
|
-
# the completed spans.
|
113
|
-
#
|
114
102
|
# @param [optional Numeric] timeout An optional timeout in seconds.
|
115
103
|
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
116
104
|
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
117
|
-
def force_flush(timeout: nil)
|
118
|
-
|
105
|
+
def force_flush(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
|
106
|
+
::OpenTelemetry::SDK::Trace::Export::SUCCESS
|
119
107
|
end
|
120
108
|
|
121
|
-
# Called when {TracerProvider#shutdown} is called.
|
122
|
-
#
|
123
109
|
# @param [optional Numeric] timeout An optional timeout in seconds.
|
124
110
|
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
125
111
|
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
126
|
-
def shutdown(timeout: nil)
|
127
|
-
|
112
|
+
def shutdown(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
|
113
|
+
::OpenTelemetry::SDK::Trace::Export::SUCCESS
|
128
114
|
end
|
129
115
|
|
130
116
|
private
|
@@ -147,16 +133,28 @@ module SolarWindsAPM
|
|
147
133
|
span.attributes[HTTP_STATUS_CODE] || LIBOBOE_HTTP_SPAN_STATUS_UNAVAILABLE
|
148
134
|
end
|
149
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
|
+
|
150
146
|
# Get trans_name and url_tran of this span instance.
|
151
147
|
# Predecessor order: custom SDK > env var SW_APM_TRANSACTION_NAME > automatic naming
|
152
148
|
def calculate_transaction_names(span)
|
153
149
|
trace_span_id = "#{span.context.hex_trace_id}-#{span.context.hex_span_id}"
|
154
150
|
trans_name = @txn_manager.get(trace_span_id)
|
155
151
|
if trans_name
|
156
|
-
SolarWindsAPM.logger.debug
|
152
|
+
SolarWindsAPM.logger.debug do
|
153
|
+
"[#{self.class}/#{__method__}] found trans name from txn_manager: #{trans_name} by #{trace_span_id}"
|
154
|
+
end
|
157
155
|
@txn_manager.del(trace_span_id)
|
158
|
-
elsif ENV.
|
159
|
-
trans_name =
|
156
|
+
elsif ENV.key?('SW_APM_TRANSACTION_NAME') && ENV['SW_APM_TRANSACTION_NAME'] != ''
|
157
|
+
trans_name = ENV.fetch('SW_APM_TRANSACTION_NAME', nil)
|
160
158
|
else
|
161
159
|
trans_name = span.attributes[HTTP_ROUTE] || nil
|
162
160
|
trans_name = span.name if span.name && (trans_name.nil? || trans_name.empty?)
|
@@ -173,4 +171,4 @@ module SolarWindsAPM
|
|
173
171
|
end
|
174
172
|
end
|
175
173
|
end
|
176
|
-
end
|
174
|
+
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
|
@@ -10,14 +12,14 @@ module SolarWindsAPM
|
|
10
12
|
# TextMapPropagator
|
11
13
|
# propagator error will be rescued by OpenTelemetry::Context::Propagation::TextMapPropagator
|
12
14
|
class TextMapPropagator
|
13
|
-
TRACESTATE_HEADER_NAME =
|
14
|
-
XTRACEOPTIONS_HEADER_NAME =
|
15
|
-
XTRACEOPTIONS_SIGNATURE_HEADER_NAME =
|
16
|
-
INTL_SWO_X_OPTIONS_KEY =
|
17
|
-
INTL_SWO_SIGNATURE_KEY =
|
15
|
+
TRACESTATE_HEADER_NAME = 'tracestate'
|
16
|
+
XTRACEOPTIONS_HEADER_NAME = 'x-trace-options'
|
17
|
+
XTRACEOPTIONS_SIGNATURE_HEADER_NAME = 'x-trace-options-signature'
|
18
|
+
INTL_SWO_X_OPTIONS_KEY = 'sw_xtraceoptions'
|
19
|
+
INTL_SWO_SIGNATURE_KEY = 'sw_signature'
|
18
20
|
|
19
21
|
private_constant \
|
20
|
-
:TRACESTATE_HEADER_NAME, :XTRACEOPTIONS_HEADER_NAME,
|
22
|
+
:TRACESTATE_HEADER_NAME, :XTRACEOPTIONS_HEADER_NAME,
|
21
23
|
:XTRACEOPTIONS_SIGNATURE_HEADER_NAME, :INTL_SWO_X_OPTIONS_KEY, :INTL_SWO_SIGNATURE_KEY
|
22
24
|
|
23
25
|
# Extract trace context from the supplied carrier.
|
@@ -31,11 +33,11 @@ module SolarWindsAPM
|
|
31
33
|
#
|
32
34
|
# @return [Context] context updated with extracted baggage, or the original context
|
33
35
|
# if extraction fails
|
34
|
-
def extract(carrier, context: ::OpenTelemetry::Context.current,
|
35
|
-
|
36
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] extract context: #{context.inspect}"}
|
36
|
+
def extract(carrier, context: ::OpenTelemetry::Context.current,
|
37
|
+
getter: ::OpenTelemetry::Context::Propagation.text_map_getter)
|
38
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] extract context: #{context.inspect}" }
|
37
39
|
|
38
|
-
context =
|
40
|
+
context = ::OpenTelemetry::Context.new({}) if context.nil?
|
39
41
|
context = inject_extracted_header(carrier, context, getter, XTRACEOPTIONS_HEADER_NAME, INTL_SWO_X_OPTIONS_KEY)
|
40
42
|
inject_extracted_header(carrier, context, getter, XTRACEOPTIONS_SIGNATURE_HEADER_NAME, INTL_SWO_SIGNATURE_KEY)
|
41
43
|
end
|
@@ -47,31 +49,37 @@ module SolarWindsAPM
|
|
47
49
|
# @param [optional Setter] setter If the optional setter is provided, it
|
48
50
|
# will be used to write context into the carrier, otherwise the default
|
49
51
|
# text map setter will be used.
|
50
|
-
def inject(carrier, context: ::OpenTelemetry::Context.current,
|
52
|
+
def inject(carrier, context: ::OpenTelemetry::Context.current,
|
53
|
+
setter: ::OpenTelemetry::Context::Propagation.text_map_setter)
|
54
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] inject context: #{context.inspect}" }
|
51
55
|
|
52
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] inject context: #{context.inspect}"}
|
53
|
-
|
54
56
|
span_context = ::OpenTelemetry::Trace.current_span(context)&.context
|
55
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] span_context #{span_context.inspect}"}
|
57
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] span_context #{span_context.inspect}" }
|
56
58
|
return unless span_context&.valid?
|
57
59
|
|
58
|
-
trace_flag = span_context.trace_flags.sampled
|
60
|
+
trace_flag = span_context.trace_flags.sampled? ? 1 : 0
|
59
61
|
sw_value = "#{span_context.hex_span_id}-0#{trace_flag}"
|
60
|
-
trace_state_header = carrier[TRACESTATE_HEADER_NAME].nil
|
61
|
-
SolarWindsAPM.logger.debug
|
62
|
+
trace_state_header = carrier[TRACESTATE_HEADER_NAME].nil? ? nil : carrier[TRACESTATE_HEADER_NAME]
|
63
|
+
SolarWindsAPM.logger.debug do
|
64
|
+
"[#{self.class}/#{__method__}] sw_value: #{sw_value}; trace_state_header: #{trace_state_header}"
|
65
|
+
end
|
62
66
|
|
63
67
|
# prepare carrier with carrier's or new tracestate
|
64
68
|
if trace_state_header.nil?
|
65
69
|
# only create new trace state if valid span_id
|
66
70
|
unless span_context.span_id == ::OpenTelemetry::Trace::INVALID_SPAN_ID
|
67
|
-
trace_state = ::OpenTelemetry::Trace::Tracestate.create({SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY => sw_value})
|
68
|
-
SolarWindsAPM.logger.debug
|
71
|
+
trace_state = ::OpenTelemetry::Trace::Tracestate.create({ SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY => sw_value })
|
72
|
+
SolarWindsAPM.logger.debug do
|
73
|
+
"[#{self.class}/#{__method__}] creating new trace state: #{trace_state.inspect}"
|
74
|
+
end
|
69
75
|
setter.set(carrier, TRACESTATE_HEADER_NAME, Utils.trace_state_header(trace_state))
|
70
76
|
end
|
71
77
|
else
|
72
78
|
trace_state_from_string = ::OpenTelemetry::Trace::Tracestate.from_string(trace_state_header)
|
73
79
|
trace_state = trace_state_from_string.set_value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY, sw_value)
|
74
|
-
SolarWindsAPM.logger.debug
|
80
|
+
SolarWindsAPM.logger.debug do
|
81
|
+
"[#{self.class}/#{__method__}] updating/adding trace state for injection #{trace_state.inspect}"
|
82
|
+
end
|
75
83
|
setter.set(carrier, TRACESTATE_HEADER_NAME, Utils.trace_state_header(trace_state))
|
76
84
|
end
|
77
85
|
end
|
@@ -85,11 +93,11 @@ module SolarWindsAPM
|
|
85
93
|
end
|
86
94
|
|
87
95
|
private
|
88
|
-
|
96
|
+
|
89
97
|
def inject_extracted_header(carrier, context, getter, header, inject_key)
|
90
98
|
extracted_header = getter.get(carrier, header)
|
91
99
|
context = context.set_value(inject_key, extracted_header) if extracted_header
|
92
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] #{header}: #{inject_key} = #{extracted_header}"}
|
100
|
+
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] #{header}: #{inject_key} = #{extracted_header}" }
|
93
101
|
context
|
94
102
|
end
|
95
103
|
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
|
@@ -10,13 +12,13 @@ module SolarWindsAPM
|
|
10
12
|
# ResponsePropagator
|
11
13
|
# response propagator error will be rescued by OpenTelemetry::Instrumentation::Rack::Middlewares::EventHandler
|
12
14
|
class TextMapPropagator
|
13
|
-
HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS =
|
14
|
-
XTRACE_HEADER_NAME =
|
15
|
-
XTRACEOPTIONS_RESPONSE_HEADER_NAME =
|
16
|
-
INTL_SWO_EQUALS =
|
15
|
+
HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS = 'Access-Control-Expose-Headers'
|
16
|
+
XTRACE_HEADER_NAME = 'x-trace'
|
17
|
+
XTRACEOPTIONS_RESPONSE_HEADER_NAME = 'x-trace-options-response'
|
18
|
+
INTL_SWO_EQUALS = '='
|
17
19
|
|
18
20
|
private_constant \
|
19
|
-
:HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, :XTRACE_HEADER_NAME,
|
21
|
+
:HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, :XTRACE_HEADER_NAME,
|
20
22
|
:XTRACEOPTIONS_RESPONSE_HEADER_NAME
|
21
23
|
|
22
24
|
def extract(carrier, context: ::OpenTelemetry::Context.current, getter: ::OpenTelemetry::Context::Propagation.text_map_getter) # rubocop:disable Lint/UnusedMethodArgument
|
@@ -30,22 +32,29 @@ module SolarWindsAPM
|
|
30
32
|
# @param [optional Setter] setter If the optional setter is provided, it
|
31
33
|
# will be used to write context into the carrier, otherwise the default
|
32
34
|
# text map setter will be used.
|
33
|
-
def inject(carrier, context: ::OpenTelemetry::Context.current,
|
34
|
-
|
35
|
+
def inject(carrier, context: ::OpenTelemetry::Context.current,
|
36
|
+
setter: ::OpenTelemetry::Context::Propagation.text_map_setter)
|
35
37
|
span_context = ::OpenTelemetry::Trace.current_span(context).context
|
36
|
-
SolarWindsAPM.logger.debug
|
38
|
+
SolarWindsAPM.logger.debug do
|
39
|
+
"[#{self.class}/#{__method__}] context: #{context.inspect}; span_context: #{span_context.inspect}"
|
40
|
+
end
|
37
41
|
return unless span_context&.valid?
|
38
|
-
|
42
|
+
|
39
43
|
x_trace = Utils.traceparent_from_context(span_context)
|
40
44
|
exposed_headers = [XTRACE_HEADER_NAME]
|
41
45
|
xtraceoptions_response = recover_response_from_tracestate(span_context.tracestate)
|
42
46
|
|
43
|
-
SolarWindsAPM.logger.debug
|
47
|
+
SolarWindsAPM.logger.debug do
|
48
|
+
"[#{self.class}/#{__method__}] x-trace: #{x_trace}; exposed headers: #{exposed_headers.inspect}; x-trace-options-response: #{xtraceoptions_response}"
|
49
|
+
end
|
44
50
|
exposed_headers.append(XTRACEOPTIONS_RESPONSE_HEADER_NAME) unless xtraceoptions_response.empty?
|
45
51
|
|
46
52
|
setter.set(carrier, XTRACE_HEADER_NAME, x_trace)
|
47
|
-
|
48
|
-
|
53
|
+
unless xtraceoptions_response.empty?
|
54
|
+
setter.set(carrier, XTRACEOPTIONS_RESPONSE_HEADER_NAME,
|
55
|
+
xtraceoptions_response)
|
56
|
+
end
|
57
|
+
setter.set(carrier, HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, exposed_headers.join(','))
|
49
58
|
end
|
50
59
|
|
51
60
|
# Returns the predefined propagation fields. If your carrier is reused, you
|
@@ -61,10 +70,14 @@ module SolarWindsAPM
|
|
61
70
|
# sw_xtraceoptions_response_key -> xtrace_options_response
|
62
71
|
def recover_response_from_tracestate(tracestate)
|
63
72
|
sanitized = tracestate.value(XTraceOptions.sw_xtraceoptions_response_key)
|
64
|
-
sanitized =
|
65
|
-
sanitized = sanitized.gsub(SolarWindsAPM::Constants::INTL_SWO_EQUALS_W3C_SANITIZED,
|
66
|
-
|
67
|
-
|
73
|
+
sanitized = '' if sanitized.nil?
|
74
|
+
sanitized = sanitized.gsub(SolarWindsAPM::Constants::INTL_SWO_EQUALS_W3C_SANITIZED,
|
75
|
+
SolarWindsAPM::Constants::INTL_SWO_EQUALS)
|
76
|
+
sanitized = sanitized.gsub(SolarWindsAPM::Constants::INTL_SWO_COMMA_W3C_SANITIZED,
|
77
|
+
SolarWindsAPM::Constants::INTL_SWO_COMMA)
|
78
|
+
SolarWindsAPM.logger.debug do
|
79
|
+
"[#{self.class}/#{__method__}] recover_response_from_tracestate sanitized: #{sanitized.inspect}"
|
80
|
+
end
|
68
81
|
sanitized
|
69
82
|
end
|
70
83
|
end
|