solarwinds_apm 6.0.0.preV1 → 6.0.0.preV3
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/LICENSE +28 -54
- data/ext/oboe_metal/extconf.rb +23 -23
- 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 -2
- data/ext/oboe_metal/src/init_solarwinds_apm.cc +0 -6
- data/ext/oboe_metal/src/oboe.h +0 -12
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +5 -5
- data/lib/oboe_metal.rb +3 -3
- data/lib/rails/generators/solarwinds_apm/install_generator.rb +0 -3
- data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +8 -25
- data/lib/solarwinds_apm/api/current_trace_info.rb +1 -2
- data/lib/solarwinds_apm/api/opentelemetry.rb +39 -0
- data/lib/solarwinds_apm/api/transaction_name.rb +18 -17
- data/lib/solarwinds_apm/api.rb +2 -0
- data/lib/solarwinds_apm/config.rb +21 -63
- data/lib/solarwinds_apm/constants.rb +2 -4
- data/lib/solarwinds_apm/noop/context.rb +1 -1
- data/lib/solarwinds_apm/oboe_init_options.rb +11 -16
- data/lib/solarwinds_apm/opentelemetry/solarwinds_exporter.rb +92 -87
- data/lib/solarwinds_apm/opentelemetry/solarwinds_processor.rb +27 -23
- data/lib/solarwinds_apm/opentelemetry/solarwinds_propagator.rb +28 -28
- data/lib/solarwinds_apm/opentelemetry/solarwinds_response_propagator.rb +9 -14
- data/lib/solarwinds_apm/opentelemetry/solarwinds_sampler.rb +132 -175
- data/lib/solarwinds_apm/otel_config.rb +55 -36
- data/lib/solarwinds_apm/support/lumberjack_formatter.rb +17 -2
- data/lib/solarwinds_apm/support/swomarginalia/comment.rb +2 -2
- data/lib/solarwinds_apm/support/swomarginalia/swomarginalia.rb +6 -5
- data/lib/solarwinds_apm/support/transaction_cache.rb +27 -2
- data/lib/solarwinds_apm/support/transaction_settings.rb +10 -10
- data/lib/solarwinds_apm/support/txn_name_manager.rb +34 -17
- data/lib/solarwinds_apm/support/utils.rb +24 -0
- data/lib/solarwinds_apm/support.rb +4 -2
- data/lib/solarwinds_apm/version.rb +1 -1
- data/lib/solarwinds_apm.rb +3 -4
- metadata +18 -33
- data/lib/oboe.rb +0 -7
- data/lib/solarwinds_apm/noop/profiling.rb +0 -17
- data/lib/solarwinds_apm/support/transformer.rb +0 -56
@@ -32,11 +32,9 @@ module SolarWindsAPM
|
|
32
32
|
return if parent_span && parent_span.context != ::OpenTelemetry::Trace::SpanContext::INVALID && parent_span.context.remote? == false
|
33
33
|
|
34
34
|
trace_flags = span.context.trace_flags.sampled? ? '01' : '00'
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] current baggage values: #{::OpenTelemetry::Baggage.values}"}
|
35
|
+
@txn_manager.set_root_context_h(span.context.hex_trace_id,"#{span.context.hex_span_id}-#{trace_flags}")
|
36
|
+
rescue StandardError => e
|
37
|
+
SolarWindsAPM.logger.info {"[#{self.class}/#{__method__}] processor on_start error: #{e.message}"}
|
40
38
|
end
|
41
39
|
|
42
40
|
# Called when a {Span} is ended, if the {Span#recording?}
|
@@ -47,7 +45,9 @@ module SolarWindsAPM
|
|
47
45
|
# Only calculate inbound metrics for service root spans
|
48
46
|
#
|
49
47
|
# @param [Span] span the {Span} that just ended.
|
50
|
-
def on_finish(span)
|
48
|
+
def on_finish(span)
|
49
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] processor on_finish span: #{span.inspect}"}
|
50
|
+
|
51
51
|
if span.parent_span_id != ::OpenTelemetry::Trace::INVALID_SPAN_ID
|
52
52
|
@exporter&.export([span.to_span_data]) if span.context.trace_flags.sampled?
|
53
53
|
return
|
@@ -57,40 +57,44 @@ module SolarWindsAPM
|
|
57
57
|
domain = nil
|
58
58
|
has_error = error?(span)
|
59
59
|
trans_name = calculate_transaction_names(span)
|
60
|
-
url_tran = span.attributes[HTTP_URL]
|
61
|
-
|
62
|
-
liboboe_txn_name = nil
|
63
60
|
if span_http?(span)
|
64
|
-
status_code
|
61
|
+
status_code = get_http_status_code(span)
|
65
62
|
request_method = span.attributes[HTTP_METHOD]
|
63
|
+
url_tran = span.attributes[HTTP_URL]
|
66
64
|
|
67
|
-
SolarWindsAPM.logger.debug
|
65
|
+
SolarWindsAPM.logger.debug do
|
66
|
+
"[#{self.class}/#{__method__}] createHttpSpan with\n
|
68
67
|
trans_name: #{trans_name}\n
|
69
68
|
url_tran: #{url_tran}\n
|
70
69
|
domain: #{domain}\n
|
71
70
|
span_time: #{span_time}\n
|
72
71
|
status_code: #{status_code}\n
|
73
72
|
request_method: #{request_method}\n
|
74
|
-
has_error: #{has_error}"
|
73
|
+
has_error: #{has_error}"
|
74
|
+
end
|
75
75
|
|
76
|
-
liboboe_txn_name = SolarWindsAPM::Span.createHttpSpan(trans_name,url_tran,domain,span_time,status_code,
|
77
|
-
request_method,has_error)
|
76
|
+
liboboe_txn_name = SolarWindsAPM::Span.createHttpSpan(trans_name,url_tran,domain,span_time,status_code,request_method,has_error)
|
78
77
|
|
79
78
|
else
|
80
79
|
|
81
|
-
SolarWindsAPM.logger.debug
|
80
|
+
SolarWindsAPM.logger.debug do
|
81
|
+
"[#{self.class}/#{__method__}] createSpan with \n
|
82
82
|
trans_name: #{trans_name}\n
|
83
83
|
domain: #{domain}\n
|
84
84
|
span_time: #{span_time}\n
|
85
|
-
has_error: #{has_error}"
|
85
|
+
has_error: #{has_error}"
|
86
|
+
end
|
86
87
|
|
87
88
|
liboboe_txn_name = SolarWindsAPM::Span.createSpan(trans_name, domain, span_time, has_error)
|
88
89
|
end
|
89
90
|
|
90
91
|
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] liboboe_txn_name: #{liboboe_txn_name}"}
|
91
92
|
@txn_manager["#{span.context.hex_trace_id}-#{span.context.hex_span_id}"] = liboboe_txn_name if span.context.trace_flags.sampled?
|
92
|
-
|
93
|
+
@txn_manager.delete_root_context_h(span.context.hex_trace_id)
|
93
94
|
@exporter&.export([span.to_span_data]) if span.context.trace_flags.sampled?
|
95
|
+
rescue StandardError => e
|
96
|
+
SolarWindsAPM.logger.info {"[#{self.class}/#{__method__}] can't flush span to exporter; processor on_finish error: #{e.message}"}
|
97
|
+
::OpenTelemetry::SDK::Trace::Export::FAILURE
|
94
98
|
end
|
95
99
|
|
96
100
|
# Export all ended spans to the configured `Exporter` that have not yet
|
@@ -105,7 +109,7 @@ module SolarWindsAPM
|
|
105
109
|
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
106
110
|
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
107
111
|
def force_flush(timeout: nil)
|
108
|
-
@exporter&.force_flush(timeout: timeout) || ::OpenTelemetry::SDK::
|
112
|
+
@exporter&.force_flush(timeout: timeout) || ::OpenTelemetry::SDK::Trace::Export::SUCCESS
|
109
113
|
end
|
110
114
|
|
111
115
|
# Called when {TracerProvider#shutdown} is called.
|
@@ -114,14 +118,13 @@ module SolarWindsAPM
|
|
114
118
|
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
115
119
|
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
116
120
|
def shutdown(timeout: nil)
|
117
|
-
@exporter&.shutdown(timeout: timeout) || ::OpenTelemetry::SDK::
|
121
|
+
@exporter&.shutdown(timeout: timeout) || ::OpenTelemetry::SDK::Trace::Export::SUCCESS
|
118
122
|
end
|
119
123
|
|
120
124
|
private
|
121
125
|
|
122
126
|
# This span from inbound HTTP request if from a SERVER by some http.method
|
123
127
|
def span_http?(span)
|
124
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] span.kind #{span.kind} span.attributes: #{span.attributes[HTTP_METHOD]}"}
|
125
128
|
(span.kind == ::OpenTelemetry::Trace::SpanKind::SERVER && !span.attributes[HTTP_METHOD].nil?)
|
126
129
|
end
|
127
130
|
|
@@ -140,10 +143,11 @@ module SolarWindsAPM
|
|
140
143
|
|
141
144
|
# Get trans_name and url_tran of this span instance.
|
142
145
|
def calculate_transaction_names(span)
|
143
|
-
|
144
146
|
trace_span_id = "#{span.context.hex_trace_id}-#{span.context.hex_span_id}"
|
145
|
-
|
146
|
-
|
147
|
+
trans_name = @txn_manager.get(trace_span_id)
|
148
|
+
if trans_name
|
149
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] found trans name from txn_manager: #{trans_name} by #{trace_span_id}"}
|
150
|
+
@txn_manager.del(trace_span_id)
|
147
151
|
else
|
148
152
|
trans_name = span.attributes[HTTP_ROUTE] || nil
|
149
153
|
trans_name = span.name if span.name && (trans_name.nil? || trans_name.empty?)
|
@@ -2,6 +2,7 @@ module SolarWindsAPM
|
|
2
2
|
module OpenTelemetry
|
3
3
|
module SolarWindsPropagator
|
4
4
|
# TextMapPropagator
|
5
|
+
# propagator error will be rescued by OpenTelemetry::Context::Propagation::TextMapPropagator
|
5
6
|
class TextMapPropagator
|
6
7
|
TRACESTATE_HEADER_NAME = "tracestate".freeze
|
7
8
|
XTRACEOPTIONS_HEADER_NAME = "x-trace-options".freeze
|
@@ -26,19 +27,11 @@ module SolarWindsAPM
|
|
26
27
|
# if extraction fails
|
27
28
|
def extract(carrier, context: ::OpenTelemetry::Context.current, getter: ::OpenTelemetry::Context::Propagation.text_map_getter)
|
28
29
|
|
29
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] context
|
30
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] extract context: #{context.inspect}"}
|
30
31
|
|
31
|
-
context = ::OpenTelemetry::Context.new({})
|
32
|
-
|
33
|
-
|
34
|
-
context = context.set_value(INTL_SWO_X_OPTIONS_KEY, xtraceoptions_header) if xtraceoptions_header
|
35
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] xtraceoptions_header: #{xtraceoptions_header}"}
|
36
|
-
|
37
|
-
signature_header = getter.get(carrier, XTRACEOPTIONS_SIGNATURE_HEADER_NAME)
|
38
|
-
context = context.set_value(INTL_SWO_SIGNATURE_KEY, signature_header) if signature_header
|
39
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] signature_header: #{signature_header}; propagator extract context: #{context.inspect}"}
|
40
|
-
|
41
|
-
context
|
32
|
+
context = context.nil?? ::OpenTelemetry::Context.new({}) : context
|
33
|
+
context = inject_extracted_header(carrier, context, getter, XTRACEOPTIONS_HEADER_NAME, INTL_SWO_X_OPTIONS_KEY)
|
34
|
+
inject_extracted_header(carrier, context, getter, XTRACEOPTIONS_SIGNATURE_HEADER_NAME, INTL_SWO_SIGNATURE_KEY)
|
42
35
|
end
|
43
36
|
|
44
37
|
# Inject trace context into the supplied carrier.
|
@@ -51,32 +44,30 @@ module SolarWindsAPM
|
|
51
44
|
def inject(carrier, context: ::OpenTelemetry::Context.current, setter: ::OpenTelemetry::Context::Propagation.text_map_setter)
|
52
45
|
|
53
46
|
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] inject context: #{context.inspect}"}
|
54
|
-
|
55
|
-
|
56
|
-
span_context
|
57
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] cspan #{cspan.inspect}; span_context #{span_context.inspect}"}
|
47
|
+
|
48
|
+
span_context = ::OpenTelemetry::Trace.current_span(context)&.context
|
49
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] span_context #{span_context.inspect}"}
|
58
50
|
return unless span_context&.valid?
|
59
51
|
|
60
|
-
|
52
|
+
trace_flag = span_context.trace_flags.sampled?? 1 : 0
|
53
|
+
sw_value = "#{span_context.hex_span_id}-0#{trace_flag}"
|
61
54
|
trace_state_header = carrier[TRACESTATE_HEADER_NAME].nil?? nil : carrier[TRACESTATE_HEADER_NAME]
|
62
|
-
|
63
55
|
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] sw_value: #{sw_value}; trace_state_header: #{trace_state_header}"}
|
64
56
|
|
65
|
-
#
|
66
|
-
trace_state = nil
|
57
|
+
# prepare carrier with carrier's or new tracestate
|
67
58
|
if trace_state_header.nil?
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
59
|
+
# only create new trace state if valid span_id
|
60
|
+
unless span_context.span_id == ::OpenTelemetry::Trace::INVALID_SPAN_ID
|
61
|
+
trace_state = ::OpenTelemetry::Trace::Tracestate.create({SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY => sw_value})
|
62
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] creating new trace state: #{trace_state.inspect}"}
|
63
|
+
setter.set(carrier, TRACESTATE_HEADER_NAME, Utils.trace_state_header(trace_state))
|
64
|
+
end
|
73
65
|
else
|
74
66
|
trace_state_from_string = ::OpenTelemetry::Trace::Tracestate.from_string(trace_state_header)
|
75
67
|
trace_state = trace_state_from_string.set_value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY, sw_value)
|
76
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}]
|
68
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] updating/adding trace state for injection #{trace_state.inspect}"}
|
69
|
+
setter.set(carrier, TRACESTATE_HEADER_NAME, Utils.trace_state_header(trace_state))
|
77
70
|
end
|
78
|
-
|
79
|
-
setter.set(carrier, TRACESTATE_HEADER_NAME, Transformer.trace_state_header(trace_state))
|
80
71
|
end
|
81
72
|
|
82
73
|
# Returns the predefined propagation fields. If your carrier is reused, you
|
@@ -86,6 +77,15 @@ module SolarWindsAPM
|
|
86
77
|
def fields
|
87
78
|
TRACESTATE_HEADER_NAME
|
88
79
|
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def inject_extracted_header(carrier, context, getter, header, inject_key)
|
84
|
+
extracted_header = getter.get(carrier, header)
|
85
|
+
context = context.set_value(inject_key, extracted_header) if extracted_header
|
86
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] #{header}: #{inject_key} = #{extracted_header}"}
|
87
|
+
context
|
88
|
+
end
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -2,6 +2,7 @@ module SolarWindsAPM
|
|
2
2
|
module OpenTelemetry
|
3
3
|
module SolarWindsResponsePropagator
|
4
4
|
# ResponsePropagator
|
5
|
+
# response propagator error will be rescued by OpenTelemetry::Instrumentation::Rack::Middlewares::EventHandler
|
5
6
|
class TextMapPropagator
|
6
7
|
HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers".freeze
|
7
8
|
XTRACE_HEADER_NAME = "x-trace".freeze
|
@@ -25,26 +26,20 @@ module SolarWindsAPM
|
|
25
26
|
# text map setter will be used.
|
26
27
|
def inject(carrier, context: ::OpenTelemetry::Context.current, setter: ::OpenTelemetry::Context::Propagation.text_map_setter)
|
27
28
|
|
28
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] response propagator context: #{context.inspect}"}
|
29
29
|
span_context = ::OpenTelemetry::Trace.current_span(context).context
|
30
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}]
|
31
|
-
return unless span_context
|
30
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] context: #{context.inspect}; span_context: #{span_context.inspect}"}
|
31
|
+
return unless span_context&.valid?
|
32
32
|
|
33
|
-
x_trace
|
34
|
-
|
35
|
-
exposed_headers = [XTRACE_HEADER_NAME]
|
36
|
-
|
37
|
-
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] response propagator span_context.tracestate: #{span_context.tracestate.inspect}"}
|
33
|
+
x_trace = Utils.traceparent_from_context(span_context)
|
34
|
+
exposed_headers = [XTRACE_HEADER_NAME]
|
38
35
|
xtraceoptions_response = recover_response_from_tracestate(span_context.tracestate)
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
setter.set(carrier, XTRACEOPTIONS_RESPONSE_HEADER_NAME, xtraceoptions_response)
|
43
|
-
end
|
37
|
+
SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] x-trace: #{x_trace}; exposed headers: #{exposed_headers.inspect}; x-trace-options-response: #{xtraceoptions_response}"}
|
38
|
+
exposed_headers.append(XTRACEOPTIONS_RESPONSE_HEADER_NAME) unless xtraceoptions_response.empty?
|
44
39
|
|
45
|
-
|
40
|
+
setter.set(carrier, XTRACE_HEADER_NAME, x_trace)
|
41
|
+
setter.set(carrier, XTRACEOPTIONS_RESPONSE_HEADER_NAME, xtraceoptions_response) unless xtraceoptions_response.empty?
|
46
42
|
setter.set(carrier, HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, exposed_headers.join(","))
|
47
|
-
|
48
43
|
end
|
49
44
|
|
50
45
|
# Returns the predefined propagation fields. If your carrier is reused, you
|