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.
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