solarwinds_apm 6.0.0.prev6 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/ext/oboe_metal/extconf.rb +43 -42
  3. data/ext/oboe_metal/lib/liboboe-1.0-aarch64.so.sha256 +1 -1
  4. data/ext/oboe_metal/lib/liboboe-1.0-alpine-aarch64.so.sha256 +1 -1
  5. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.sha256 +1 -1
  6. data/ext/oboe_metal/lib/liboboe-1.0-lambda-aarch64.so.sha256 +1 -0
  7. data/ext/oboe_metal/lib/liboboe-1.0-lambda-x86_64.so.sha256 +1 -0
  8. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.sha256 +1 -1
  9. data/ext/oboe_metal/src/VERSION +1 -1
  10. data/ext/oboe_metal/src/oboe.h +3 -0
  11. data/ext/oboe_metal/src/oboe_api.cpp +1 -1
  12. data/lib/oboe_metal.rb +46 -84
  13. data/lib/rails/generators/solarwinds_apm/install_generator.rb +21 -19
  14. data/lib/solarwinds_apm/api/current_trace_info.rb +16 -9
  15. data/lib/solarwinds_apm/api/custom_metrics.rb +6 -4
  16. data/lib/solarwinds_apm/api/opentelemetry.rb +10 -6
  17. data/lib/solarwinds_apm/api/tracing.rb +7 -5
  18. data/lib/solarwinds_apm/api/transaction_name.rb +21 -11
  19. data/lib/solarwinds_apm/api.rb +8 -6
  20. data/lib/solarwinds_apm/config.rb +72 -47
  21. data/lib/solarwinds_apm/constants.rb +26 -26
  22. data/lib/solarwinds_apm/logger.rb +2 -0
  23. data/lib/solarwinds_apm/noop/README.md +1 -1
  24. data/lib/solarwinds_apm/noop/api.rb +85 -0
  25. data/lib/solarwinds_apm/noop/context.rb +15 -2
  26. data/lib/solarwinds_apm/noop/metadata.rb +7 -2
  27. data/lib/solarwinds_apm/{base.rb → noop/span.rb} +16 -15
  28. data/lib/solarwinds_apm/noop.rb +33 -0
  29. data/lib/solarwinds_apm/oboe_init_options.rb +50 -111
  30. data/lib/solarwinds_apm/opentelemetry/otlp_processor.rb +135 -0
  31. data/lib/solarwinds_apm/opentelemetry/solarwinds_exporter.rb +66 -41
  32. data/lib/solarwinds_apm/opentelemetry/solarwinds_processor.rb +50 -52
  33. data/lib/solarwinds_apm/opentelemetry/solarwinds_propagator.rb +30 -22
  34. data/lib/solarwinds_apm/opentelemetry/solarwinds_response_propagator.rb +29 -16
  35. data/lib/solarwinds_apm/opentelemetry/solarwinds_sampler.rb +136 -99
  36. data/lib/solarwinds_apm/opentelemetry.rb +8 -5
  37. data/lib/solarwinds_apm/otel_config.rb +38 -43
  38. data/lib/solarwinds_apm/otel_lambda_config.rb +53 -0
  39. data/lib/solarwinds_apm/patch/dummy_patch.rb +12 -0
  40. data/lib/solarwinds_apm/{thread_local.rb → patch.rb} +6 -22
  41. data/lib/solarwinds_apm/support/logger_formatter.rb +4 -2
  42. data/lib/solarwinds_apm/support/logging_log_event.rb +2 -0
  43. data/lib/solarwinds_apm/support/lumberjack_formatter.rb +2 -0
  44. data/lib/solarwinds_apm/support/oboe_tracing_mode.rb +22 -22
  45. data/lib/solarwinds_apm/support/service_key_checker.rb +106 -0
  46. data/lib/solarwinds_apm/{support_report.rb → support/support_report.rb} +15 -10
  47. data/lib/solarwinds_apm/support/swomarginalia/comment.rb +18 -17
  48. data/lib/solarwinds_apm/support/swomarginalia/load_swomarginalia.rb +13 -12
  49. data/lib/solarwinds_apm/support/swomarginalia/railtie.rb +4 -2
  50. data/lib/solarwinds_apm/support/swomarginalia/swomarginalia.rb +3 -1
  51. data/lib/solarwinds_apm/support/transaction_cache.rb +6 -4
  52. data/lib/solarwinds_apm/support/transaction_settings.rb +7 -3
  53. data/lib/solarwinds_apm/support/txn_name_manager.rb +8 -3
  54. data/lib/solarwinds_apm/support/utils.rb +12 -9
  55. data/lib/solarwinds_apm/support/x_trace_options.rb +23 -17
  56. data/lib/solarwinds_apm/support.rb +28 -23
  57. data/lib/solarwinds_apm/version.rb +4 -2
  58. data/lib/solarwinds_apm.rb +82 -52
  59. 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 = "http.method".freeze
12
- HTTP_ROUTE = "http.route".freeze
13
- HTTP_STATUS_CODE = "http.status_code".freeze
14
- HTTP_URL = "http.url".freeze
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(exporter, txn_manager)
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
- SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] processor on_start span: #{span.inspect}, parent_context: #{parent_context.inspect}"}
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.parent_span_id != ::OpenTelemetry::Trace::INVALID_SPAN_ID
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,request_method,has_error)
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
- @txn_manager["#{span.context.hex_trace_id}-#{span.context.hex_span_id}"] = liboboe_txn_name if span.context.trace_flags.sampled?
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 {"[#{self.class}/#{__method__}] can't flush span to exporter; processor on_finish error: #{e.message}"}
103
- ::OpenTelemetry::SDK::Trace::Export::FAILURE
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
- @exporter&.force_flush(timeout: timeout) || ::OpenTelemetry::SDK::Trace::Export::SUCCESS
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
- @exporter&.shutdown(timeout: timeout) || ::OpenTelemetry::SDK::Trace::Export::SUCCESS
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 {"[#{self.class}/#{__method__}] found trans name from txn_manager: #{trans_name} by #{trace_span_id}"}
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.has_key?('SW_APM_TRANSACTION_NAME') && ENV['SW_APM_TRANSACTION_NAME'] != ''
159
- trans_name = ENV['SW_APM_TRANSACTION_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 = "tracestate".freeze
14
- XTRACEOPTIONS_HEADER_NAME = "x-trace-options".freeze
15
- XTRACEOPTIONS_SIGNATURE_HEADER_NAME = "x-trace-options-signature".freeze
16
- INTL_SWO_X_OPTIONS_KEY = "sw_xtraceoptions".freeze
17
- INTL_SWO_SIGNATURE_KEY = "sw_signature".freeze
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, getter: ::OpenTelemetry::Context::Propagation.text_map_getter)
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 = context.nil?? ::OpenTelemetry::Context.new({}) : 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, setter: ::OpenTelemetry::Context::Propagation.text_map_setter)
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?? 1 : 0
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?? nil : carrier[TRACESTATE_HEADER_NAME]
61
- SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] sw_value: #{sw_value}; trace_state_header: #{trace_state_header}"}
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 {"[#{self.class}/#{__method__}] creating new trace state: #{trace_state.inspect}"}
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 {"[#{self.class}/#{__method__}] updating/adding trace state for injection #{trace_state.inspect}"}
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 = "Access-Control-Expose-Headers".freeze
14
- XTRACE_HEADER_NAME = "x-trace".freeze
15
- XTRACEOPTIONS_RESPONSE_HEADER_NAME = "x-trace-options-response".freeze
16
- INTL_SWO_EQUALS = "=".freeze
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, setter: ::OpenTelemetry::Context::Propagation.text_map_setter)
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 {"[#{self.class}/#{__method__}] context: #{context.inspect}; span_context: #{span_context.inspect}"}
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 {"[#{self.class}/#{__method__}] x-trace: #{x_trace}; exposed headers: #{exposed_headers.inspect}; x-trace-options-response: #{xtraceoptions_response}"}
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
- setter.set(carrier, XTRACEOPTIONS_RESPONSE_HEADER_NAME, xtraceoptions_response) unless xtraceoptions_response.empty?
48
- setter.set(carrier, HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, exposed_headers.join(","))
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 = "" if sanitized.nil?
65
- sanitized = sanitized.gsub(SolarWindsAPM::Constants::INTL_SWO_EQUALS_W3C_SANITIZED, SolarWindsAPM::Constants::INTL_SWO_EQUALS)
66
- sanitized = sanitized.gsub(SolarWindsAPM::Constants::INTL_SWO_COMMA_W3C_SANITIZED, SolarWindsAPM::Constants::INTL_SWO_COMMA)
67
- SolarWindsAPM.logger.debug {"[#{self.class}/#{__method__}] recover_response_from_tracestate sanitized: #{sanitized.inspect}"}
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