instana 1.11.5 → 1.13.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.
@@ -32,6 +32,8 @@ if defined?(::Net::HTTP) && ::Instana.config[:nethttp][:enabled]
32
32
  kv_payload[:http][:url] = "http://#{@address}:#{@port}#{request.path}"
33
33
  end
34
34
  end
35
+
36
+ kv_payload[:http][:url] = ::Instana.secrets.remove_from_query(kv_payload[:http][:url])
35
37
 
36
38
  # The core call
37
39
  response = request_without_instana(*args, &block)
@@ -8,8 +8,9 @@ module Instana
8
8
  @app = app
9
9
  end
10
10
 
11
- def call(env)
12
- kvs = { :http => {} }
11
+ def collect_kvs(env)
12
+ kvs = {}
13
+ kvs[:http] = {}
13
14
  kvs[:http][:method] = env['REQUEST_METHOD']
14
15
  kvs[:http][:url] = ::CGI.unescape(env['PATH_INFO'])
15
16
 
@@ -37,15 +38,27 @@ module Instana
37
38
  end
38
39
  }
39
40
  end
41
+ return kvs
42
+ end
40
43
 
44
+ def call(env)
41
45
  # Check incoming context
42
46
  incoming_context = {}
43
47
  if env.key?('HTTP_X_INSTANA_T')
44
48
  incoming_context[:trace_id] = ::Instana::Util.header_to_id(env['HTTP_X_INSTANA_T'])
45
49
  incoming_context[:span_id] = ::Instana::Util.header_to_id(env['HTTP_X_INSTANA_S']) if env.key?('HTTP_X_INSTANA_S')
46
50
  incoming_context[:level] = env['HTTP_X_INSTANA_L'] if env.key?('HTTP_X_INSTANA_L')
51
+
52
+ # Honor X-Instana-L
53
+ if incoming_context[:level] and incoming_context[:level].length > 0
54
+ if incoming_context[:level][0] == "0"
55
+ return @app.call(env)
56
+ end
57
+ end
47
58
  end
48
59
 
60
+ kvs = collect_kvs(env)
61
+
49
62
  ::Instana.tracer.log_start_or_continue(:rack, {}, incoming_context)
50
63
 
51
64
  status, headers, response = @app.call(env)
@@ -63,6 +76,11 @@ module Instana
63
76
  ::Instana.tracer.log_error(nil)
64
77
  end
65
78
 
79
+ # If the framework instrumentation provides a path template,
80
+ # pass it into the span here.
81
+ # See: https://www.instana.com/docs/tracing/custom-best-practices/#path-templates-visual-grouping-of-http-endpoints
82
+ kvs[:http][:path_tpl] = env['INSTANA_HTTP_PATH_TEMPLATE'] if env['INSTANA_HTTP_PATH_TEMPLATE']
83
+
66
84
  # Save the IDs before the trace ends so we can place
67
85
  # them in the response headers in the ensure block
68
86
  trace_id = ::Instana.tracer.current_span.trace_id
@@ -78,8 +96,10 @@ module Instana
78
96
  # Set reponse headers; encode as hex string
79
97
  headers['X-Instana-T'] = ::Instana::Util.id_to_header(trace_id)
80
98
  headers['X-Instana-S'] = ::Instana::Util.id_to_header(span_id)
99
+ headers['X-Instana-L'] = '1'
100
+ headers['Server-Timing'] = "intid;desc=#{::Instana::Util.id_to_header(trace_id)}"
101
+ ::Instana.tracer.log_end(:rack, kvs)
81
102
  end
82
- ::Instana.tracer.log_end(:rack, kvs)
83
103
  end
84
104
  end
85
105
  end
@@ -2,28 +2,31 @@ if defined?(::Redis) && ::Instana.config[:redis][:enabled]
2
2
  ::Redis::Client.class_eval do
3
3
  def call_with_instana(*args, &block)
4
4
  kv_payload = { redis: {} }
5
+ dnt_spans = [:redis, :'resque-client', :'sidekiq-client']
5
6
 
6
- if !Instana.tracer.tracing? || ::Instana.tracer.tracing_span?(:redis)
7
+ if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name)
7
8
  return call_without_instana(*args, &block)
8
9
  end
9
10
 
10
- ::Instana.tracer.log_entry(:redis)
11
-
12
11
  begin
13
- kv_payload[:redis][:connection] = "#{self.host}:#{self.port}"
14
- kv_payload[:redis][:db] = db.to_s
15
- kv_payload[:redis][:command] = args[0][0].to_s.upcase
16
- rescue
17
- nil
18
- end
12
+ ::Instana.tracer.log_entry(:redis)
19
13
 
20
- call_without_instana(*args, &block)
21
- rescue => e
22
- ::Instana.tracer.log_info({ redis: {error: true} })
23
- ::Instana.tracer.log_error(e)
24
- raise
25
- ensure
26
- ::Instana.tracer.log_exit(:redis, kv_payload)
14
+ begin
15
+ kv_payload[:redis][:connection] = "#{self.host}:#{self.port}"
16
+ kv_payload[:redis][:db] = db.to_s
17
+ kv_payload[:redis][:command] = args[0][0].to_s.upcase
18
+ rescue
19
+ nil
20
+ end
21
+
22
+ call_without_instana(*args, &block)
23
+ rescue => e
24
+ ::Instana.tracer.log_info({ redis: {error: true} })
25
+ ::Instana.tracer.log_error(e)
26
+ raise
27
+ ensure
28
+ ::Instana.tracer.log_exit(:redis, kv_payload)
29
+ end
27
30
  end
28
31
 
29
32
  ::Instana.logger.debug "Instrumenting Redis"
@@ -33,29 +36,32 @@ if defined?(::Redis) && ::Instana.config[:redis][:enabled]
33
36
 
34
37
  def call_pipeline_with_instana(*args, &block)
35
38
  kv_payload = { redis: {} }
39
+ dnt_spans = [:redis, :'resque-client', :'sidekiq-client']
36
40
 
37
- if !Instana.tracer.tracing? || ::Instana.tracer.tracing_span?(:redis)
41
+ if !Instana.tracer.tracing? || dnt_spans.include?(::Instana.tracer.current_span.name)
38
42
  return call_pipeline_without_instana(*args, &block)
39
43
  end
40
44
 
41
- ::Instana.tracer.log_entry(:redis)
42
-
43
- pipeline = args.first
44
45
  begin
45
- kv_payload[:redis][:connection] = "#{self.host}:#{self.port}"
46
- kv_payload[:redis][:db] = db.to_s
47
- kv_payload[:redis][:command] = pipeline.is_a?(::Redis::Pipeline::Multi) ? 'MULTI' : 'PIPELINE'
48
- rescue
49
- nil
50
- end
46
+ ::Instana.tracer.log_entry(:redis)
51
47
 
52
- call_pipeline_without_instana(*args, &block)
53
- rescue => e
54
- ::Instana.tracer.log_info({ redis: {error: true} })
55
- ::Instana.tracer.log_error(e)
56
- raise
57
- ensure
58
- ::Instana.tracer.log_exit(:redis, kv_payload)
48
+ pipeline = args.first
49
+ begin
50
+ kv_payload[:redis][:connection] = "#{self.host}:#{self.port}"
51
+ kv_payload[:redis][:db] = db.to_s
52
+ kv_payload[:redis][:command] = pipeline.is_a?(::Redis::Pipeline::Multi) ? 'MULTI' : 'PIPELINE'
53
+ rescue
54
+ nil
55
+ end
56
+
57
+ call_pipeline_without_instana(*args, &block)
58
+ rescue => e
59
+ ::Instana.tracer.log_info({ redis: {error: true} })
60
+ ::Instana.tracer.log_error(e)
61
+ raise
62
+ ensure
63
+ ::Instana.tracer.log_exit(:redis, kv_payload)
64
+ end
59
65
  end
60
66
 
61
67
  alias call_pipeline_without_instana call_pipeline
@@ -0,0 +1,42 @@
1
+ require 'uri'
2
+ require 'cgi'
3
+
4
+ module Instana
5
+ class Secrets
6
+ def remove_from_query(str, secret_values = Instana.agent.secret_values)
7
+ return str unless secret_values
8
+
9
+ url = URI(str)
10
+ params = CGI.parse(url.query)
11
+
12
+ redacted = params.map do |k, v|
13
+ needs_redaction = secret_values['list']
14
+ .any? { |t| matcher(secret_values['matcher']).(t,k) }
15
+ [k, needs_redaction ? '<redacted>' : v]
16
+ end
17
+
18
+ url.query = URI.encode_www_form(redacted)
19
+ CGI.unescape(url.to_s)
20
+ end
21
+
22
+ private
23
+
24
+ def matcher(name)
25
+ case name
26
+ when 'equals-ignore-case'
27
+ ->(expected, actual) { expected.casecmp(actual) == 0 }
28
+ when 'equals'
29
+ ->(expected, actual) { (expected <=> actual) == 0 }
30
+ when 'contains-ignore-case'
31
+ ->(expected, actual) { actual.downcase.include?(expected) }
32
+ when 'contains'
33
+ ->(expected, actual) { actual.include?(expected) }
34
+ when 'regex'
35
+ ->(expected, actual) { !Regexp.new(expected).match(actual).nil? }
36
+ else
37
+ ::Instana.logger.warn("Matcher #{name} is not supported.")
38
+ lambda { false }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -4,6 +4,7 @@ require "instana/base"
4
4
  require "instana/config"
5
5
  require "instana/agent"
6
6
  require "instana/collector"
7
+ require "instana/secrets"
7
8
  require "instana/tracer"
8
9
  require "instana/tracing/processor"
9
10
  require "instana/instrumentation"
@@ -7,14 +7,15 @@ module Instana
7
7
  def setup_environment
8
8
  # Set defaults if not set
9
9
  ENV['MEMCACHED_HOST'] ||= '127.0.0.1:11211'
10
- ENV['TRAVIS_PSQL_HOST'] ||= "127.0.0.1"
11
- ENV['TRAVIS_PSQL_USER'] ||= "postgres"
10
+ ENV['POSTGRES_HOST'] ||= "127.0.0.1"
11
+ ENV['POSTGRES_USER'] ||= "stan"
12
+ ENV['POSTGRES_PASSWORD'] ||= "stanlikesdata"
12
13
  ENV['TRAVIS_MYSQL_HOST'] ||= "127.0.0.1"
13
14
  ENV['TRAVIS_MYSQL_USER'] ||= "root"
14
15
 
15
16
  if !ENV.key?('DATABASE_URL')
16
17
  if ENV['DB_FLAVOR'] == 'postgresql'
17
- ENV['DATABASE_URL'] = "postgresql://#{ENV['TRAVIS_PSQL_USER']}:#{ENV['TRAVIS_PSQL_PASS']}@#{ENV['TRAVIS_PSQL_HOST']}:5432/travis_ci_test"
18
+ ENV['DATABASE_URL'] = "postgresql://#{ENV['POSTGRES_USER']}:#{ENV['POSTGRES_PASSWORD']}@#{ENV['POSTGRES_HOST']}:5432/#{ENV['POSTGRES_USER']}"
18
19
  elsif ENV['DB_FLAVOR'] == 'mysql'
19
20
  ENV['DATABASE_URL'] = "mysql://#{ENV['TRAVIS_MYSQL_USER']}:#{ENV['TRAVIS_MYSQL_PASS']}@#{ENV['TRAVIS_MYSQL_HOST']}:3306/travis_ci_test"
20
21
  else
@@ -303,6 +303,15 @@ module Instana
303
303
  # a String, Numeric, or Boolean it will be encoded with to_s
304
304
  #
305
305
  def set_tag(key, value)
306
+ if ![Symbol, String].include?(key.class)
307
+ key = key.to_s
308
+ end
309
+
310
+ # If <value> is not a Symbol, String, Array, Hash or Numeric - convert to string
311
+ if ![Symbol, String, Array, TrueClass, FalseClass, Hash].include?(value.class) && !value.is_a?(Numeric)
312
+ value = value.to_s
313
+ end
314
+
306
315
  if custom?
307
316
  @data[:data][:sdk][:custom] ||= {}
308
317
  @data[:data][:sdk][:custom][:tags] ||= {}
@@ -1,4 +1,4 @@
1
1
  module Instana
2
- VERSION = "1.11.5"
2
+ VERSION = "1.13.0"
3
3
  VERSION_FULL = "instana-#{VERSION}"
4
4
  end
@@ -7,6 +7,10 @@ Cuba.define do
7
7
  on "hello" do
8
8
  res.write "Hello Instana!"
9
9
  end
10
+
11
+ on "greet/:name" do |name|
12
+ res.write "Hello, #{name}"
13
+ end
10
14
 
11
15
  on root do
12
16
  res.redirect '/hello'
@@ -6,5 +6,8 @@ class InstanaRodaApp < Roda
6
6
  r.get "hello" do
7
7
  "Hello Roda + Instana"
8
8
  end
9
+ r.get "greet", String do |name|
10
+ "Hello, #{name}!"
11
+ end
9
12
  end
10
13
  end
@@ -2,4 +2,8 @@ class InstanaSinatraApp < ::Sinatra::Base
2
2
  get '/' do
3
3
  "Hello Sinatra!"
4
4
  end
5
+
6
+ get '/greet/:name' do
7
+ "Hello, #{params[:name]}!"
8
+ end
5
9
  end
@@ -10,28 +10,12 @@ class ConfigTest < Minitest::Test
10
10
  assert_equal '127.0.0.1', ::Instana.config[:agent_host]
11
11
  assert_equal 42699, ::Instana.config[:agent_port]
12
12
 
13
- assert ::Instana.config[:enabled]
14
13
  assert ::Instana.config[:tracing][:enabled]
15
14
  assert ::Instana.config[:metrics][:enabled]
16
15
 
17
16
  ::Instana.config[:metrics].each do |k, v|
17
+ next unless v.is_a? Hash
18
18
  assert_equal true, ::Instana.config[:metrics][k].key?(:enabled)
19
19
  end
20
20
  end
21
-
22
- def test_that_global_affects_children
23
- # Disabling the gem should explicitly disable
24
- # metrics and tracing flags
25
- ::Instana.config[:enabled] = false
26
-
27
- assert_equal false, ::Instana.config[:tracing][:enabled]
28
- assert_equal false, ::Instana.config[:metrics][:enabled]
29
-
30
- # Enabling the gem should explicitly enable
31
- # metrics and tracing flags
32
- ::Instana.config[:enabled] = true
33
-
34
- assert_equal ::Instana.config[:tracing][:enabled]
35
- assert_equal ::Instana.config[:metrics][:enabled]
36
- end
37
21
  end
@@ -1,4 +1,3 @@
1
-
2
1
  if defined?(::Cuba)
3
2
  require 'test_helper'
4
3
  require File.expand_path(File.dirname(__FILE__) + '/../apps/cuba')
@@ -40,5 +39,19 @@ if defined?(::Cuba)
40
39
  assert first_span[:data][:http].key?(:host)
41
40
  assert_equal "example.org", first_span[:data][:http][:host]
42
41
  end
42
+
43
+ def test_path_template
44
+ clear_all!
45
+
46
+ r = get '/greet/instana'
47
+ assert last_response.ok?
48
+
49
+ spans = ::Instana.processor.queued_spans
50
+ assert_equal 1, spans.count
51
+
52
+ first_span = spans.first
53
+ assert_equal :rack, first_span[:n]
54
+ assert_equal '/greet/{name}', first_span[:data][:http][:path_tpl]
55
+ end
43
56
  end
44
57
  end
@@ -5,16 +5,22 @@ require "instana/rack"
5
5
 
6
6
  class RackTest < Minitest::Test
7
7
  include Rack::Test::Methods
8
+
9
+ class PathTemplateApp
10
+ def call(env)
11
+ env['INSTANA_HTTP_PATH_TEMPLATE'] = 'sample_template'
12
+ [200, {}, ['Ok']]
13
+ end
14
+ end
8
15
 
9
16
  def app
10
- @app = Rack::Builder.new {
17
+ @app = Rack::Builder.new do
11
18
  use Rack::CommonLogger
12
19
  use Rack::ShowExceptions
13
20
  use Instana::Rack
14
- map "/mrlobster" do
15
- run Rack::Lobster.new
16
- end
17
- }
21
+ map("/mrlobster") { run Rack::Lobster.new }
22
+ map("/path_tpl") { run PathTemplateApp.new }
23
+ end
18
24
  end
19
25
 
20
26
  def test_basic_get
@@ -29,23 +35,33 @@ class RackTest < Minitest::Test
29
35
  # Span validation
30
36
  assert_equal 1, spans.count
31
37
 
32
- first_span = spans.first
33
- assert_equal :rack, first_span[:n]
34
- assert first_span.key?(:data)
35
- assert first_span[:data].key?(:http)
36
- assert_equal "GET", first_span[:data][:http][:method]
37
- assert_equal "/mrlobster", first_span[:data][:http][:url]
38
- assert_equal 200, first_span[:data][:http][:status]
39
- assert_equal 'example.org', first_span[:data][:http][:host]
40
- assert first_span.key?(:f)
41
- assert first_span[:f].key?(:e)
42
- assert first_span[:f].key?(:h)
43
- assert_equal ::Instana.agent.agent_uuid, first_span[:f][:h]
38
+ rack_span = spans.first
39
+ assert_equal :rack, rack_span[:n]
40
+
41
+ assert last_response.headers.key?("X-Instana-T")
42
+ assert last_response.headers["X-Instana-T"] == ::Instana::Util.id_to_header(rack_span[:t])
43
+ assert last_response.headers.key?("X-Instana-S")
44
+ assert last_response.headers["X-Instana-S"] == ::Instana::Util.id_to_header(rack_span[:s])
45
+ assert last_response.headers.key?("X-Instana-L")
46
+ assert last_response.headers["X-Instana-L"] == '1'
47
+ assert last_response.headers.key?("Server-Timing")
48
+ assert last_response.headers["Server-Timing"] == "intid;desc=#{::Instana::Util.id_to_header(rack_span[:t])}"
49
+
50
+ assert rack_span.key?(:data)
51
+ assert rack_span[:data].key?(:http)
52
+ assert_equal "GET", rack_span[:data][:http][:method]
53
+ assert_equal "/mrlobster", rack_span[:data][:http][:url]
54
+ assert_equal 200, rack_span[:data][:http][:status]
55
+ assert_equal 'example.org', rack_span[:data][:http][:host]
56
+ assert rack_span.key?(:f)
57
+ assert rack_span[:f].key?(:e)
58
+ assert rack_span[:f].key?(:h)
59
+ assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
44
60
 
45
61
  # Backtrace fingerprint validation
46
- assert first_span.key?(:stack)
47
- assert_equal 2, first_span[:stack].count
48
- refute_nil first_span[:stack].first[:c].match(/instana\/instrumentation\/rack.rb/)
62
+ assert rack_span.key?(:stack)
63
+ assert_equal 2, rack_span[:stack].count
64
+ refute_nil rack_span[:stack].first[:c].match(/instana\/instrumentation\/rack.rb/)
49
65
 
50
66
  # Restore to default
51
67
  ::Instana.config[:collect_backtraces] = false
@@ -63,8 +79,8 @@ class RackTest < Minitest::Test
63
79
  # Span validation
64
80
  assert_equal 1, spans.count
65
81
 
66
- first_span = spans.first
67
- assert_equal 'WalterBishop', first_span[:data][:service]
82
+ rack_span = spans.first
83
+ assert_equal 'WalterBishop', rack_span[:data][:service]
68
84
 
69
85
  ENV.delete('INSTANA_SERVICE_NAME')
70
86
  end
@@ -78,17 +94,27 @@ class RackTest < Minitest::Test
78
94
 
79
95
  # Span validation
80
96
  assert_equal 1, spans.count
81
- first_span = spans.first
82
- assert_equal :rack, first_span[:n]
83
- assert first_span.key?(:data)
84
- assert first_span[:data].key?(:http)
85
- assert_equal "POST", first_span[:data][:http][:method]
86
- assert_equal "/mrlobster", first_span[:data][:http][:url]
87
- assert_equal 200, first_span[:data][:http][:status]
88
- assert first_span.key?(:f)
89
- assert first_span[:f].key?(:e)
90
- assert first_span[:f].key?(:h)
91
- assert_equal ::Instana.agent.agent_uuid, first_span[:f][:h]
97
+ rack_span = spans.first
98
+ assert_equal :rack, rack_span[:n]
99
+
100
+ assert last_response.headers.key?("X-Instana-T")
101
+ assert last_response.headers["X-Instana-T"] == ::Instana::Util.id_to_header(rack_span[:t])
102
+ assert last_response.headers.key?("X-Instana-S")
103
+ assert last_response.headers["X-Instana-S"] == ::Instana::Util.id_to_header(rack_span[:s])
104
+ assert last_response.headers.key?("X-Instana-L")
105
+ assert last_response.headers["X-Instana-L"] == '1'
106
+ assert last_response.headers.key?("Server-Timing")
107
+ assert last_response.headers["Server-Timing"] == "intid;desc=#{::Instana::Util.id_to_header(rack_span[:t])}"
108
+
109
+ assert rack_span.key?(:data)
110
+ assert rack_span[:data].key?(:http)
111
+ assert_equal "POST", rack_span[:data][:http][:method]
112
+ assert_equal "/mrlobster", rack_span[:data][:http][:url]
113
+ assert_equal 200, rack_span[:data][:http][:status]
114
+ assert rack_span.key?(:f)
115
+ assert rack_span[:f].key?(:e)
116
+ assert rack_span[:f].key?(:h)
117
+ assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
92
118
  end
93
119
 
94
120
  def test_basic_put
@@ -100,17 +126,27 @@ class RackTest < Minitest::Test
100
126
 
101
127
  # Span validation
102
128
  assert_equal 1, spans.count
103
- first_span = spans.first
104
- assert_equal :rack, first_span[:n]
105
- assert first_span.key?(:data)
106
- assert first_span[:data].key?(:http)
107
- assert_equal "PUT", first_span[:data][:http][:method]
108
- assert_equal "/mrlobster", first_span[:data][:http][:url]
109
- assert_equal 200, first_span[:data][:http][:status]
110
- assert first_span.key?(:f)
111
- assert first_span[:f].key?(:e)
112
- assert first_span[:f].key?(:h)
113
- assert_equal ::Instana.agent.agent_uuid, first_span[:f][:h]
129
+ rack_span = spans.first
130
+ assert_equal :rack, rack_span[:n]
131
+
132
+ assert last_response.headers.key?("X-Instana-T")
133
+ assert last_response.headers["X-Instana-T"] == ::Instana::Util.id_to_header(rack_span[:t])
134
+ assert last_response.headers.key?("X-Instana-S")
135
+ assert last_response.headers["X-Instana-S"] == ::Instana::Util.id_to_header(rack_span[:s])
136
+ assert last_response.headers.key?("X-Instana-L")
137
+ assert last_response.headers["X-Instana-L"] == '1'
138
+ assert last_response.headers.key?("Server-Timing")
139
+ assert last_response.headers["Server-Timing"] == "intid;desc=#{::Instana::Util.id_to_header(rack_span[:t])}"
140
+
141
+ assert rack_span.key?(:data)
142
+ assert rack_span[:data].key?(:http)
143
+ assert_equal "PUT", rack_span[:data][:http][:method]
144
+ assert_equal "/mrlobster", rack_span[:data][:http][:url]
145
+ assert_equal 200, rack_span[:data][:http][:status]
146
+ assert rack_span.key?(:f)
147
+ assert rack_span[:f].key?(:e)
148
+ assert rack_span[:f].key?(:h)
149
+ assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
114
150
  end
115
151
 
116
152
  def test_context_continuation
@@ -125,23 +161,33 @@ class RackTest < Minitest::Test
125
161
 
126
162
  # Span validation
127
163
  assert_equal 1, spans.count
128
- first_span = spans.first
129
- assert_equal :rack, first_span[:n]
130
- assert first_span.key?(:data)
131
- assert first_span[:data].key?(:http)
132
- assert_equal "GET", first_span[:data][:http][:method]
133
- assert_equal "/mrlobster", first_span[:data][:http][:url]
134
- assert_equal 200, first_span[:data][:http][:status]
135
- assert first_span.key?(:f)
136
- assert first_span[:f].key?(:e)
137
- assert first_span[:f].key?(:h)
138
- assert_equal ::Instana.agent.agent_uuid, first_span[:f][:h]
164
+ rack_span = spans.first
165
+ assert_equal :rack, rack_span[:n]
166
+
167
+ assert last_response.headers.key?("X-Instana-T")
168
+ assert last_response.headers["X-Instana-T"] == ::Instana::Util.id_to_header(rack_span[:t])
169
+ assert last_response.headers.key?("X-Instana-S")
170
+ assert last_response.headers["X-Instana-S"] == ::Instana::Util.id_to_header(rack_span[:s])
171
+ assert last_response.headers.key?("X-Instana-L")
172
+ assert last_response.headers["X-Instana-L"] == '1'
173
+ assert last_response.headers.key?("Server-Timing")
174
+ assert last_response.headers["Server-Timing"] == "intid;desc=#{::Instana::Util.id_to_header(rack_span[:t])}"
175
+
176
+ assert rack_span.key?(:data)
177
+ assert rack_span[:data].key?(:http)
178
+ assert_equal "GET", rack_span[:data][:http][:method]
179
+ assert_equal "/mrlobster", rack_span[:data][:http][:url]
180
+ assert_equal 200, rack_span[:data][:http][:status]
181
+ assert rack_span.key?(:f)
182
+ assert rack_span[:f].key?(:e)
183
+ assert rack_span[:f].key?(:h)
184
+ assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
139
185
 
140
186
  # Context validation
141
187
  # The first span should have the passed in trace ID
142
188
  # and specify the passed in span ID as it's parent.
143
- assert_equal 1234, first_span[:t]
144
- assert_equal 4321, first_span[:p]
189
+ assert_equal 1234, rack_span[:t]
190
+ assert_equal 4321, rack_span[:p]
145
191
  end
146
192
 
147
193
  def test_instana_response_headers
@@ -181,20 +227,34 @@ class RackTest < Minitest::Test
181
227
 
182
228
  # Span validation
183
229
  assert_equal 1, spans.count
184
- first_span = spans.first
230
+ rack_span = spans.first
185
231
 
186
- assert first_span[:data][:http].key?(:header)
187
- assert first_span[:data][:http][:header].key?(:"X-Capture-This")
188
- assert !first_span[:data][:http][:header].key?(:"X-Capture-That")
189
- assert_equal "ThereYouGo", first_span[:data][:http][:header][:"X-Capture-This"]
232
+ assert rack_span[:data][:http].key?(:header)
233
+ assert rack_span[:data][:http][:header].key?(:"X-Capture-This")
234
+ assert !rack_span[:data][:http][:header].key?(:"X-Capture-That")
235
+ assert_equal "ThereYouGo", rack_span[:data][:http][:header][:"X-Capture-This"]
190
236
 
191
237
  # Backtrace fingerprint validation
192
- assert first_span.key?(:stack)
193
- assert_equal 2, first_span[:stack].count
194
- refute_nil first_span[:stack].first[:c].match(/instana\/instrumentation\/rack.rb/)
238
+ assert rack_span.key?(:stack)
239
+ assert_equal 2, rack_span[:stack].count
240
+ refute_nil rack_span[:stack].first[:c].match(/instana\/instrumentation\/rack.rb/)
195
241
 
196
242
  # Restore to default
197
243
  ::Instana.config[:collect_backtraces] = false
198
244
  ::Instana.agent.extra_headers = nil
199
245
  end
246
+
247
+ def test_capture_http_path_template
248
+ clear_all!
249
+
250
+ get '/path_tpl'
251
+ assert last_response.ok?
252
+
253
+ spans = ::Instana.processor.queued_spans
254
+ assert_equal 1, spans.length
255
+
256
+ rack_span = spans.first
257
+ assert_equal :rack, rack_span[:n]
258
+ assert_equal 'sample_template', rack_span[:data][:http][:path_tpl]
259
+ end
200
260
  end