solarwinds_apm 6.1.2 → 7.0.0.prev2

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -3
  3. data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +1 -30
  4. data/lib/solarwinds_apm/api/current_trace_info.rb +10 -6
  5. data/lib/solarwinds_apm/api/custom_metrics.rb +8 -25
  6. data/lib/solarwinds_apm/api/tracing.rb +12 -27
  7. data/lib/solarwinds_apm/api/transaction_name.rb +6 -10
  8. data/lib/solarwinds_apm/config.rb +7 -1
  9. data/lib/solarwinds_apm/constants.rb +1 -0
  10. data/lib/solarwinds_apm/noop/api.rb +5 -2
  11. data/lib/solarwinds_apm/noop.rb +0 -24
  12. data/lib/solarwinds_apm/opentelemetry/otlp_processor.rb +116 -66
  13. data/lib/solarwinds_apm/opentelemetry/solarwinds_propagator.rb +0 -2
  14. data/lib/solarwinds_apm/opentelemetry/solarwinds_response_propagator.rb +5 -4
  15. data/lib/solarwinds_apm/opentelemetry.rb +5 -7
  16. data/lib/solarwinds_apm/otel_native_config.rb +180 -0
  17. data/lib/solarwinds_apm/patch/README.md +15 -0
  18. data/lib/solarwinds_apm/{noop/metadata.rb → sampling/dice.rb} +19 -17
  19. data/lib/solarwinds_apm/sampling/http_sampler.rb +87 -0
  20. data/lib/solarwinds_apm/sampling/json_sampler.rb +52 -0
  21. data/lib/solarwinds_apm/sampling/metrics.rb +38 -0
  22. data/lib/solarwinds_apm/sampling/oboe_sampler.rb +348 -0
  23. data/lib/solarwinds_apm/sampling/sampler.rb +197 -0
  24. data/lib/solarwinds_apm/sampling/sampling_constants.rb +127 -0
  25. data/lib/solarwinds_apm/sampling/sampling_patch.rb +49 -0
  26. data/lib/solarwinds_apm/sampling/setting_example.txt +1 -0
  27. data/lib/solarwinds_apm/{noop/context.rb → sampling/settings.rb} +14 -25
  28. data/lib/solarwinds_apm/sampling/token_bucket.rb +126 -0
  29. data/lib/solarwinds_apm/sampling/trace_options.rb +100 -0
  30. data/lib/solarwinds_apm/{patch.rb → sampling.rb} +20 -4
  31. data/lib/solarwinds_apm/support/logger_formatter.rb +1 -1
  32. data/lib/solarwinds_apm/support/logging_log_event.rb +1 -1
  33. data/lib/solarwinds_apm/support/lumberjack_formatter.rb +1 -1
  34. data/lib/solarwinds_apm/support/otlp_endpoint.rb +99 -0
  35. data/lib/solarwinds_apm/support/resource_detector.rb +192 -0
  36. data/lib/solarwinds_apm/support/service_key_checker.rb +12 -6
  37. data/lib/solarwinds_apm/support/transaction_settings.rb +6 -0
  38. data/lib/solarwinds_apm/support/txn_name_manager.rb +54 -9
  39. data/lib/solarwinds_apm/support/utils.rb +9 -0
  40. data/lib/solarwinds_apm/support.rb +2 -4
  41. data/lib/solarwinds_apm/version.rb +4 -4
  42. data/lib/solarwinds_apm.rb +27 -73
  43. metadata +107 -40
  44. data/ext/oboe_metal/extconf.rb +0 -168
  45. data/ext/oboe_metal/lib/liboboe-1.0-aarch64.so.sha256 +0 -1
  46. data/ext/oboe_metal/lib/liboboe-1.0-alpine-aarch64.so.sha256 +0 -1
  47. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.sha256 +0 -1
  48. data/ext/oboe_metal/lib/liboboe-1.0-lambda-aarch64.so.sha256 +0 -1
  49. data/ext/oboe_metal/lib/liboboe-1.0-lambda-x86_64.so.sha256 +0 -1
  50. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.sha256 +0 -1
  51. data/ext/oboe_metal/src/VERSION +0 -1
  52. data/ext/oboe_metal/src/bson/bson.h +0 -220
  53. data/ext/oboe_metal/src/bson/platform_hacks.h +0 -91
  54. data/ext/oboe_metal/src/init_solarwinds_apm.cc +0 -18
  55. data/ext/oboe_metal/src/oboe.h +0 -930
  56. data/ext/oboe_metal/src/oboe_api.cpp +0 -793
  57. data/ext/oboe_metal/src/oboe_api.h +0 -621
  58. data/ext/oboe_metal/src/oboe_debug.h +0 -17
  59. data/ext/oboe_metal/src/oboe_swig_wrap.cc +0 -11045
  60. data/lib/oboe_metal.rb +0 -187
  61. data/lib/solarwinds_apm/cert/star.appoptics.com.issuer.crt +0 -24
  62. data/lib/solarwinds_apm/noop/span.rb +0 -25
  63. data/lib/solarwinds_apm/oboe_init_options.rb +0 -222
  64. data/lib/solarwinds_apm/opentelemetry/solarwinds_exporter.rb +0 -239
  65. data/lib/solarwinds_apm/opentelemetry/solarwinds_processor.rb +0 -174
  66. data/lib/solarwinds_apm/opentelemetry/solarwinds_sampler.rb +0 -333
  67. data/lib/solarwinds_apm/otel_config.rb +0 -174
  68. data/lib/solarwinds_apm/otel_lambda_config.rb +0 -56
  69. data/lib/solarwinds_apm/patch/dummy_patch.rb +0 -12
  70. data/lib/solarwinds_apm/support/oboe_tracing_mode.rb +0 -33
  71. data/lib/solarwinds_apm/support/support_report.rb +0 -99
  72. data/lib/solarwinds_apm/support/transaction_cache.rb +0 -57
  73. data/lib/solarwinds_apm/support/x_trace_options.rb +0 -138
@@ -1,239 +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
- # SolarWindsExporter
12
- class SolarWindsExporter
13
- SUCCESS = ::OpenTelemetry::SDK::Trace::Export::SUCCESS # ::OpenTelemetry #=> the OpenTelemetry at top level (to ignore SolarWindsAPM)
14
- FAILURE = ::OpenTelemetry::SDK::Trace::Export::FAILURE
15
-
16
- private_constant(:SUCCESS, :FAILURE)
17
-
18
- def initialize(txn_manager: nil)
19
- @shutdown = false
20
- @txn_manager = txn_manager
21
- @reporter = SolarWindsAPM::Reporter
22
- @context = SolarWindsAPM::Context
23
- @metadata = SolarWindsAPM::Metadata
24
- @version_cache = {}
25
- end
26
-
27
- def export(span_data, timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
28
- return FAILURE if @shutdown
29
-
30
- status = SUCCESS
31
- span_data.each do |data|
32
- status = log_span_data(data)
33
- end
34
-
35
- status
36
- end
37
-
38
- def force_flush(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
39
- SUCCESS
40
- end
41
-
42
- def shutdown(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
43
- @shutdown = true
44
- SUCCESS
45
- end
46
-
47
- private
48
-
49
- def log_span_data(span_data)
50
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] span_data: #{span_data.inspect}\n" }
51
-
52
- md = build_meta_data(span_data)
53
- event = nil
54
- if span_data.parent_span_id == ::OpenTelemetry::Trace::INVALID_SPAN_ID
55
- event = @context.createEntry(md, (span_data.start_timestamp.to_i / 1000).to_i)
56
- add_info_transaction_name(span_data, event)
57
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] Start a new trace." }
58
- else
59
- parent_md = build_meta_data(span_data, parent: true)
60
- event = @context.createEntry(md, (span_data.start_timestamp.to_i / 1000).to_i, parent_md)
61
- SolarWindsAPM.logger.debug do
62
- "[#{self.class}/#{__method__}] Continue trace from parent metadata: #{parent_md.toString}."
63
- end
64
- end
65
-
66
- layer_name = "#{span_data.kind}:#{span_data.name}"
67
- event.addInfo('Layer', layer_name)
68
- event.addInfo('sw.span_kind', span_data.kind.to_s)
69
- event.addInfo('Language', 'Ruby')
70
-
71
- add_instrumentation_scope(event, span_data)
72
- add_instrumented_framework(event, span_data)
73
- add_span_data_attributes(event, span_data.attributes) if span_data.attributes
74
-
75
- event.addInfo(SolarWindsAPM::Constants::INTL_SWO_OTEL_STATUS, span_data.status.ok? ? 'OK' : 'ERROR')
76
- unless span_data.status.description.empty?
77
- event.addInfo(SolarWindsAPM::Constants::INTL_SWO_OTEL_STATUS_DESCRIPTION,
78
- span_data.status.description)
79
- end
80
-
81
- @reporter.send_report(event, with_system_timestamp: false)
82
-
83
- # info / exception event
84
- span_data.events&.each do |span_data_event|
85
- span_data_event.name == 'exception' ? report_exception_event(span_data_event) : report_info_event(span_data_event)
86
- end
87
-
88
- event = @context.createExit((span_data.end_timestamp.to_i / 1000).to_i)
89
- event.addInfo('Layer', layer_name)
90
- @reporter.send_report(event, with_system_timestamp: false)
91
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] Exit a trace: #{event.metadataString}" }
92
- SUCCESS
93
- rescue StandardError => e
94
- SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] exporter error: \n #{e.message} #{e.backtrace}\n" }
95
- FAILURE
96
- end
97
-
98
- ##
99
- # extract the span_data.attributes (OpenTelemetry::SDK::Trace::SpanData.attributes)
100
- def add_span_data_attributes(event, span_attributes)
101
- target = 'http.target'
102
- attributes = span_attributes.dup
103
- attributes[target] = attributes[target].split('?').first if attributes[target] && SolarWindsAPM::Config[:log_args] == false
104
- attributes.each { |k, v| event.addInfo(k, v) }
105
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] span_data attributes added: #{attributes.inspect}" }
106
- end
107
-
108
- ##
109
- # get instrumentation scope data: scope name and version.
110
- # the version if the opentelemetry-instrumentation-* gem version
111
- def add_instrumentation_scope(event, span_data)
112
- scope_name = ''
113
- scope_version = ''
114
- if span_data.instrumentation_scope
115
- scope_name = span_data.instrumentation_scope.name if span_data.instrumentation_scope.name
116
- scope_version = span_data.instrumentation_scope.version if span_data.instrumentation_scope.version
117
- end
118
- event.addInfo(SolarWindsAPM::Constants::INTL_SWO_OTEL_SCOPE_NAME, scope_name)
119
- event.addInfo(SolarWindsAPM::Constants::INTL_SWO_OTEL_SCOPE_VERSION, scope_version)
120
- end
121
-
122
- ##
123
- # add the gem library version to event
124
- # p.s. gem library version is not same as the opentelemetry-instrumentation-* gem version
125
- def add_instrumented_framework(event, span_data)
126
- scope_name = span_data.instrumentation_scope.name
127
- scope_name = scope_name.downcase if scope_name
128
- return unless scope_name&.include? 'opentelemetry::instrumentation'
129
-
130
- framework = scope_name.split('::')[2..]&.join('::')
131
- return if framework.nil? || framework.empty?
132
-
133
- framework = normalize_framework_name(framework)
134
- framework_version = check_framework_version(framework)
135
- SolarWindsAPM.logger.debug do
136
- "[#{self.class}/#{__method__}] #{span_data.instrumentation_scope.name} with #{framework} and version #{framework_version}"
137
- end
138
- event.addInfo("Ruby.#{framework}.Version", framework_version) unless framework_version.nil?
139
- end
140
-
141
- ##
142
- # helper function that extract gem library version for func add_instrumented_framework
143
- def check_framework_version(framework)
144
- framework_version = nil
145
- if @version_cache.key?(framework)
146
-
147
- framework_version = @version_cache[framework]
148
- else
149
-
150
- begin
151
- require framework
152
- framework_version = Gem.loaded_specs[version_framework_name(framework)].version.to_s
153
- rescue LoadError => e
154
- SolarWindsAPM.logger.debug do
155
- "[#{self.class}/#{__method__}] couldn't load #{framework} with error #{e.message}; skip"
156
- end
157
- rescue StandardError => e
158
- SolarWindsAPM.logger.debug do
159
- "[#{self.class}/#{__method__}] couldn't find #{framework} with error #{e.message}; skip"
160
- end
161
- ensure
162
- @version_cache[framework] = framework_version
163
- end
164
- end
165
- SolarWindsAPM.logger.debug do
166
- "[#{self.class}/#{__method__}] current framework version cached: #{@version_cache.inspect}"
167
- end
168
- framework_version
169
- end
170
-
171
- ##
172
- # helper function that convert opentelemetry instrumentation name to gem library understandable
173
- def normalize_framework_name(framework)
174
- case framework
175
- when 'net::http'
176
- 'net/http'
177
- else
178
- framework
179
- end
180
- end
181
-
182
- ##
183
- # helper function that convert opentelemetry instrumentation name to gem library understandable
184
- def version_framework_name(framework)
185
- case framework
186
- when 'net/http'
187
- 'net-http'
188
- else
189
- framework
190
- end
191
- end
192
-
193
- ##
194
- # Add transaction name from cache to root span then removes from cache
195
- def add_info_transaction_name(span_data, event)
196
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] transaction manager: #{@txn_manager.inspect}." }
197
- trace_span_id = "#{span_data.hex_trace_id}-#{span_data.hex_span_id}"
198
- txname = @txn_manager.get(trace_span_id) || ''
199
- event.addInfo('TransactionName', txname)
200
- @txn_manager.del(trace_span_id)
201
- end
202
-
203
- ##
204
- # report exception event
205
- def report_exception_event(span_event)
206
- event = @context.createEvent((span_event.timestamp.to_i / 1000).to_i)
207
- event.addInfo('Label', 'error')
208
- event.addInfo('Spec', 'error')
209
-
210
- unless span_event.attributes.nil?
211
- attributes = span_event.attributes.dup
212
- attributes.delete('exception.type') if event.addInfo('ErrorClass', attributes['exception.type'])
213
- attributes.delete('exception.message') if event.addInfo('ErrorMsg', attributes['exception.message'])
214
- attributes.delete('exception.stacktrace') if event.addInfo('Backtrace', attributes['exception.stacktrace'])
215
- attributes.each { |key, value| event.addInfo(key, value) }
216
- end
217
-
218
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] exception event #{event.metadataString}" }
219
- @reporter.send_report(event, with_system_timestamp: false)
220
- end
221
-
222
- ##
223
- # report non-exception/info event
224
- def report_info_event(span_event)
225
- event = @context.createEvent((span_event.timestamp.to_i / 1000).to_i)
226
- event.addInfo('Label', 'info')
227
- span_event.attributes&.each { |key, value| event.addInfo(key, value) }
228
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] info event #{event.metadataString}" }
229
- @reporter.send_report(event, with_system_timestamp: false)
230
- end
231
-
232
- def build_meta_data(span_data, parent: false)
233
- flag = span_data.trace_flags.sampled? ? 1 : 0
234
- xtr = parent == false ? "00-#{span_data.hex_trace_id}-#{span_data.hex_span_id}-0#{flag}" : "00-#{span_data.hex_trace_id}-#{span_data.hex_parent_span_id}-0#{flag}"
235
- @metadata.fromString(xtr)
236
- end
237
- end
238
- end
239
- 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
- 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