instana 2.1.0 → 2.2.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: ca8072a81b44cce54a3a2db8ef236038fa4814226c714e88f12285ea952eede4
4
- data.tar.gz: 6f3b666908eb9442c1a8e6d3d1b9a332576bb818810a2c588df4de2232c1b65a
3
+ metadata.gz: 4a940d6791ca18a45f73ca949de0268cb4195ca269991d78683d1d89c3801919
4
+ data.tar.gz: c4a79bc94556b873ca0d2cb3cbe2b988914e2579d6fd124bbf4925142316dd85
5
5
  SHA512:
6
- metadata.gz: 84861f4a775983202c19731ce78302bf5e7cfd677591bf9b42014be4dee8b93efd1e6606910f756bbba495584a932ac860eb76cad5cf6539202d0588c3c01592
7
- data.tar.gz: ab26f124f9e087501046f56645649aed9b077ee656120d99ac1c375f44552f92345e338c1d5495c28e4a1959a7c459bf652511e13031912812a1acef003ca3f3
6
+ metadata.gz: f0c11ead2a6eb5e7cf4811a44b0edb6af0edbed588e712a080b5de07a704fbd28b91474e593b6342537459fe69cc0fcc60dfb83c18618e8e4ca5babea5096d6b
7
+ data.tar.gz: 5a22a83d6a6f930df189a914116398b372976d95f76ce86ae63b18c2f014eb4aa170a5415f5b6feb2f69b63bc9aff511d16e2d5e5bfb2682c369a0299cb5d2d3
@@ -122,6 +122,7 @@ module Instana
122
122
  long_instana_id: long_instana_id? ? sanitized_t : nil,
123
123
  external_trace_id: external_trace_id,
124
124
  external_state: @env['HTTP_TRACESTATE'],
125
+ external_trace_flags: context_from_trace_parent[:external_trace_flags],
125
126
  from_w3c: false
126
127
  }.reject { |_, v| v.nil? }
127
128
  end
@@ -140,6 +141,7 @@ module Instana
140
141
  external_state: @env['HTTP_TRACESTATE'],
141
142
  trace_id: trace_id,
142
143
  span_id: span_id,
144
+ external_trace_flags: matches['flags'],
143
145
  from_w3c: true
144
146
  }
145
147
  end
@@ -56,7 +56,8 @@ module Instana
56
56
  # without a backtrace (no exception)
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))
60
+ kv_payload[:http][:header] = extra_headers unless extra_headers&.empty?
60
61
  response
61
62
  rescue => e
62
63
  current_span&.record_exception(e)
@@ -10,7 +10,7 @@ module Instana
10
10
  @app = app
11
11
  end
12
12
 
13
- def call(env) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
13
+ def call(env)
14
14
  req = InstrumentedRequest.new(env)
15
15
  kvs = {
16
16
  http: req.request_tags
@@ -26,75 +26,14 @@ module Instana
26
26
  @trace_token = OpenTelemetry::Context.attach(trace_ctx)
27
27
  status, headers, response = @app.call(env)
28
28
 
29
- if ::Instana.tracer.tracing?
30
- unless req.correlation_data.empty?
31
- current_span[:crid] = req.correlation_data[:id]
32
- current_span[:crtp] = req.correlation_data[:type]
33
- end
34
-
35
- if !req.instana_ancestor.empty? && req.continuing_from_trace_parent?
36
- current_span[:ia] = req.instana_ancestor
37
- end
38
-
39
- if req.continuing_from_trace_parent?
40
- current_span[:tp] = true
41
- end
42
-
43
- if req.external_trace_id?
44
- current_span[:lt] = req.external_trace_id
45
- end
46
-
47
- if req.synthetic?
48
- current_span[:sy] = true
49
- end
50
-
51
- # In case some previous middleware returned a string status, make sure that we're dealing with
52
- # an integer. In Ruby nil.to_i, "asdfasdf".to_i will always return 0 from Ruby versions 1.8.7 and newer.
53
- # So if an 0 status is reported here, it indicates some other issue (e.g. no status from previous middleware)
54
- # See Rack Spec: https://www.rubydoc.info/github/rack/rack/file/SPEC#label-The+Status
55
- kvs[:http][:status] = status.to_i
56
-
57
- if status.to_i >= 500
58
- # Because of the 5xx response, we flag this span as errored but
59
- # without a backtrace (no exception)
60
- ::Instana.tracer.log_error(nil)
61
- end
62
-
63
- # If the framework instrumentation provides a path template,
64
- # pass it into the span here.
65
- # See: https://www.instana.com/docs/tracing/custom-best-practices/#path-templates-visual-grouping-of-http-endpoints
66
- kvs[:http][:path_tpl] = env['INSTANA_HTTP_PATH_TEMPLATE'] if env['INSTANA_HTTP_PATH_TEMPLATE']
67
-
68
- # Save the span context before the trace ends so we can place
69
- # them in the response headers in the ensure block
70
- trace_context = ::Instana.tracer.current_span.context
71
- end
72
-
29
+ trace_context = process_span_tags(req, current_span, kvs, status, env) if ::Instana.tracer.tracing?
30
+ merge_response_headers(kvs, headers)
73
31
  [status, headers, response]
74
32
  rescue Exception => e
75
33
  current_span.record_exception(e) if ::Instana.tracer.tracing?
76
34
  raise
77
35
  ensure
78
- if ::Instana.tracer.tracing?
79
- if headers
80
- # Set response headers; encode as hex string
81
- if trace_context.active?
82
- headers['X-Instana-T'] = trace_context.trace_id_header
83
- headers['X-Instana-S'] = trace_context.span_id_header
84
- headers['X-Instana-L'] = '1'
85
-
86
- headers['Tracestate'] = trace_context.trace_state_header
87
- else
88
- headers['X-Instana-L'] = '0'
89
- end
90
-
91
- headers['Traceparent'] = trace_context.trace_parent_header
92
- headers['Server-Timing'] = "intid;desc=#{trace_context.trace_id_header}"
93
- end
94
- current_span.set_tags(kvs)
95
- OpenTelemetry::Context.detach(@trace_token) if @trace_token
96
- current_span.finish
97
- end
36
+ finalize_trace(current_span, kvs, headers, trace_context) if ::Instana.tracer.tracing?
98
37
  end
99
38
 
100
39
  private
@@ -112,7 +51,8 @@ module Instana
112
51
  level: incoming_context[:level],
113
52
  baggage: {
114
53
  external_trace_id: incoming_context[:external_trace_id],
115
- external_state: incoming_context[:external_state]
54
+ external_state: incoming_context[:external_state],
55
+ external_trace_flags: incoming_context[:external_trace_flags]
116
56
  }
117
57
  )
118
58
  end
@@ -121,5 +61,85 @@ module Instana
121
61
  end
122
62
  parent_context
123
63
  end
64
+
65
+ def process_span_tags(req, current_span, kvs, status, env)
66
+ add_correlation_data(req, current_span)
67
+ add_trace_parent_data(req, current_span)
68
+ add_status_and_error(kvs, status)
69
+ add_path_template(kvs, env)
70
+
71
+ # Save the span context before the trace ends so we can place
72
+ # them in the response headers in the ensure block
73
+ ::Instana.tracer.current_span.context
74
+ end
75
+
76
+ def add_correlation_data(req, current_span)
77
+ return if req.correlation_data.empty?
78
+
79
+ current_span[:crid] = req.correlation_data[:id]
80
+ current_span[:crtp] = req.correlation_data[:type]
81
+ end
82
+
83
+ def add_trace_parent_data(req, current_span)
84
+ if !req.instana_ancestor.empty? && req.continuing_from_trace_parent?
85
+ current_span[:ia] = req.instana_ancestor
86
+ end
87
+
88
+ current_span[:tp] = true if req.continuing_from_trace_parent?
89
+ current_span[:lt] = req.external_trace_id if req.external_trace_id?
90
+ current_span[:sy] = true if req.synthetic?
91
+ end
92
+
93
+ def add_status_and_error(kvs, status)
94
+ # In case some previous middleware returned a string status, make sure that we're dealing with
95
+ # an integer. In Ruby nil.to_i, "asdfasdf".to_i will always return 0 from Ruby versions 1.8.7 and newer.
96
+ # So if an 0 status is reported here, it indicates some other issue (e.g. no status from previous middleware)
97
+ # See Rack Spec: https://www.rubydoc.info/github/rack/rack/file/SPEC#label-The+Status
98
+ kvs[:http][:status] = status.to_i
99
+
100
+ return unless status.to_i >= 500
101
+
102
+ # Because of the 5xx response, we flag this span as errored but
103
+ # without a backtrace (no exception)
104
+ ::Instana.tracer.log_error(nil)
105
+ end
106
+
107
+ def add_path_template(kvs, env)
108
+ # If the framework instrumentation provides a path template,
109
+ # pass it into the span here.
110
+ # See: https://www.instana.com/docs/tracing/custom-best-practices/#path-templates-visual-grouping-of-http-endpoints
111
+ kvs[:http][:path_tpl] = env['INSTANA_HTTP_PATH_TEMPLATE'] if env['INSTANA_HTTP_PATH_TEMPLATE']
112
+ end
113
+
114
+ def merge_response_headers(kvs, headers)
115
+ extra_response_headers = ::Instana::Util.extra_header_tags(headers)
116
+ if kvs[:http][:header].nil?
117
+ kvs[:http][:header] = extra_response_headers
118
+ else
119
+ kvs[:http][:header].merge!(extra_response_headers)
120
+ end
121
+ end
122
+
123
+ def finalize_trace(current_span, kvs, headers, trace_context)
124
+ set_response_headers(headers, trace_context) if headers
125
+ current_span.set_tags(kvs)
126
+ OpenTelemetry::Context.detach(@trace_token) if @trace_token
127
+ current_span.finish
128
+ end
129
+
130
+ def set_response_headers(headers, trace_context)
131
+ # Set response headers; encode as hex string
132
+ if trace_context.active?
133
+ headers['X-Instana-T'] = trace_context.trace_id_header
134
+ headers['X-Instana-S'] = trace_context.span_id_header
135
+ headers['X-Instana-L'] = '1'
136
+ headers['Tracestate'] = trace_context.trace_state_header
137
+ else
138
+ headers['X-Instana-L'] = '0'
139
+ end
140
+
141
+ headers['Traceparent'] = trace_context.trace_parent_header
142
+ headers['Server-Timing'] = "intid;desc=#{trace_context.trace_id_header}"
143
+ end
124
144
  end
125
145
  end
@@ -42,8 +42,16 @@ module Instana
42
42
  def trace_parent_header
43
43
  trace = (@baggage[:external_trace_id] || trace_id_header).rjust(32, '0')
44
44
  parent = span_id_header.rjust(16, '0')
45
- flags = @level == 1 ? "01" : "00"
46
-
45
+ flags = if @baggage[:external_trace_flags]
46
+ # Parse external flags as 8-bit hex, clear LSB, then set LSB based on level
47
+ external_flags = @baggage[:external_trace_flags].to_i(16) & 0xFE # Clear LSB
48
+ combined_flags = external_flags | (@level == 1 ? 1 : 0) # Set LSB based on level
49
+ combined_flags = [combined_flags, 0xFF].min # Cap at 8-bit max
50
+ format('%02x', combined_flags)
51
+ else
52
+ @level == 1 ? "03" : "02"
53
+ end
54
+ flags = "03" if flags > "03"
47
55
  "00-#{trace}-#{parent}-#{flags}"
48
56
  end
49
57
 
@@ -307,27 +307,6 @@ module Instana
307
307
  self.current_span = nil
308
308
  end
309
309
 
310
- # Creates a span that is active during the execution of the provided block.
311
- # The span is automatically closed when the block completes, whether it completes
312
- # normally or with an exception.
313
- #
314
- # @param name [String, Symbol] the name of the span to create
315
- # @param attributes [Hash, nil] optional attributes to set on the span
316
- # @param links [Array<Link>, nil] optional links to associate with the span
317
- # @param start_timestamp [Integer, nil] optional start time for the span in milliseconds
318
- # @param kind [Symbol, nil] optional span kind (e.g., :internal, :client, :server)
319
- #
320
- # @return [Object] the return value of the block
321
- #
322
- # @note This method is a wrapper around the parent class implementation and
323
- # will only create a span if the Instana agent is ready and tracing is enabled.
324
- #
325
- def in_span(name, attributes: nil, links: nil, start_timestamp: nil, kind: nil)
326
- return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled]
327
-
328
- super
329
- end
330
-
331
310
  # Starts a new span with the given parameters.
332
311
  #
333
312
  # @param name [String, Symbol] the name of the span to create (defaults to 'empty' if nil)
data/lib/instana/util.rb CHANGED
@@ -181,6 +181,19 @@ module Instana
181
181
  timeout -= (timeout_timestamp - start_time)
182
182
  timeout.positive? ? timeout : 0
183
183
  end
184
+
185
+ def extra_header_tags(req_res_headers)
186
+ return {} if req_res_headers.nil?
187
+ return nil unless ::Instana.agent.extra_headers
188
+
189
+ headers = {}
190
+
191
+ ::Instana.agent.extra_headers.each do |custom_header|
192
+ headers[custom_header.to_sym] = req_res_headers[custom_header] if req_res_headers.key?(custom_header)
193
+ end
194
+
195
+ headers
196
+ end
184
197
  end
185
198
  end
186
199
  end
@@ -2,6 +2,6 @@
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
4
  module Instana
5
- VERSION = "2.1.0"
5
+ VERSION = "2.2.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.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Giacomo Lombardo