solarwinds_apm 6.0.0 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/ext/oboe_metal/extconf.rb +42 -41
  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 +30 -27
  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 +8 -4
  17. data/lib/solarwinds_apm/api/tracing.rb +6 -4
  18. data/lib/solarwinds_apm/api/transaction_name.rb +21 -11
  19. data/lib/solarwinds_apm/api.rb +7 -5
  20. data/lib/solarwinds_apm/config.rb +70 -46
  21. data/lib/solarwinds_apm/constants.rb +25 -23
  22. data/lib/solarwinds_apm/logger.rb +2 -0
  23. data/lib/solarwinds_apm/noop/api.rb +3 -1
  24. data/lib/solarwinds_apm/noop/context.rb +2 -0
  25. data/lib/solarwinds_apm/noop/metadata.rb +2 -0
  26. data/lib/solarwinds_apm/noop/span.rb +2 -0
  27. data/lib/solarwinds_apm/noop.rb +8 -6
  28. data/lib/solarwinds_apm/oboe_init_options.rb +47 -39
  29. data/lib/solarwinds_apm/opentelemetry/otlp_processor.rb +135 -0
  30. data/lib/solarwinds_apm/opentelemetry/solarwinds_exporter.rb +66 -41
  31. data/lib/solarwinds_apm/opentelemetry/solarwinds_processor.rb +49 -51
  32. data/lib/solarwinds_apm/opentelemetry/solarwinds_propagator.rb +30 -22
  33. data/lib/solarwinds_apm/opentelemetry/solarwinds_response_propagator.rb +29 -16
  34. data/lib/solarwinds_apm/opentelemetry/solarwinds_sampler.rb +135 -98
  35. data/lib/solarwinds_apm/opentelemetry.rb +8 -5
  36. data/lib/solarwinds_apm/otel_config.rb +32 -25
  37. data/lib/solarwinds_apm/otel_lambda_config.rb +53 -0
  38. data/lib/solarwinds_apm/patch.rb +2 -0
  39. data/lib/solarwinds_apm/support/logger_formatter.rb +4 -2
  40. data/lib/solarwinds_apm/support/logging_log_event.rb +2 -0
  41. data/lib/solarwinds_apm/support/lumberjack_formatter.rb +2 -0
  42. data/lib/solarwinds_apm/support/oboe_tracing_mode.rb +2 -0
  43. data/lib/solarwinds_apm/support/service_key_checker.rb +18 -6
  44. data/lib/solarwinds_apm/support/support_report.rb +5 -3
  45. data/lib/solarwinds_apm/support/swomarginalia/comment.rb +18 -17
  46. data/lib/solarwinds_apm/support/swomarginalia/load_swomarginalia.rb +13 -12
  47. data/lib/solarwinds_apm/support/swomarginalia/railtie.rb +4 -2
  48. data/lib/solarwinds_apm/support/swomarginalia/swomarginalia.rb +3 -1
  49. data/lib/solarwinds_apm/support/transaction_cache.rb +6 -4
  50. data/lib/solarwinds_apm/support/transaction_settings.rb +7 -3
  51. data/lib/solarwinds_apm/support/txn_name_manager.rb +8 -3
  52. data/lib/solarwinds_apm/support/utils.rb +12 -9
  53. data/lib/solarwinds_apm/support/x_trace_options.rb +23 -17
  54. data/lib/solarwinds_apm/support.rb +28 -24
  55. data/lib/solarwinds_apm/version.rb +3 -1
  56. data/lib/solarwinds_apm.rb +44 -34
  57. metadata +14 -23
@@ -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
@@ -35,35 +37,43 @@ module SolarWindsAPM
35
37
  # === Returns:
36
38
  # * Boolean
37
39
  #
38
- def set_transaction_name(custom_name=nil)
40
+ def set_transaction_name(custom_name = nil)
39
41
  status = true
40
42
  if ENV.fetch('SW_APM_ENABLED', 'true') == 'false' ||
41
43
  SolarWindsAPM::Context.toString == '99-00000000000000000000000000000000-0000000000000000-00'
42
44
  # library disabled or noop, just log and skip work.
43
45
  # TODO: can we have a single indicator that the API is in noop mode?
44
- SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] SolarWindsAPM is in disabled or noop mode."}
46
+ SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] SolarWindsAPM is in disabled or noop mode." }
45
47
  elsif custom_name.nil? || custom_name.empty?
46
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Set transaction name failed: custom_name is either nil or empty string."}
48
+ SolarWindsAPM.logger.warn do
49
+ "[#{name}/#{__method__}] Set transaction name failed: custom_name is either nil or empty string."
50
+ end
47
51
  status = false
48
- elsif SolarWindsAPM::OTelConfig.class_variable_get(:@@config)[:span_processor].nil?
49
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Set transaction name failed: Solarwinds processor is missing."}
52
+ elsif SolarWindsAPM::OTelConfig[:metrics_processor].nil?
53
+ SolarWindsAPM.logger.warn do
54
+ "[#{name}/#{__method__}] Set transaction name failed: Solarwinds processor is missing."
55
+ end
50
56
  status = false
51
57
  else
52
- solarwinds_processor = SolarWindsAPM::OTelConfig.class_variable_get(:@@config)[:span_processor]
53
- current_span = ::OpenTelemetry::Trace.current_span
58
+ solarwinds_processor = SolarWindsAPM::OTelConfig[:metrics_processor]
59
+ current_span = ::OpenTelemetry::Trace.current_span
54
60
 
55
61
  if current_span.context.valid?
56
62
  current_trace_id = current_span.context.hex_trace_id
57
63
  entry_span_id, trace_flags = solarwinds_processor.txn_manager.get_root_context_h(current_trace_id)&.split('-')
58
64
  if entry_span_id.to_s.empty? || trace_flags.to_s.empty?
59
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Set transaction name failed: record not found in the transaction manager."}
65
+ SolarWindsAPM.logger.warn do
66
+ "[#{name}/#{__method__}] Set transaction name failed: record not found in the transaction manager."
67
+ end
60
68
  status = false
61
69
  else
62
- solarwinds_processor.txn_manager.set("#{current_trace_id}-#{entry_span_id}",custom_name)
63
- SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] Cached custom transaction name for #{current_trace_id}-#{entry_span_id} as #{custom_name}"}
70
+ solarwinds_processor.txn_manager.set("#{current_trace_id}-#{entry_span_id}", custom_name)
71
+ SolarWindsAPM.logger.debug do
72
+ "[#{name}/#{__method__}] Cached custom transaction name for #{current_trace_id}-#{entry_span_id} as #{custom_name}"
73
+ end
64
74
  end
65
75
  else
66
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Set transaction name failed: invalid span context."}
76
+ SolarWindsAPM.logger.warn { "[#{name}/#{__method__}] Set transaction name failed: invalid span context." }
67
77
  status = false
68
78
  end
69
79
  end
@@ -1,14 +1,16 @@
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
4
6
  #
5
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.
6
8
 
7
- require_relative './api/transaction_name'
8
- require_relative './api/current_trace_info'
9
- require_relative './api/tracing'
10
- require_relative './api/opentelemetry'
11
- require_relative './api/custom_metrics'
9
+ require_relative 'api/transaction_name'
10
+ require_relative 'api/current_trace_info'
11
+ require_relative 'api/tracing'
12
+ require_relative 'api/opentelemetry'
13
+ require_relative 'api/custom_metrics'
12
14
 
13
15
  module SolarWindsAPM
14
16
  module API
@@ -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
@@ -12,24 +14,24 @@ module SolarWindsAPM
12
14
  # Use SolarWindsAPM::Config.show to view the entire nested hash.
13
15
  #
14
16
  module Config
15
- SW_LOG_LEVEL_MAPPING = {-1 => {:stdlib => ::Logger::FATAL, :otel => 'fatal'},
16
- 0 => {:stdlib => ::Logger::FATAL, :otel => 'fatal'},
17
- 1 => {:stdlib => ::Logger::ERROR, :otel => 'error'},
18
- 2 => {:stdlib => ::Logger::WARN, :otel => 'warn'},
19
- 3 => {:stdlib => ::Logger::INFO, :otel => 'info'},
20
- 4 => {:stdlib => ::Logger::DEBUG, :otel => 'debug'},
21
- 5 => {:stdlib => ::Logger::DEBUG, :otel => 'debug'},
22
- 6 => {:stdlib => ::Logger::DEBUG, :otel => 'debug'}}.freeze
17
+ SW_LOG_LEVEL_MAPPING = { -1 => { stdlib: ::Logger::FATAL, otel: 'fatal' },
18
+ 0 => { stdlib: ::Logger::FATAL, otel: 'fatal' },
19
+ 1 => { stdlib: ::Logger::ERROR, otel: 'error' },
20
+ 2 => { stdlib: ::Logger::WARN, otel: 'warn' },
21
+ 3 => { stdlib: ::Logger::INFO, otel: 'info' },
22
+ 4 => { stdlib: ::Logger::DEBUG, otel: 'debug' },
23
+ 5 => { stdlib: ::Logger::DEBUG, otel: 'debug' },
24
+ 6 => { stdlib: ::Logger::DEBUG, otel: 'debug' } }.freeze
23
25
 
24
26
  @@config = {}
25
- @@instrumentation = [:action_controller, :action_controller_api, :action_view,
26
- :active_record, :bunnyclient, :bunnyconsumer, :curb,
27
- :dalli, :delayed_jobclient, :delayed_jobworker,
28
- :excon, :faraday, :graphql, :grpc_client, :grpc_server, :grape,
29
- :httpclient, :nethttp, :memcached, :mongo, :moped, :padrino, :rack, :redis,
30
- :resqueclient, :resqueworker, :rest_client,
31
- :sequel, :sidekiqclient, :sidekiqworker, :sinatra, :typhoeus,
32
- :curb, :excon, :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
27
+ @@instrumentation = %i[action_controller action_controller_api action_view
28
+ active_record bunnyclient bunnyconsumer curb
29
+ dalli delayed_jobclient delayed_jobworker
30
+ excon faraday graphql grpc_client grpc_server grape
31
+ httpclient nethttp memcached mongo moped padrino rack redis
32
+ resqueclient resqueworker rest_client
33
+ sequel sidekiqclient sidekiqworker sinatra typhoeus
34
+ curb excon faraday httpclient nethttp rest_client typhoeus]
33
35
 
34
36
  ##
35
37
  # load_config_file
@@ -53,26 +55,32 @@ module SolarWindsAPM
53
55
  config_files << config_file if File.exist?(config_file)
54
56
 
55
57
  # Check for file set by env variable
56
- config_files << config_file_from_env if ENV.has_key?('SW_APM_CONFIG_RUBY')
58
+ config_files << config_file_from_env if ENV.key?('SW_APM_CONFIG_RUBY')
57
59
 
58
60
  # Check for default config file
59
61
  config_file = File.join(Dir.pwd, 'solarwinds_apm_config.rb')
60
62
  config_files << config_file if File.exist?(config_file)
61
63
 
62
- SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] Available config_files: #{config_files.join(', ')}" }
63
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Multiple configuration files configured, using the first one listed: #{config_files.join(', ')}"} if config_files.size > 1
64
- load(config_files[0]) if config_files.size > 0
64
+ SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] Available config_files: #{config_files.join(', ')}" }
65
+ if config_files.size > 1
66
+ SolarWindsAPM.logger.warn do
67
+ "[#{name}/#{__method__}] Multiple configuration files configured, using the first one listed: #{config_files.join(', ')}"
68
+ end
69
+ end
70
+ load(config_files[0]) if config_files.size.positive?
65
71
 
66
- set_log_level # sets SolarWindsAPM::Config[:debug_level], SolarWindsAPM.logger.level
72
+ set_log_level # sets SolarWindsAPM::Config[:debug_level], SolarWindsAPM.logger.level
67
73
  end
68
74
 
69
75
  def self.config_file_from_env
70
- if File.exist?(ENV['SW_APM_CONFIG_RUBY']) && !File.directory?(ENV['SW_APM_CONFIG_RUBY'])
71
- config_file = ENV['SW_APM_CONFIG_RUBY']
72
- elsif File.exist?(File.join(ENV['SW_APM_CONFIG_RUBY'], 'solarwinds_apm_config.rb'))
73
- config_file = File.join(ENV['SW_APM_CONFIG_RUBY'], 'solarwinds_apm_config.rb')
76
+ if File.exist?(ENV.fetch('SW_APM_CONFIG_RUBY', nil)) && !File.directory?(ENV.fetch('SW_APM_CONFIG_RUBY', nil))
77
+ config_file = ENV.fetch('SW_APM_CONFIG_RUBY', nil)
78
+ elsif File.exist?(File.join(ENV.fetch('SW_APM_CONFIG_RUBY', nil), 'solarwinds_apm_config.rb'))
79
+ config_file = File.join(ENV.fetch('SW_APM_CONFIG_RUBY', nil), 'solarwinds_apm_config.rb')
74
80
  else
75
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Could not find the configuration file set by the SW_APM_CONFIG_RUBY environment variable: #{ENV['SW_APM_CONFIG_RUBY']}"}
81
+ SolarWindsAPM.logger.warn do
82
+ "[#{name}/#{__method__}] Could not find the configuration file set by the SW_APM_CONFIG_RUBY environment variable: #{ENV.fetch('SW_APM_CONFIG_RUBY', nil)}"
83
+ end
76
84
  end
77
85
  config_file
78
86
  end
@@ -92,7 +100,7 @@ module SolarWindsAPM
92
100
  if env_var && valid_env_values.include?(env_value)
93
101
  value = bool ? true?(env_value) : env_value.to_sym
94
102
  elsif env_var && !env_value.to_s.empty?
95
- SolarWindsAPM.logger.warn("[#{name}/#{__method__}] #{env_var} must be #{valid_env_values.join('/')} (current setting is #{ENV[env_var]}). Using default value: #{default}.")
103
+ SolarWindsAPM.logger.warn("[#{name}/#{__method__}] #{env_var} must be #{valid_env_values.join('/')} (current setting is #{ENV.fetch(env_var, nil)}). Using default value: #{default}.")
96
104
  return @@config[key.to_sym] = default
97
105
  end
98
106
 
@@ -103,7 +111,7 @@ module SolarWindsAPM
103
111
  end
104
112
 
105
113
  def self.true?(obj)
106
- obj.to_s.casecmp("true").zero?
114
+ obj.to_s.casecmp('true').zero?
107
115
  end
108
116
 
109
117
  def self.boolean?(obj)
@@ -111,7 +119,7 @@ module SolarWindsAPM
111
119
  end
112
120
 
113
121
  def self.symbol?(obj)
114
- [:enabled, :disabled].include?(obj)
122
+ %i[enabled disabled].include?(obj)
115
123
  end
116
124
 
117
125
  ##
@@ -121,9 +129,13 @@ module SolarWindsAPM
121
129
  # to create an output similar to the content of the config file
122
130
  #
123
131
  def self.print_config
124
- SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] General configurations list blow:"}
125
- @@config.each do |k,v|
126
- SolarWindsAPM.logger.debug {"[#{name}/#{__method__}] Config Key/Value: #{k}, #{v.inspect}"} unless @@instrumentation.include?(k)
132
+ SolarWindsAPM.logger.debug { "[#{name}/#{__method__}] General configurations list blow:" }
133
+ @@config.each do |k, v|
134
+ next if @@instrumentation.include?(k)
135
+
136
+ SolarWindsAPM.logger.debug do
137
+ "[#{name}/#{__method__}] Config Key/Value: #{k}, #{v.inspect}"
138
+ end
127
139
  end
128
140
  nil
129
141
  end
@@ -137,12 +149,18 @@ module SolarWindsAPM
137
149
  #
138
150
  def self.initialize
139
151
  # for config file backward compatibility
140
- @@instrumentation.each {|inst| @@config[inst] = {}}
152
+ @@instrumentation.each { |inst| @@config[inst] = {} }
141
153
  @@config[:transaction_name] = {}
142
154
 
143
155
  # Always load the template, it has all the keys and defaults defined,
144
156
  # no guarantee of completeness in the user's config file
145
- load(File.join(File.dirname(File.dirname(__FILE__)), 'rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb'))
157
+
158
+ load(File.join(File.dirname(File.dirname(__FILE__)),
159
+ 'rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb'))
160
+
161
+ load_config_file
162
+
163
+ print_config if SolarWindsAPM.logger.level.zero?
146
164
  end
147
165
 
148
166
  def self.update!(data)
@@ -164,7 +182,7 @@ module SolarWindsAPM
164
182
  #
165
183
  # Config variable assignment method. Here we validate and store the
166
184
  # assigned value(s) and trigger any secondary action needed.
167
- # ENV always have higher precedence
185
+ # ENV always have higher precedence
168
186
  #
169
187
  def self.[]=(key, value)
170
188
  key = key.to_sym
@@ -172,18 +190,24 @@ module SolarWindsAPM
172
190
 
173
191
  case key
174
192
  when :sampling_rate
175
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] sampling_rate is not a supported setting for SolarWindsAPM::Config. Please use :sample_rate."}
193
+ SolarWindsAPM.logger.warn do
194
+ "[#{name}/#{__method__}] sampling_rate is not a supported setting for SolarWindsAPM::Config. Please use :sample_rate."
195
+ end
176
196
 
177
197
  when :sample_rate
178
198
  unless value.is_a?(Integer) || value.is_a?(Float)
179
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] :sample_rate must be a number between 0 and 1000000 (1m) (provided: #{value}), corrected to 0"}
199
+ SolarWindsAPM.logger.warn do
200
+ "[#{name}/#{__method__}] :sample_rate must be a number between 0 and 1000000 (1m) (provided: #{value}), corrected to 0"
201
+ end
180
202
  value = 0
181
203
  end
182
204
 
183
205
  # Validate :sample_rate value
184
206
  unless value.between?(0, 1e6)
185
- new_value = value < 0 ? 0 : 1_000_000
186
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] :sample_rate must be between 0 and 1000000 (1m) (provided: #{value}), corrected to #{new_value}"}
207
+ new_value = value.negative? ? 0 : 1_000_000
208
+ SolarWindsAPM.logger.warn do
209
+ "[#{name}/#{__method__}] :sample_rate must be between 0 and 1000000 (1m) (provided: #{value}), corrected to #{new_value}"
210
+ end
187
211
  end
188
212
 
189
213
  # Assure value is an integer
@@ -217,7 +241,7 @@ module SolarWindsAPM
217
241
  end
218
242
 
219
243
  # `tracing: disabled` is the default
220
- disabled = settings.select { |v| !v.has_key?(:tracing) || v[:tracing] == :disabled }
244
+ disabled = settings.select { |v| !v.key?(:tracing) || v[:tracing] == :disabled }
221
245
  enabled = settings.select { |v| v[:tracing] == :enabled }
222
246
 
223
247
  SolarWindsAPM::Config[:enabled_regexps] = compile_regexp(enabled)
@@ -234,18 +258,18 @@ module SolarWindsAPM
234
258
 
235
259
  def self.compile_settings_regexp(value)
236
260
  regexps = value.select do |v|
237
- v.has_key?(:regexp) &&
261
+ v.key?(:regexp) &&
238
262
  !(v[:regexp].is_a?(String) && v[:regexp].empty?) &&
239
263
  !(v[:regexp].is_a?(Regexp) && v[:regexp].inspect == '//')
240
264
  end
241
265
 
242
266
  regexps.map! do |v|
243
- begin
244
- v[:regexp].is_a?(String) ? Regexp.new(v[:regexp], v[:opts]) : Regexp.new(v[:regexp])
245
- rescue StandardError => e
246
- SolarWindsAPM.logger.warn {"[#{name}/#{__method__}] Problem compiling transaction_settings item #{v}, will ignore. Error: #{e.message}"}
247
- nil
267
+ v[:regexp].is_a?(String) ? Regexp.new(v[:regexp], v[:opts]) : Regexp.new(v[:regexp])
268
+ rescue StandardError => e
269
+ SolarWindsAPM.logger.warn do
270
+ "[#{name}/#{__method__}] Problem compiling transaction_settings item #{v}, will ignore. Error: #{e.message}"
248
271
  end
272
+ nil
249
273
  end
250
274
  regexps.keep_if { |v| !v.nil? }
251
275
  regexps.empty? ? nil : regexps
@@ -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
@@ -7,28 +9,28 @@
7
9
  module SolarWindsAPM
8
10
  # Constants
9
11
  module Constants
10
- HTTP_METHOD = "http.method".freeze
11
- HTTP_ROUTE = "http.route".freeze
12
- HTTP_STATUS_CODE = "http.status_code".freeze
13
- HTTP_URL = "http.url".freeze
14
- INTL_SWO_AO_COLLECTOR = "collector.appoptics.com".freeze
15
- INTL_SWO_AO_STG_COLLECTOR = "collector-stg.appoptics.com".freeze
16
- INTL_SWO_COMMA = ",".freeze
17
- INTL_SWO_COMMA_W3C_SANITIZED = "....".freeze
18
- INTL_SWO_EQUALS = "=".freeze
19
- INTL_SWO_EQUALS_W3C_SANITIZED = "####".freeze
20
- INTL_SWO_TRACESTATE_KEY = "sw".freeze
21
- INTL_SWO_X_OPTIONS_KEY = "sw_xtraceoptions".freeze
22
- INTL_SWO_SIGNATURE_KEY = "sw_signature".freeze
23
- INTL_SWO_DEFAULT_TRACES_EXPORTER = "solarwinds_exporter".freeze
24
- INTL_SWO_TRACECONTEXT_PROPAGATOR = "tracecontext".freeze
25
- INTL_SWO_PROPAGATOR = "solarwinds_propagator".freeze
26
- INTL_SWO_DEFAULT_PROPAGATORS = [INTL_SWO_TRACECONTEXT_PROPAGATOR, "baggage",INTL_SWO_PROPAGATOR].freeze
27
- INTL_SWO_SUPPORT_EMAIL = "SWO-support@solarwinds.com".freeze
28
- INTL_SWO_OTEL_SCOPE_NAME = "otel.scope.name".freeze
29
- INTL_SWO_OTEL_SCOPE_VERSION = "otel.scope.version".freeze
30
- INTL_SWO_OTEL_STATUS = "otel.status".freeze
31
- INTL_SWO_OTEL_STATUS_DESCRIPTION = "otel.status_description".freeze
32
- INTERNAL_TRIGGERED_TRACE = "TriggeredTrace".freeze
12
+ HTTP_METHOD = 'http.method'
13
+ HTTP_ROUTE = 'http.route'
14
+ HTTP_STATUS_CODE = 'http.status_code'
15
+ HTTP_URL = 'http.url'
16
+ INTL_SWO_AO_COLLECTOR = 'collector.appoptics.com'
17
+ INTL_SWO_AO_STG_COLLECTOR = 'collector-stg.appoptics.com'
18
+ INTL_SWO_COMMA = ','
19
+ INTL_SWO_COMMA_W3C_SANITIZED = '....'
20
+ INTL_SWO_EQUALS = '='
21
+ INTL_SWO_EQUALS_W3C_SANITIZED = '####'
22
+ INTL_SWO_TRACESTATE_KEY = 'sw'
23
+ INTL_SWO_X_OPTIONS_KEY = 'sw_xtraceoptions'
24
+ INTL_SWO_SIGNATURE_KEY = 'sw_signature'
25
+ INTL_SWO_DEFAULT_TRACES_EXPORTER = 'solarwinds_exporter'
26
+ INTL_SWO_TRACECONTEXT_PROPAGATOR = 'tracecontext'
27
+ INTL_SWO_PROPAGATOR = 'solarwinds_propagator'
28
+ INTL_SWO_DEFAULT_PROPAGATORS = [INTL_SWO_TRACECONTEXT_PROPAGATOR, 'baggage', INTL_SWO_PROPAGATOR].freeze
29
+ INTL_SWO_SUPPORT_EMAIL = 'SWO-support@solarwinds.com'
30
+ INTL_SWO_OTEL_SCOPE_NAME = 'otel.scope.name'
31
+ INTL_SWO_OTEL_SCOPE_VERSION = 'otel.scope.version'
32
+ INTL_SWO_OTEL_STATUS = 'otel.status'
33
+ INTL_SWO_OTEL_STATUS_DESCRIPTION = 'otel.status_description'
34
+ INTERNAL_TRIGGERED_TRACE = 'TriggeredTrace'
33
35
  end
34
36
  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
@@ -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
@@ -9,7 +11,7 @@
9
11
  #
10
12
  module SolarWindsAPM
11
13
  # API
12
- module API
14
+ module API
13
15
  end
14
16
  end
15
17
 
@@ -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
@@ -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
@@ -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
@@ -1,13 +1,15 @@
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
4
6
  #
5
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.
6
8
 
7
- require_relative './noop/context'
8
- require_relative './noop/metadata'
9
- require_relative './noop/span'
10
- require_relative './noop/api'
9
+ require_relative 'noop/context'
10
+ require_relative 'noop/metadata'
11
+ require_relative 'noop/span'
12
+ require_relative 'noop/api'
11
13
 
12
14
  module SolarWindsAPM
13
15
  include Oboe_metal
@@ -21,11 +23,11 @@ module SolarWindsAPM
21
23
  ##
22
24
  # noop version of :send_status
23
25
  #
24
- def self.send_status(event, context=nil, with_system_timestamp: false); end
26
+ def self.send_status(event, context = nil, with_system_timestamp: false); end
25
27
 
26
28
  ##
27
29
  # noop version of :start
28
30
  #
29
31
  def self.start; end
30
32
  end
31
- end
33
+ 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
@@ -7,16 +9,18 @@
7
9
  require 'singleton'
8
10
  require 'uri'
9
11
 
10
- require_relative './support/service_key_checker'
12
+ require_relative 'support/service_key_checker'
11
13
 
12
14
  module SolarWindsAPM
13
15
  # OboeInitOptions
14
16
  class OboeInitOptions
15
17
  include Singleton
16
18
 
17
- attr_reader :reporter, :host, :service_name, :ec2_md_timeout, :grpc_proxy # exposing these mainly for testing
19
+ attr_reader :reporter, :host, :service_name, :ec2_md_timeout, :grpc_proxy, :lambda_env # exposing these mainly for testing
18
20
 
19
21
  def initialize
22
+ # determining the lambda env based on env var (not used in array_for_oboe for oboe initialization)
23
+ @lambda_env = determine_lambda
20
24
  # optional hostname alias
21
25
  @hostname_alias = ENV['SW_APM_HOSTNAME_ALIAS'] || SolarWindsAPM::Config[:hostname_alias] || ''
22
26
  # level at which log messages will be written to log file (0-6)
@@ -82,18 +86,18 @@ module SolarWindsAPM
82
86
  @reporter, # 7
83
87
  @host, # 8
84
88
  @service_key, # 9
85
- @certificates, #10
86
- @buffer_size, #11
87
- @trace_metrics, #12
88
- @histogram_precision, #13
89
- @token_bucket_capacity, #14
90
- @token_bucket_rate, #15
91
- @file_single, #16
92
- @ec2_md_timeout, #17
93
- @grpc_proxy, #18
94
- 0, #19 arg for lambda (no lambda for ruby yet)
95
- @metric_format, #20
96
- @log_type #21
89
+ @certificates, # 10
90
+ @buffer_size, # 11
91
+ @trace_metrics, # 12
92
+ @histogram_precision, # 13
93
+ @token_bucket_capacity, # 14
94
+ @token_bucket_rate, # 15
95
+ @file_single, # 16
96
+ @ec2_md_timeout, # 17
97
+ @grpc_proxy, # 18
98
+ 0, # 19 arg for lambda (no lambda for ruby yet)
99
+ @metric_format, # 20
100
+ @log_type # 21
97
101
  ]
98
102
  end
99
103
 
@@ -104,32 +108,23 @@ module SolarWindsAPM
104
108
  private
105
109
 
106
110
  def reporter_and_host
107
-
108
111
  reporter = ENV['SW_APM_REPORTER'] || 'ssl'
109
112
 
110
- host = ''
111
- case reporter
112
- when 'ssl', 'file'
113
- host = ENV['SW_APM_COLLECTOR'] || ''
114
- when 'udp'
115
- host = ENV['SW_APM_COLLECTOR'] || "#{SolarWindsAPM::Config[:reporter_host]}:#{SolarWindsAPM::Config[:reporter_port]}"
116
- # TODO: decide what to do
117
- # ____ SolarWindsAPM::Config[:reporter_host] and
118
- # ____ SolarWindsAPM::Config[:reporter_port] were moved here from
119
- # ____ oboe_metal.rb and are not documented anywhere
120
- # ____ udp is for internal use only
121
- when 'null'
122
- host = ''
123
- end
113
+ host = case reporter
114
+ when 'ssl', 'file'
115
+ ENV['SW_APM_COLLECTOR'] || ''
116
+ else
117
+ ''
118
+ end
124
119
 
125
120
  host = sanitize_collector_uri(host) unless reporter == 'file'
126
121
  [reporter, host]
127
122
  end
128
123
 
129
124
  def read_and_validate_service_key
130
- service_key_checker = SolarWindsAPM::ServiceKeyChecker.new(@reporter)
125
+ service_key_checker = SolarWindsAPM::ServiceKeyChecker.new(@reporter, @lambda_env)
131
126
  service_key = service_key_checker.read_and_validate_service_key
132
- @service_name = service_key.split(':',2).last # instance variable used in testing
127
+ @service_name = service_key.split(':', 2).last # instance variable used in testing
133
128
  service_key
134
129
  end
135
130
 
@@ -145,8 +140,8 @@ module SolarWindsAPM
145
140
  proxy = ENV['SW_APM_PROXY'] || SolarWindsAPM::Config[:http_proxy] || ''
146
141
  return proxy if proxy == ''
147
142
 
148
- unless /http:\/\/.*:\d+$/.match?(proxy)
149
- SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] SW_APM_PROXY/http_proxy doesn't start with 'http://', #{proxy}"}
143
+ unless %r{http://.*:\d+$}.match?(proxy)
144
+ SolarWindsAPM.logger.error { "[#{self.class}/#{__method__}] SW_APM_PROXY/http_proxy doesn't start with 'http://', #{proxy}" }
150
145
  return '' # try without proxy, it may work, shouldn't crash but may not report
151
146
  end
152
147
 
@@ -156,13 +151,15 @@ module SolarWindsAPM
156
151
  def read_certificates
157
152
  certificate = ''
158
153
 
159
- file = appoptics_collector?? "#{__dir__}/cert/star.appoptics.com.issuer.crt" : ENV['SW_APM_TRUSTEDPATH']
154
+ file = appoptics_collector? ? "#{__dir__}/cert/star.appoptics.com.issuer.crt" : ENV.fetch('SW_APM_TRUSTEDPATH', nil)
160
155
  return certificate if file.nil? || file&.empty?
161
156
 
162
157
  begin
163
- certificate = File.open(file,"r").read
158
+ certificate = File.read(file)
164
159
  rescue StandardError => e
165
- SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] certificates: #{file} doesn't exist or caused by #{e.message}."}
160
+ SolarWindsAPM.logger.error do
161
+ "[#{self.class}/#{__method__}] certificates: #{file} doesn't exist or caused by #{e.message}."
162
+ end
166
163
  end
167
164
 
168
165
  certificate
@@ -176,7 +173,7 @@ module SolarWindsAPM
176
173
  allowed_uri = ['collector.appoptics.com', 'collector-stg.appoptics.com',
177
174
  'collector.appoptics.com:443', 'collector-stg.appoptics.com:443']
178
175
 
179
- (allowed_uri.include? ENV["SW_APM_COLLECTOR"])? true : false
176
+ (allowed_uri.include? ENV.fetch('SW_APM_COLLECTOR', nil))
180
177
  end
181
178
 
182
179
  def sanitize_collector_uri(uri)
@@ -186,9 +183,11 @@ module SolarWindsAPM
186
183
  sanitized_uri = ::URI.parse("http://#{uri}").host
187
184
  return sanitized_uri unless sanitized_uri.nil?
188
185
  rescue StandardError => e
189
- SolarWindsAPM.logger.error {"[#{self.class}/#{__method__}] uri for collector #{uri} is malformat. Error: #{e.message}"}
186
+ SolarWindsAPM.logger.error do
187
+ "[#{self.class}/#{__method__}] uri for collector #{uri} is malformat. Error: #{e.message}"
188
+ end
190
189
  end
191
- ""
190
+ ''
192
191
  end
193
192
 
194
193
  def determine_oboe_log_type
@@ -197,5 +196,14 @@ module SolarWindsAPM
197
196
  log_type = 4 if @debug_level == -1
198
197
  log_type
199
198
  end
199
+
200
+ def determine_lambda
201
+ if ENV['LAMBDA_TASK_ROOT'].to_s.empty? && ENV['AWS_LAMBDA_FUNCTION_NAME'].to_s.empty?
202
+ false
203
+ else
204
+ SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] lambda environment - LAMBDA_TASK_ROOT: #{ENV.fetch('LAMBDA_TASK_ROOT', nil)}; AWS_LAMBDA_FUNCTION_NAME: #{ENV.fetch('AWS_LAMBDA_FUNCTION_NAME', nil)}" }
205
+ true
206
+ end
207
+ end
200
208
  end
201
209
  end