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,333 +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
- # SolarWindsSampler
12
- class SolarWindsSampler
13
- INTERNAL_BUCKET_CAPACITY = 'BucketCapacity'
14
- INTERNAL_BUCKET_RATE = 'BucketRate'
15
- INTERNAL_SAMPLE_RATE = 'SampleRate'
16
- INTERNAL_SAMPLE_SOURCE = 'SampleSource'
17
- INTERNAL_SW_KEYS = 'SWKeys'
18
- LIBOBOE_CONTINUED = -1
19
- SW_TRACESTATE_CAPTURE_KEY = 'sw.w3c.tracestate'
20
- SW_TRACESTATE_ROOT_KEY = 'sw.tracestate_parent_id'
21
- UNSET = -1
22
- SWO_TRACING_ENABLED = 1
23
- SWO_TRACING_DISABLED = 0
24
- SWO_TRACING_UNSET = -1
25
- XTRACEOPTIONS_RESP_AUTH = 'auth'
26
- XTRACEOPTIONS_RESP_IGNORED = 'ignored'
27
- XTRACEOPTIONS_RESP_TRIGGER_IGNORED = 'ignored'
28
- XTRACEOPTIONS_RESP_TRIGGER_NOT_REQUESTED = 'not-requested'
29
- XTRACEOPTIONS_RESP_TRIGGER_TRACE = 'trigger-trace'
30
-
31
- attr_reader :description
32
-
33
- def initialize(config = {})
34
- @config = config
35
- end
36
-
37
- def ==(other)
38
- @decision == other.decision && @description == other.description
39
- end
40
-
41
- # @api private
42
- #
43
- # See {Samplers}.
44
- # trace_id
45
- # parent_context: OpenTelemetry::Context
46
- def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
47
- SolarWindsAPM.logger.debug do
48
- "[#{self.class}/#{__method__}] should_sample? start parameters \n
49
- trace_id: #{trace_id.unpack1('H*')}\n
50
- parent_context: #{parent_context}\n
51
- parent_context.inspect: #{parent_context.inspect}\n
52
- links: #{links}\n
53
- name: #{name}\n
54
- kind: #{kind}\n
55
- attributes: #{attributes}"
56
- end
57
-
58
- SolarWindsAPM::Reporter.send(:report_init) # This only happens if after_fork enabled
59
-
60
- parent_span_context = ::OpenTelemetry::Trace.current_span(parent_context).context
61
- xtraceoptions = ::SolarWindsAPM::XTraceOptions.new(parent_context)
62
- SolarWindsAPM.logger.debug do
63
- "[#{self.class}/#{__method__}] parent_span_context: #{parent_span_context.inspect}\n xtraceoptions: #{xtraceoptions.inspect}"
64
- end
65
-
66
- liboboe_decision = calculate_liboboe_decision(parent_span_context, xtraceoptions, name, kind, attributes)
67
- otel_decision = otel_decision_from_liboboe(liboboe_decision)
68
- new_trace_state = calculate_trace_state(liboboe_decision, parent_span_context, xtraceoptions)
69
- new_attributes = if otel_sampled?(otel_decision)
70
- calculate_attributes(attributes, liboboe_decision,
71
- new_trace_state, parent_span_context, xtraceoptions)
72
- end
73
- sampling_result = ::OpenTelemetry::SDK::Trace::Samplers::Result.new(decision: otel_decision,
74
- attributes: new_attributes,
75
- tracestate: new_trace_state)
76
-
77
- SolarWindsAPM.logger.debug do
78
- "[#{self.class}/#{__method__}] should_sample? end with sampling_result: #{sampling_result.inspect} from otel_decision: #{otel_decision.inspect} and new_attributes: #{new_attributes.inspect}"
79
- end
80
- sampling_result
81
- rescue StandardError => e
82
- SolarWindsAPM.logger.info { "[#{self.class}/#{__method__}] sampler error: #{e.message}" }
83
- ::OpenTelemetry::SDK::Trace::Samplers::Result.new(decision: ::OpenTelemetry::SDK::Trace::Samplers::Decision::DROP,
84
- attributes: attributes,
85
- tracestate: ::OpenTelemetry::Trace::Tracestate::DEFAULT)
86
- end
87
-
88
- protected
89
-
90
- attr_reader :decision
91
-
92
- private
93
-
94
- ##
95
- # use parent_span_context and xtraceoptions object to feed to liboboe function getDecisions that get liboboe_decision
96
- # name, kind and attributes are used for transaction filter caching (to avoid continous calculate_trace_mode calculation)
97
- # return decision Hash
98
- def calculate_liboboe_decision(parent_span_context, xtraceoptions, name, kind, attributes)
99
- tracestring = Utils.traceparent_from_context(parent_span_context) if parent_span_context.valid? && parent_span_context.remote?
100
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] tracestring: #{tracestring}" }
101
-
102
- # otel-ruby contrib use different key to store url info, currently it's using http.target for path
103
- url_path = attributes.nil? ? '' : attributes['http.target']
104
- transaction_naming_key = "#{url_path}-#{name}-#{kind}"
105
- tracing_mode = SolarWindsAPM::TransactionCache.get(transaction_naming_key)
106
- SolarWindsAPM.logger.debug do
107
- "[#{self.class}/#{__method__}] transaction cache: #{transaction_naming_key}; tracing_mode: #{tracing_mode}."
108
- end
109
-
110
- unless tracing_mode
111
- trans_settings = SolarWindsAPM::TransactionSettings.new(url_path: url_path, name: name, kind: kind)
112
- tracing_mode = trans_settings.calculate_trace_mode == 1 ? SWO_TRACING_ENABLED : SWO_TRACING_DISABLED
113
- SolarWindsAPM::TransactionCache.set(transaction_naming_key, tracing_mode)
114
- end
115
-
116
- sw_member_value = parent_span_context.tracestate[SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY]
117
- trigger_trace_mode = SolarWindsAPM::OboeTracingMode.get_oboe_trigger_trace_mode(@config['trigger_trace'])
118
- sample_rate = UNSET
119
- options = xtraceoptions&.options
120
- trigger_trace = xtraceoptions&.intify_trigger_trace || 0
121
- signature = xtraceoptions&.signature
122
- timestamp = xtraceoptions&.timestamp
123
-
124
- SolarWindsAPM.logger.debug do
125
- "[#{self.class}/#{__method__}] get liboboe decision parameters: \n
126
- tracestring: #{tracestring}\n
127
- sw_member_value: #{sw_member_value}\n
128
- tracing_mode: #{tracing_mode}\n
129
- sample_rate: #{sample_rate}\n
130
- trigger_trace: #{trigger_trace}\n
131
- trigger_trace_mode: #{trigger_trace_mode}\n
132
- options: #{options}\n
133
- signature: #{signature}\n
134
- timestamp: #{timestamp}"
135
- end
136
-
137
- args = [tracestring, sw_member_value, tracing_mode, sample_rate,
138
- trigger_trace, trigger_trace_mode, options, signature, timestamp]
139
-
140
- if SolarWindsAPM::OboeInitOptions.instance.lambda_env
141
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] get decision from oboe_api" }
142
- # trigger trace disabled at this point (https://swicloud.atlassian.net/wiki/spaces/NIT/pages/3753116438/AWS+Lambda+Instrumentation+POC#Concerns)
143
- do_metrics, do_sample, rate, source, bucket_rate,
144
- bucket_cap, decision_type, auth, status_msg, auth_msg,
145
- status = SolarWindsAPM.oboe_api.getTracingDecision(*args)
146
- else
147
- do_metrics, do_sample, rate, source, bucket_rate,
148
- bucket_cap, decision_type, auth, status_msg, auth_msg,
149
- status = SolarWindsAPM::Context.getDecisions(*args)
150
- end
151
-
152
- {
153
- 'do_metrics' => do_metrics.positive?,
154
- 'do_sample' => do_sample.positive?,
155
- 'rate' => rate,
156
- 'source' => source,
157
- 'bucket_rate' => bucket_rate,
158
- 'bucket_cap' => bucket_cap,
159
- 'decision_type' => decision_type,
160
- 'auth' => auth,
161
- 'status_msg' => status_msg,
162
- 'auth_msg' => auth_msg,
163
- 'status' => status
164
- }
165
- end
166
-
167
- def otel_decision_from_liboboe(liboboe_decision)
168
- decision = ::OpenTelemetry::SDK::Trace::Samplers::Decision::DROP
169
- if liboboe_decision['do_sample']
170
- decision = ::OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_AND_SAMPLE # even if not do_metrics
171
- elsif liboboe_decision['do_metrics']
172
- decision = ::OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_ONLY
173
- end
174
- SolarWindsAPM.logger.debug { "otel decision: #{decision} created from liboboe_decision: #{liboboe_decision}" }
175
- decision
176
- end
177
-
178
- ##
179
- # add sw=value and xtrace_options_response=value into the old/new tracestate
180
- # the returned value tracestate will be used in propagating to next services
181
- def calculate_trace_state(liboboe_decision, parent_span_context, xtraceoptions)
182
- if !parent_span_context.valid? || parent_span_context.tracestate.nil?
183
- trace_state = create_new_trace_state(parent_span_context, liboboe_decision)
184
- else
185
- trace_state = parent_span_context.tracestate.set_value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY,
186
- sw_from_span_and_decision(parent_span_context,
187
- liboboe_decision))
188
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] updated trace_state: #{trace_state.inspect}" }
189
- end
190
-
191
- # for setting up the xtrace_options_response
192
- if xtraceoptions&.options
193
- trace_state = trace_state.set_value(XTraceOptions.sw_xtraceoptions_response_key.to_s,
194
- create_xtraceoptions_response_value(liboboe_decision,
195
- parent_span_context, xtraceoptions))
196
- end
197
- trace_state
198
- end
199
-
200
- ##
201
- #
202
- def create_new_trace_state(parent_span_context, liboboe_decision)
203
- decision = sw_from_span_and_decision(parent_span_context, liboboe_decision)
204
- trace_state = ::OpenTelemetry::Trace::Tracestate.from_hash({ SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY => decision }) # e.g. sw=3e222c863a04123a-01
205
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] created new trace_state: #{trace_state.inspect}" }
206
- trace_state
207
- end
208
-
209
- ##
210
- #
211
- def create_xtraceoptions_response_value(liboboe_decision, parent_span_context, xtraceoptions)
212
- response = []
213
- w3c_sanitized = SolarWindsAPM::Constants::INTL_SWO_EQUALS_W3C_SANITIZED
214
- w3c_sanitized_comma = SolarWindsAPM::Constants::INTL_SWO_COMMA_W3C_SANITIZED
215
- if xtraceoptions.signature && liboboe_decision['auth_msg']
216
- response << [XTRACEOPTIONS_RESP_AUTH,
217
- liboboe_decision['auth_msg']].join(w3c_sanitized)
218
- end
219
-
220
- if !liboboe_decision['auth'] || liboboe_decision['auth'] < 1
221
- if xtraceoptions.trigger_trace
222
- # If a traceparent header was provided then oboe does not generate the message
223
- tracestring = Utils.traceparent_from_context(parent_span_context) if parent_span_context.valid? && parent_span_context.remote?
224
- trigger_msg = tracestring && (liboboe_decision['decision_type']).zero? ? XTRACEOPTIONS_RESP_TRIGGER_IGNORED : liboboe_decision['status_msg']
225
- SolarWindsAPM.logger.debug do
226
- "[#{self.class}/#{__method__}] tracestring: #{tracestring}; trigger_msg: #{trigger_msg}"
227
- end
228
- else
229
- trigger_msg = XTRACEOPTIONS_RESP_TRIGGER_NOT_REQUESTED
230
- end
231
-
232
- response << [XTRACEOPTIONS_RESP_TRIGGER_TRACE, trigger_msg].join(w3c_sanitized) # e.g. response << trigger-trace####ok
233
- end
234
-
235
- # appending ignored value from xtraceoptions to response. e.g. response << ignored####invalidkeys,invalidkeys,invalidkeys
236
- unless xtraceoptions.ignored.empty?
237
- response << [XTRACEOPTIONS_RESP_IGNORED,
238
- xtraceoptions.ignored.join(w3c_sanitized_comma)].join(w3c_sanitized)
239
- end
240
- joined_response = response.join(';')
241
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] final response_value: #{joined_response}" }
242
- joined_response
243
- end
244
-
245
- ##
246
- # calculate_attributes is used for getting the otel Result class in last step of sampler should_sample?
247
- # e.g. result = Result.new(decision: otel_decision, attributes: new_attributes, tracestate: new_trace_state)
248
- # calculate_attributes use new_trace_state that is derived from current span information and old tracestate from parent_span_context.tracestate
249
- # the sw.w3c.tracestate should perserve the old tracestate value for debugging purpose
250
- def calculate_attributes(attributes, liboboe_decision, trace_state, parent_span_context, xtraceoptions)
251
- SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] new_trace_state: #{trace_state.inspect}" }
252
- new_attributes = attributes.dup || {}
253
-
254
- # Always (root or is_remote) set _INTERNAL_SW_KEYS if injected
255
- new_attributes[INTERNAL_SW_KEYS] = xtraceoptions.sw_keys if xtraceoptions.sw_keys
256
-
257
- # Always (root or is_remote) set custom KVs if extracted from x-trace-options
258
- xtraceoptions.custom_kvs&.each { |k, v| new_attributes[k] = v }
259
-
260
- # Always (root or is_remote) set service entry internal KVs
261
- new_attributes[INTERNAL_BUCKET_CAPACITY] = liboboe_decision['bucket_cap'].to_s
262
- new_attributes[INTERNAL_BUCKET_RATE] = liboboe_decision['bucket_rate'].to_s
263
- new_attributes[INTERNAL_SAMPLE_RATE] = liboboe_decision['rate']
264
- new_attributes[INTERNAL_SAMPLE_SOURCE] = liboboe_decision['source']
265
-
266
- # set sw.tracestate_parent_id if its tracestate contains "sw"
267
- sw_value = parent_span_context.tracestate.value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY)
268
- new_attributes[SW_TRACESTATE_ROOT_KEY] = sw_value.split('-')[0] if sw_value && parent_span_context.remote?
269
-
270
- # If unsigned or signed TT (root or is_remote), set TriggeredTrace
271
- new_attributes[SolarWindsAPM::Constants::INTERNAL_TRIGGERED_TRACE] = true if xtraceoptions.trigger_trace
272
-
273
- # Trace's root span has no valid traceparent nor tracestate so we can't calculate remaining attributes
274
- if !parent_span_context.valid? || trace_state.nil?
275
- SolarWindsAPM.logger.debug do
276
- "[#{self.class}/#{__method__}] No valid traceparent or no tracestate - returning attributes: #{new_attributes}"
277
- end
278
- return new_attributes.freeze || nil
279
- end
280
-
281
- new_attributes = add_tracestate_capture_to_new_attributes(new_attributes, liboboe_decision, trace_state,
282
- parent_span_context)
283
- new_attributes.freeze
284
- end
285
-
286
- ##
287
- #
288
- def add_tracestate_capture_to_new_attributes(new_attributes, liboboe_decision, trace_state, parent_span_context)
289
- tracestate_capture = new_attributes[SW_TRACESTATE_CAPTURE_KEY]
290
- SolarWindsAPM.logger.debug do
291
- "[#{self.class}/#{__method__}] tracestate_capture #{tracestate_capture.inspect}; new_attributes #{new_attributes.inspect}"
292
- end
293
-
294
- if tracestate_capture.nil?
295
- trace_state_no_response = trace_state.delete(XTraceOptions.sw_xtraceoptions_response_key)
296
- else
297
- # retain all potential tracestate pairs for attributes and generate new sw=key for tracestate based on root parent_span_id
298
- attr_trace_state = ::OpenTelemetry::Trace::Tracestate.from_string(tracestate_capture)
299
- new_attr_trace_state = attr_trace_state.set_value(SolarWindsAPM::Constants::INTL_SWO_TRACESTATE_KEY,
300
- sw_from_span_and_decision(parent_span_context,
301
- liboboe_decision))
302
- trace_state_no_response = new_attr_trace_state.delete(XTraceOptions.sw_xtraceoptions_response_key)
303
- end
304
- SolarWindsAPM.logger.debug do
305
- "[#{self.class}/#{__method__}] trace_state_no_response #{trace_state_no_response.inspect}"
306
- end
307
-
308
- trace_state_no_response = parent_span_context.tracestate.delete(XTraceOptions.sw_xtraceoptions_response_key)
309
- no_sw_count = trace_state_no_response.to_h.count { |k, _v| k != 'sw' }
310
-
311
- if no_sw_count.positive?
312
- new_attributes[SW_TRACESTATE_CAPTURE_KEY] =
313
- Utils.trace_state_header(trace_state_no_response)
314
- end
315
- SolarWindsAPM.logger.debug do
316
- "[#{self.class}/#{__method__}] new_attributes after add_tracestate_capture_to_new_attributes: #{new_attributes.inspect}"
317
- end
318
-
319
- new_attributes
320
- end
321
-
322
- # formats tracestate sw value from span_id and liboboe decision as 16-byte span_id with 8-bit trace_flags e.g. 1a2b3c4d5e6f7g8h-01
323
- def sw_from_span_and_decision(parent_span_context, liboboe_decision)
324
- trace_flag = liboboe_decision['do_sample'] == true ? '01' : '00'
325
- [parent_span_context.hex_span_id, trace_flag].join('-')
326
- end
327
-
328
- def otel_sampled?(otel_decision)
329
- otel_decision == ::OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_AND_SAMPLE
330
- end
331
- end
332
- end
333
- 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
- # OTelConfig module
11
- # For configure otel component: configurable: propagator, exporter
12
- # non-config: sampler, processor, response_propagator
13
- # Level of this configuration: SolarWindsOTel::Config -> OboeOption -> SolarWindsOTel::OTelConfig
14
- module OTelConfig
15
- @@config = {}
16
- @@config_map = {}
17
-
18
- @@agent_enabled = true
19
-
20
- def self.disable_agent(reason: nil)
21
- return unless @@agent_enabled # only show the msg once
22
-
23
- @@agent_enabled = false
24
- SolarWindsAPM.logger.warn { "[#{name}/#{__method__}] SolarWindsAPM disabled. No Trace exported. Reason: #{reason}" }
25
- end
26
-
27
- def self.resolve_sampler
28
- sampler_config = { 'trigger_trace' => SolarWindsAPM::Config[:trigger_tracing_mode] }
29
- @@config[:sampler] =
30
- ::OpenTelemetry::SDK::Trace::Samplers.parent_based(
31
- root: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config),
32
- remote_parent_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config),
33
- remote_parent_not_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new(sampler_config)
34
- )
35
- end
36
-
37
- #
38
- # append/add solarwinds_response_propagator into rack instrumentation
39
- #
40
- def self.resolve_response_propagator
41
- response_propagator = SolarWindsAPM::OpenTelemetry::SolarWindsResponsePropagator::TextMapPropagator.new
42
- rack_setting = @@config_map['OpenTelemetry::Instrumentation::Rack']
43
-
44
- if rack_setting
45
- if rack_setting[:response_propagators].instance_of?(Array)
46
- rack_setting[:response_propagators].append(response_propagator)
47
- elsif rack_setting[:response_propagators].nil?
48
- rack_setting[:response_propagators] = [response_propagator]
49
- else
50
- SolarWindsAPM.logger.warn do
51
- "[#{name}/#{__method__}] Rack response propagator resolve failed. Provided type #{rack_setting[:response_propagators].class}, please provide Array e.g. [#{rack_setting[:response_propagators]}]"
52
- end
53
- end
54
- else
55
- @@config_map['OpenTelemetry::Instrumentation::Rack'] = { response_propagators: [response_propagator] }
56
- end
57
- end
58
-
59
- def self.[](key)
60
- @@config[key.to_sym]
61
- end
62
-
63
- def self.print_config
64
- @@config.each do |k, v|
65
- SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] Config Key/Value: #{k}, #{v.class}" }
66
- end
67
- @@config_map.each do |k, v|
68
- SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] Config Key/Value: #{k}, #{v}" }
69
- end
70
- nil
71
- end
72
-
73
- def self.resolve_solarwinds_processor
74
- txn_manager = SolarWindsAPM::TxnNameManager.new
75
- exporter = SolarWindsAPM::OpenTelemetry::SolarWindsExporter.new(txn_manager: txn_manager)
76
- @@config[:metrics_processor] = SolarWindsAPM::OpenTelemetry::SolarWindsProcessor.new(txn_manager)
77
- @@config[:span_processor] = ::OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(exporter)
78
- end
79
-
80
- def self.resolve_solarwinds_propagator
81
- @@config[:propagators] = SolarWindsAPM::OpenTelemetry::SolarWindsPropagator::TextMapPropagator.new
82
- end
83
-
84
- def self.validate_propagator(propagators)
85
- if propagators.nil?
86
- disable_agent(reason: 'propagators are invaliad.')
87
- return
88
- end
89
-
90
- SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] propagators: #{propagators.map(&:class)}" }
91
- disable_agent(reason: 'Missing tracecontext propagator.') unless ([::OpenTelemetry::Trace::Propagation::TraceContext::TextMapPropagator, ::OpenTelemetry::Baggage::Propagation::TextMapPropagator] - propagators.map(&:class)).empty?
92
- end
93
-
94
- def self.initialize
95
- unless defined?(::OpenTelemetry::SDK::Configurator)
96
- disable_agent(reason: 'missing OpenTelemetry::SDK::Configurator; opentelemetry seems not loaded.')
97
- return
98
- end
99
-
100
- resolve_sampler
101
- resolve_solarwinds_propagator
102
- resolve_solarwinds_processor
103
- resolve_response_propagator
104
-
105
- print_config if SolarWindsAPM.logger.level.zero?
106
-
107
- # resolve OTEL environmental variables
108
- ENV['OTEL_TRACES_EXPORTER'] = 'none' if ENV['OTEL_TRACES_EXPORTER'].to_s.empty?
109
- if ENV['OTEL_LOG_LEVEL'].to_s.empty?
110
- log_level = (ENV['SW_APM_DEBUG_LEVEL'] || SolarWindsAPM::Config[:debug_level] || 3).to_i
111
- ENV['OTEL_LOG_LEVEL'] = SolarWindsAPM::Config::SW_LOG_LEVEL_MAPPING.dig(log_level, :otel)
112
- end
113
-
114
- # for dbo, traceparent injection as comments
115
- require_relative 'patch/tag_sql_patch' if SolarWindsAPM::Config[:tag_sql]
116
-
117
- ::OpenTelemetry::SDK.configure { |c| c.use_all(@@config_map) }
118
-
119
- validate_propagator(::OpenTelemetry.propagation.instance_variable_get(:@propagators))
120
-
121
- return unless @@agent_enabled
122
-
123
- # append our propagators
124
- ::OpenTelemetry.propagation.instance_variable_get(:@propagators).append(@@config[:propagators])
125
-
126
- # append our processors (with our exporter)
127
- ::OpenTelemetry.tracer_provider.add_span_processor(@@config[:metrics_processor])
128
- ::OpenTelemetry.tracer_provider.add_span_processor(@@config[:span_processor])
129
-
130
- # configure sampler afterwards
131
- ::OpenTelemetry.tracer_provider.sampler = @@config[:sampler]
132
-
133
- if ENV['SW_APM_AUTO_CONFIGURE'] == 'false'
134
- SolarWindsAPM.logger.info '==================================================================='
135
- SolarWindsAPM.logger.info "\e[1mSolarWindsAPM manual initialization was successful.\e[0m"
136
- SolarWindsAPM.logger.info '==================================================================='
137
- end
138
-
139
- nil
140
- end
141
-
142
- #
143
- # Allow initialize after set new value to SolarWindsAPM::Config[:key]=value
144
- #
145
- # Usage:
146
- #
147
- # Default using the use_all to load all instrumentation
148
- # But with specific instrumentation disabled, use {:enabled: false} in config
149
- # SolarWindsAPM::OTelConfig.initialize_with_config do |config|
150
- # config["OpenTelemetry::Instrumentation::Rack"] = {"a" => "b"}
151
- # config["OpenTelemetry::Instrumentation::Dalli"] = {:enabled: false}
152
- # end
153
- #
154
- def self.initialize_with_config
155
- unless block_given?
156
- SolarWindsAPM.logger.warn do
157
- "[#{name}/#{__method__}] Block not given while doing in-code configuration. Agent disabled."
158
- end
159
- return
160
- end
161
-
162
- yield @@config_map
163
-
164
- if @@config_map.empty?
165
- SolarWindsAPM.logger.warn do
166
- "[#{name}/#{__method__}] No configuration given for in-code configuration. Agent disabled."
167
- end
168
- return
169
- end
170
-
171
- initialize
172
- end
173
- end
174
- end
@@ -1,56 +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
- require 'solarwinds_apm/constants'
10
- require 'solarwinds_apm/api'
11
- require 'solarwinds_apm/support'
12
- require 'solarwinds_apm/opentelemetry'
13
-
14
- module SolarWindsAPM
15
- # OTelLambdaConfig module
16
- module OTelLambdaConfig
17
- def self.initialize
18
- return unless defined?(::OpenTelemetry::SDK::Configurator)
19
-
20
- if ENV['OTEL_TRACES_EXPORTER'].to_s.empty?
21
- ENV['OTEL_TRACES_EXPORTER'] = 'otlp'
22
- elsif !ENV['OTEL_TRACES_EXPORTER'].include? 'otlp'
23
- ENV['OTEL_TRACES_EXPORTER'] += ',otlp'
24
- end
25
-
26
- ENV['OTEL_RESOURCE_ATTRIBUTES'] = "sw.apm.version=#{SolarWindsAPM::Version::STRING},sw.data.module=apm,service.name=#{ENV['OTEL_SERVICE_NAME'] || ENV.fetch('AWS_LAMBDA_FUNCTION_NAME', nil)}," + ENV['OTEL_RESOURCE_ATTRIBUTES'].to_s
27
- ::OpenTelemetry::SDK.configure(&:use_all)
28
-
29
- # append our propagators
30
- ::OpenTelemetry.propagation.instance_variable_get(:@propagators).append(SolarWindsAPM::OpenTelemetry::SolarWindsPropagator::TextMapPropagator.new)
31
-
32
- # register metrics_exporter to meter_provider
33
- ::OpenTelemetry.meter_provider.add_metric_reader(::OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new)
34
-
35
- # append our processors
36
- ::OpenTelemetry.tracer_provider.add_span_processor(SolarWindsAPM::OpenTelemetry::OTLPProcessor.new)
37
-
38
- # configure sampler afterwards
39
- ::OpenTelemetry.tracer_provider.sampler = ::OpenTelemetry::SDK::Trace::Samplers.parent_based(
40
- root: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new,
41
- remote_parent_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new,
42
- remote_parent_not_sampled: SolarWindsAPM::OpenTelemetry::SolarWindsSampler.new
43
- )
44
-
45
- SolarWindsAPM.logger.info do
46
- "[#{name}/#{__method__}] SolarWindsAPM lambda configuration initialized \
47
- \n Installed instrumentation: #{::OpenTelemetry.tracer_provider.instance_variable_get(:@registry).keys} \
48
- \n SpanProcessor: #{::OpenTelemetry.tracer_provider.instance_variable_get(:@span_processors).map(&:class)} \
49
- \n Sampler: #{::OpenTelemetry.tracer_provider.instance_variable_get(:@sampler).inspect} \
50
- \n Resource: #{::OpenTelemetry.tracer_provider.instance_variable_get(:@resource).inspect}"
51
- end
52
-
53
- nil
54
- end
55
- end
56
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright The OpenTelemetry Authors
4
- #
5
- # SPDX-License-Identifier: Apache-2.0
6
-
7
- module SolarWindsAPM
8
- module Patch
9
- module DummyPatch
10
- end
11
- end
12
- end
@@ -1,33 +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
- # OboeTracingMode
11
- # Used in solarwinds_sampler
12
- class OboeTracingMode
13
- OBOE_SETTINGS_UNSET = -1
14
- OBOE_TRACE_DISABLED = 0
15
- OBOE_TRACE_ENABLED = 1
16
- OBOE_TRIGGER_DISABLED = 0
17
- OBOE_TRIGGER_ENABLED = 1
18
-
19
- def self.get_oboe_trace_mode(tracing_mode)
20
- mode = OBOE_SETTINGS_UNSET
21
- mode = OBOE_TRACE_ENABLED if tracing_mode == :enabled
22
- mode = OBOE_TRACE_DISABLED if tracing_mode == :disabled
23
- mode
24
- end
25
-
26
- def self.get_oboe_trigger_trace_mode(trigger_trace_mode)
27
- mode = OBOE_SETTINGS_UNSET
28
- mode = OBOE_TRIGGER_ENABLED if trigger_trace_mode == :enabled
29
- mode = OBOE_TRIGGER_DISABLED if trigger_trace_mode == :disabled
30
- mode
31
- end
32
- end
33
- end