instana 2.8.0 → 2.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80154e97601cca5ffd4537ecc7f664c97f27de2f62c0d72f0951d75749ddb5db
4
- data.tar.gz: 61db3e2ab8805be8ed97da7f0b9d0fd24927f8f68a98d7c82075d69859db217a
3
+ metadata.gz: 52139723659935eb43ab59f60e5c0f7305d860d5457c9545d395f9e4576fc604
4
+ data.tar.gz: 223dcdbe22af35ceed817411b850114f9cf3e7eb5fce3b3fc1b4f5ffa29c00e1
5
5
  SHA512:
6
- metadata.gz: 29c643217182cc683c2c770c72fe74d5d3acb84d39766f38363dbd250d6469d49bbf0d00fb9987af600af66b0afec944063d79bff17da91b8dd9f68d9a2eeb1a
7
- data.tar.gz: 262ab506d671a71f4eab35078717ff27fedaa46eebaa1cb8cc01eeb6e01a11ce30ea3fec7709b68db246b918bc822ad5d54e971271903a3c99c4c25ef9272433
6
+ metadata.gz: 0743a4a453182c90abb623189d4a6e5105cd03e3823b3b6cf9ee5269c80f14652d21bfc5481c914457a79a8a52633c718cfd1581d219122327996cb67c2b222f
7
+ data.tar.gz: 767f9eb2f714e83e045f27086061ef11ab3511574b8636c87740595f871a0051ccc977341e0e523f174d4f4d5a4575fbcd3d8b87ed1ab26b347198fbdb3d4d94
@@ -80,6 +80,10 @@ module Instana
80
80
  # W3C Trace Context Support
81
81
  @config[:w3c_trace_correlation] = ENV.fetch('INSTANA_DISABLE_W3C_TRACE_CORRELATION', nil).nil?
82
82
 
83
+ # HTTP exit span 4xx error classification (opt-in, default: off)
84
+ # Priority: env vars > agent config > default (false / [])
85
+ read_http_exit_config
86
+
83
87
  @config[:post_fork_proc] = proc { ::Instana.agent.spawn_background_thread }
84
88
 
85
89
  @config[:action_controller] = { :enabled => true }
@@ -142,6 +146,8 @@ module Instana
142
146
  read_span_stack_config_from_agent(tracing_config) if should_read_from_agent?(:back_trace)
143
147
  # Read OTLP configuration from agent if not already set from YAML or env
144
148
  read_otlp_config_from_agent(tracing_config) if should_read_from_agent?(:otlp)
149
+ # Read HTTP exit 4xx classification from agent if env vars did not already set it
150
+ read_http_exit_classification_from_agent(tracing_config) unless env_http_exit_classification_set?
145
151
  # Read span filtering configuration from agent
146
152
  ::Instana.span_filtering_config&.read_config_from_agent(discovery)
147
153
  rescue => e
@@ -256,6 +262,75 @@ module Instana
256
262
 
257
263
  private
258
264
 
265
+ # Read HTTP exit 4xx error classification config (wrapper — same pattern as read_span_stack_config / read_otlp_config)
266
+ def read_http_exit_config
267
+ @config[:http_exit_classify_all_4xx_as_errors] = false
268
+ @config[:http_exit_classify_as_errors] = []
269
+ read_http_exit_classification_from_env
270
+ end
271
+
272
+ # Read HTTP exit 4xx classification from environment variables (highest priority).
273
+ def read_http_exit_classification_from_env
274
+ classify_codes_raw = ENV.fetch('INSTANA_TRACING_HTTP_EXIT_CLASSIFY_AS_ERRORS', nil)
275
+ if classify_codes_raw
276
+ codes = classify_codes_raw.split(',').filter_map do |part|
277
+ part = part.strip
278
+ if part.match?(/\A\d+\z/)
279
+ code = part.to_i
280
+ if (400..499).cover?(code)
281
+ code
282
+ else
283
+ msg = "Ignoring out-of-range value in INSTANA_TRACING_HTTP_EXIT_CLASSIFY_AS_ERRORS: #{code}, must be 400-499"
284
+ ::Instana.logger.warn(msg)
285
+ nil
286
+ end
287
+ elsif part != ''
288
+ ::Instana.logger.warn("Ignoring non-integer value in INSTANA_TRACING_HTTP_EXIT_CLASSIFY_AS_ERRORS: #{part}")
289
+ nil
290
+ end
291
+ end
292
+ @config[:http_exit_classify_as_errors] = codes unless codes.empty?
293
+ else
294
+ classify_all_raw = ENV.fetch('INSTANA_TRACING_HTTP_EXIT_CLASSIFY_ALL_4XX_AS_ERRORS', nil)
295
+ @config[:http_exit_classify_all_4xx_as_errors] = truthy?(classify_all_raw) if classify_all_raw
296
+ end
297
+ end
298
+
299
+ # Return true if env vars have already configured HTTP exit 4xx classification.
300
+ def env_http_exit_classification_set?
301
+ ENV.key?('INSTANA_TRACING_HTTP_EXIT_CLASSIFY_AS_ERRORS') ||
302
+ ENV.key?('INSTANA_TRACING_HTTP_EXIT_CLASSIFY_ALL_4XX_AS_ERRORS')
303
+ end
304
+
305
+ # Read HTTP exit 4xx classification from agent discovery response (lowest priority).
306
+ # @param tracing_config [Hash] the tracing sub-hash from the discovery payload
307
+ def read_http_exit_classification_from_agent(tracing_config)
308
+ http_cfg = tracing_config['http']
309
+ return unless http_cfg.is_a?(Hash)
310
+
311
+ exit_cfg = http_cfg['exit']
312
+ return unless exit_cfg.is_a?(Hash)
313
+
314
+ if exit_cfg.key?('classify-as-errors')
315
+ codes = Array(exit_cfg['classify-as-errors']).filter_map do |code|
316
+ if code.is_a?(Integer) && (400..499).cover?(code)
317
+ code
318
+ else
319
+ ::Instana.logger.warn("Ignoring invalid value in agent config tracing.http.exit.classify-as-errors: #{code}")
320
+ nil
321
+ end
322
+ end
323
+ @config[:http_exit_classify_as_errors] = codes unless codes.empty?
324
+ elsif exit_cfg.key?('classify-all-4xx-as-errors')
325
+ val = exit_cfg['classify-all-4xx-as-errors']
326
+ if [true, false].include?(val)
327
+ @config[:http_exit_classify_all_4xx_as_errors] = val
328
+ else
329
+ ::Instana.logger.warn("Ignoring non-boolean value in agent config tracing.http.exit.classify-all-4xx-as-errors: #{val}")
330
+ end
331
+ end
332
+ end
333
+
259
334
  # Read OTLP configuration — precedence: YAML > env vars > defaults (agent handled separately)
260
335
  def read_otlp_config
261
336
  # Try YAML first
@@ -1,6 +1,8 @@
1
1
  # (c) Copyright IBM Corp. 2021
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
+ require 'instana/util'
5
+
4
6
  module Instana
5
7
  module Instrumentation
6
8
  class Excon < ::Excon::Middleware::Base
@@ -60,17 +62,18 @@ module Instana
60
62
  status = datum[:response][:status]
61
63
  end
62
64
 
63
- if status >= 500
64
- # Because of the 5xx response, we flag this span as errored but
65
- # without a backtrace (no exception)
65
+ http_kv = { status: status }
66
+ if ::Instana::Util.should_mark_http_exit_as_error?(status)
67
+ reason = ::Instana::Util.http_reason_phrase(status)
68
+ http_kv[:error] = reason ? "#{status} #{reason}" : status.to_s
66
69
  ::Instana.tracer.log_error(nil)
67
70
  end
68
71
 
69
72
  if datum[:pipeline] == true
70
73
  # Pickup context of this async span from datum[:instana_span]
71
- ::Instana.tracer.log_async_exit(:excon, { :http => {:status => status } }, datum[:instana_span])
74
+ ::Instana.tracer.log_async_exit(:excon, { :http => http_kv }, datum[:instana_span])
72
75
  else
73
- ::Instana.tracer.log_exit(:excon, { :http => {:status => status } })
76
+ ::Instana.tracer.log_exit(:excon, { :http => http_kv })
74
77
  end
75
78
  result
76
79
  end
@@ -2,6 +2,7 @@
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
4
  require 'net/http'
5
+ require 'instana/util'
5
6
 
6
7
  module Instana
7
8
  module Instrumentation
@@ -51,9 +52,8 @@ module Instana
51
52
  response = super(*args, &block)
52
53
 
53
54
  kv_payload[:http][:status] = response.code
54
- if response.code.to_i >= 500
55
- # Because of the 5xx response, we flag this span as errored but
56
- # without a backtrace (no exception)
55
+ if ::Instana::Util.should_mark_http_exit_as_error?(response.code.to_i)
56
+ kv_payload[:http][:error] = "#{response.code} #{response.message}"
57
57
  current_span.record_exception(nil)
58
58
  end
59
59
  extra_headers = ::Instana::Util.extra_header_tags(response)&.merge(::Instana::Util.extra_header_tags(request))
@@ -1,6 +1,8 @@
1
1
  # (c) Copyright IBM Corp. 2021
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
+ require 'instana/util'
5
+
4
6
  module Instana
5
7
  module Instrumentation
6
8
  module RestClientRequest
@@ -12,11 +14,21 @@ module Instana
12
14
 
13
15
  Trace.with_span(span) { super(&block) }
14
16
  rescue => e
15
- span.record_exception(e)
17
+ span.record_exception(e) if error_span?(e)
16
18
  raise
17
19
  ensure
18
20
  span.finish
19
21
  end
22
+
23
+ private
24
+
25
+ def error_span?(exception)
26
+ if exception.respond_to?(:response) && exception.response.respond_to?(:code)
27
+ ::Instana::Util.should_mark_http_exit_as_error?(exception.response.code.to_i)
28
+ else
29
+ true
30
+ end
31
+ end
20
32
  end
21
33
  end
22
34
  end
data/lib/instana/util.rb CHANGED
@@ -194,6 +194,41 @@ module Instana
194
194
 
195
195
  headers
196
196
  end
197
+
198
+ # Return true if an HTTP exit span with +status_code+ should be marked as errored.
199
+ #
200
+ # Rules (in priority order):
201
+ # 1. status >= 500 → always an error.
202
+ # 2. 400 <= status <= 499 and +config[:http_exit_classify_as_errors]+ is non-empty
203
+ # → error only if +status_code+ is in that list.
204
+ # 3. 400 <= status <= 499 and +config[:http_exit_classify_all_4xx_as_errors]+ is true
205
+ # → error for every 4xx code.
206
+ # 4. Otherwise → not an error.
207
+ #
208
+ # Entry (server/rack) spans must never be passed here; this helper is for exit spans only.
209
+ def should_mark_http_exit_as_error?(status_code)
210
+ return true if status_code >= 500
211
+
212
+ if (400..499).cover?(status_code)
213
+ codes = ::Instana.config[:http_exit_classify_as_errors]
214
+ return codes.include?(status_code) if codes&.any?
215
+
216
+ return ::Instana.config[:http_exit_classify_all_4xx_as_errors]
217
+ end
218
+
219
+ false
220
+ end
221
+
222
+ # Return the HTTP reason phrase for a numeric status code, or nil if unknown.
223
+ # Uses Ruby stdlib Net::HTTPResponse::CODE_TO_OBJ to derive the phrase from
224
+ # the response class name (e.g. Net::HTTPUnauthorized → "Unauthorized").
225
+ def http_reason_phrase(status_code)
226
+ require 'net/http'
227
+ klass = Net::HTTPResponse::CODE_TO_OBJ[status_code.to_s]
228
+ return nil unless klass
229
+
230
+ klass.name.sub('Net::HTTP', '').gsub(/([A-Z])/, ' \1').strip
231
+ end
197
232
  end
198
233
  end
199
234
  end
@@ -2,6 +2,6 @@
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
4
  module Instana
5
- VERSION = "2.8.0"
5
+ VERSION = "2.9.0"
6
6
  VERSION_FULL = "instana-#{VERSION}"
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instana
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Giacomo Lombardo
@@ -416,7 +416,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
416
416
  - !ruby/object:Gem::Version
417
417
  version: '0'
418
418
  requirements: []
419
- rubygems_version: 4.0.18
419
+ rubygems_version: 4.0.21
420
420
  specification_version: 4
421
421
  summary: Ruby Distributed Tracing & Metrics Sensor for Instana
422
422
  test_files: []