instana 1.11.6 → 1.193.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of instana might be problematic. Click here for more details.

Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +168 -0
  3. data/Rakefile +26 -37
  4. data/gemfiles/libraries.gemfile +2 -0
  5. data/lib/instana/agent.rb +6 -0
  6. data/lib/instana/base.rb +2 -0
  7. data/lib/instana/config.rb +11 -0
  8. data/lib/instana/frameworks/cuba.rb +33 -0
  9. data/lib/instana/frameworks/instrumentation/action_controller.rb +11 -0
  10. data/lib/instana/frameworks/instrumentation/mysql2_adapter.rb +7 -1
  11. data/lib/instana/frameworks/instrumentation/mysql_adapter.rb +7 -1
  12. data/lib/instana/frameworks/instrumentation/postgresql_adapter.rb +23 -5
  13. data/lib/instana/frameworks/roda.rb +41 -0
  14. data/lib/instana/frameworks/sinatra.rb +17 -0
  15. data/lib/instana/instrumentation/excon.rb +1 -1
  16. data/lib/instana/instrumentation/graphql.rb +77 -0
  17. data/lib/instana/instrumentation/net-http.rb +2 -0
  18. data/lib/instana/instrumentation/rack.rb +23 -3
  19. data/lib/instana/secrets.rb +42 -0
  20. data/lib/instana/setup.rb +1 -0
  21. data/lib/instana/test.rb +4 -3
  22. data/lib/instana/tracing/span.rb +23 -10
  23. data/lib/instana/version.rb +1 -1
  24. data/test/apps/cuba.rb +4 -0
  25. data/test/apps/roda.rb +3 -0
  26. data/test/apps/sinatra.rb +4 -0
  27. data/test/config_test.rb +1 -17
  28. data/test/frameworks/cuba_test.rb +14 -1
  29. data/test/frameworks/rack_test.rb +121 -69
  30. data/test/frameworks/rails/actioncontroller_test.rb +12 -0
  31. data/test/frameworks/rails/activerecord_test.rb +80 -28
  32. data/test/frameworks/roda_test.rb +14 -0
  33. data/test/frameworks/sinatra_test.rb +37 -15
  34. data/test/instrumentation/excon_test.rb +0 -2
  35. data/test/instrumentation/graphql_test.rb +116 -0
  36. data/test/instrumentation/grpc_test.rb +1 -1
  37. data/test/instrumentation/redis_test.rb +10 -0
  38. data/test/secrets_test.rb +73 -0
  39. data/test/tracing/tracer_test.rb +31 -1
  40. metadata +10 -6
  41. data/.travis.yml +0 -43
  42. data/test/tracing/trace_test.rb +0 -67
@@ -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,29 @@ 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]
44
-
45
- # 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/)
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]
60
+ assert !rack_span.key?(:stack)
49
61
 
50
62
  # Restore to default
51
63
  ::Instana.config[:collect_backtraces] = false
@@ -63,8 +75,8 @@ class RackTest < Minitest::Test
63
75
  # Span validation
64
76
  assert_equal 1, spans.count
65
77
 
66
- first_span = spans.first
67
- assert_equal 'WalterBishop', first_span[:data][:service]
78
+ rack_span = spans.first
79
+ assert_equal 'WalterBishop', rack_span[:data][:service]
68
80
 
69
81
  ENV.delete('INSTANA_SERVICE_NAME')
70
82
  end
@@ -78,17 +90,27 @@ class RackTest < Minitest::Test
78
90
 
79
91
  # Span validation
80
92
  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]
93
+ rack_span = spans.first
94
+ assert_equal :rack, rack_span[:n]
95
+
96
+ assert last_response.headers.key?("X-Instana-T")
97
+ assert last_response.headers["X-Instana-T"] == ::Instana::Util.id_to_header(rack_span[:t])
98
+ assert last_response.headers.key?("X-Instana-S")
99
+ assert last_response.headers["X-Instana-S"] == ::Instana::Util.id_to_header(rack_span[:s])
100
+ assert last_response.headers.key?("X-Instana-L")
101
+ assert last_response.headers["X-Instana-L"] == '1'
102
+ assert last_response.headers.key?("Server-Timing")
103
+ assert last_response.headers["Server-Timing"] == "intid;desc=#{::Instana::Util.id_to_header(rack_span[:t])}"
104
+
105
+ assert rack_span.key?(:data)
106
+ assert rack_span[:data].key?(:http)
107
+ assert_equal "POST", rack_span[:data][:http][:method]
108
+ assert_equal "/mrlobster", rack_span[:data][:http][:url]
109
+ assert_equal 200, rack_span[:data][:http][:status]
110
+ assert rack_span.key?(:f)
111
+ assert rack_span[:f].key?(:e)
112
+ assert rack_span[:f].key?(:h)
113
+ assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
92
114
  end
93
115
 
94
116
  def test_basic_put
@@ -100,17 +122,27 @@ class RackTest < Minitest::Test
100
122
 
101
123
  # Span validation
102
124
  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]
125
+ rack_span = spans.first
126
+ assert_equal :rack, rack_span[:n]
127
+
128
+ assert last_response.headers.key?("X-Instana-T")
129
+ assert last_response.headers["X-Instana-T"] == ::Instana::Util.id_to_header(rack_span[:t])
130
+ assert last_response.headers.key?("X-Instana-S")
131
+ assert last_response.headers["X-Instana-S"] == ::Instana::Util.id_to_header(rack_span[:s])
132
+ assert last_response.headers.key?("X-Instana-L")
133
+ assert last_response.headers["X-Instana-L"] == '1'
134
+ assert last_response.headers.key?("Server-Timing")
135
+ assert last_response.headers["Server-Timing"] == "intid;desc=#{::Instana::Util.id_to_header(rack_span[:t])}"
136
+
137
+ assert rack_span.key?(:data)
138
+ assert rack_span[:data].key?(:http)
139
+ assert_equal "PUT", rack_span[:data][:http][:method]
140
+ assert_equal "/mrlobster", rack_span[:data][:http][:url]
141
+ assert_equal 200, rack_span[:data][:http][:status]
142
+ assert rack_span.key?(:f)
143
+ assert rack_span[:f].key?(:e)
144
+ assert rack_span[:f].key?(:h)
145
+ assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
114
146
  end
115
147
 
116
148
  def test_context_continuation
@@ -125,23 +157,33 @@ class RackTest < Minitest::Test
125
157
 
126
158
  # Span validation
127
159
  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]
160
+ rack_span = spans.first
161
+ assert_equal :rack, rack_span[:n]
162
+
163
+ assert last_response.headers.key?("X-Instana-T")
164
+ assert last_response.headers["X-Instana-T"] == ::Instana::Util.id_to_header(rack_span[:t])
165
+ assert last_response.headers.key?("X-Instana-S")
166
+ assert last_response.headers["X-Instana-S"] == ::Instana::Util.id_to_header(rack_span[:s])
167
+ assert last_response.headers.key?("X-Instana-L")
168
+ assert last_response.headers["X-Instana-L"] == '1'
169
+ assert last_response.headers.key?("Server-Timing")
170
+ assert last_response.headers["Server-Timing"] == "intid;desc=#{::Instana::Util.id_to_header(rack_span[:t])}"
171
+
172
+ assert rack_span.key?(:data)
173
+ assert rack_span[:data].key?(:http)
174
+ assert_equal "GET", rack_span[:data][:http][:method]
175
+ assert_equal "/mrlobster", rack_span[:data][:http][:url]
176
+ assert_equal 200, rack_span[:data][:http][:status]
177
+ assert rack_span.key?(:f)
178
+ assert rack_span[:f].key?(:e)
179
+ assert rack_span[:f].key?(:h)
180
+ assert_equal ::Instana.agent.agent_uuid, rack_span[:f][:h]
139
181
 
140
182
  # Context validation
141
183
  # The first span should have the passed in trace ID
142
184
  # 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]
185
+ assert_equal 1234, rack_span[:t]
186
+ assert_equal 4321, rack_span[:p]
145
187
  end
146
188
 
147
189
  def test_instana_response_headers
@@ -181,20 +223,30 @@ class RackTest < Minitest::Test
181
223
 
182
224
  # Span validation
183
225
  assert_equal 1, spans.count
184
- first_span = spans.first
185
-
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"]
226
+ rack_span = spans.first
190
227
 
191
- # 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/)
228
+ assert rack_span[:data][:http].key?(:header)
229
+ assert rack_span[:data][:http][:header].key?(:"X-Capture-This")
230
+ assert !rack_span[:data][:http][:header].key?(:"X-Capture-That")
231
+ assert_equal "ThereYouGo", rack_span[:data][:http][:header][:"X-Capture-This"]
232
+ assert !rack_span.key?(:stack)
195
233
 
196
234
  # Restore to default
197
235
  ::Instana.config[:collect_backtraces] = false
198
236
  ::Instana.agent.extra_headers = nil
199
237
  end
238
+
239
+ def test_capture_http_path_template
240
+ clear_all!
241
+
242
+ get '/path_tpl'
243
+ assert last_response.ok?
244
+
245
+ spans = ::Instana.processor.queued_spans
246
+ assert_equal 1, spans.length
247
+
248
+ rack_span = spans.first
249
+ assert_equal :rack, rack_span[:n]
250
+ assert_equal 'sample_template', rack_span[:data][:http][:path_tpl]
251
+ end
200
252
  end
@@ -153,4 +153,16 @@ class ActionControllerTest < Minitest::Test
153
153
  assert ac_span.key?(:stack)
154
154
  assert 1, ac_span[:ec]
155
155
  end
156
+
157
+ def test_path_template
158
+ clear_all!
159
+
160
+ Net::HTTP.get(URI.parse('http://localhost:3205/test/world'))
161
+
162
+ spans = ::Instana.processor.queued_spans
163
+ rack_span = find_first_span_by_name(spans, :rack)
164
+
165
+ assert_equal false, rack_span.key?(:error)
166
+ assert_equal '/test/world(.:format)', rack_span[:data][:http][:path_tpl]
167
+ end
156
168
  end
@@ -2,7 +2,14 @@ require 'test_helper'
2
2
  require 'active_record'
3
3
 
4
4
  class ActiveRecordTest < Minitest::Test
5
+
6
+ def teardown
7
+ # Make sure defaults are back in place
8
+ ::Instana.config[:sanitize_sql] = true
9
+ end
10
+
5
11
  def test_config_defaults
12
+ assert ::Instana.config[:sanitize_sql] == true
6
13
  assert ::Instana.config[:active_record].is_a?(Hash)
7
14
  assert ::Instana.config[:active_record].key?(:enabled)
8
15
  assert_equal true, ::Instana.config[:active_record][:enabled]
@@ -28,19 +35,14 @@ class ActiveRecordTest < Minitest::Test
28
35
  assert span[:data][:activerecord].key?(:username)
29
36
  end
30
37
 
31
-
32
- found = false
33
38
  if ::Rails::VERSION::MAJOR < 4
34
39
  sql = "INSERT INTO \"blocks\" (\"color\", \"created_at\", \"name\", \"updated_at\") VALUES ($?, $?, $?, $?) RETURNING \"id\""
35
40
  else
36
41
  sql = "INSERT INTO \"blocks\" (\"name\", \"color\", \"created_at\", \"updated_at\") VALUES ($?, $?, $?, $?) RETURNING \"id\""
37
42
  end
38
- ar_spans.each do |span|
39
- if span[:data][:activerecord][:sql] ==
40
- found = true
41
- end
43
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
44
+ span[:data][:activerecord][:sql] == sql
42
45
  end
43
- assert found
44
46
 
45
47
  found = false
46
48
  if ::Rails::VERSION::MAJOR >= 5
@@ -50,12 +52,9 @@ class ActiveRecordTest < Minitest::Test
50
52
  else
51
53
  sql = "SELECT \"blocks\".* FROM \"blocks\" WHERE \"blocks\".\"name\" = ? LIMIT ?"
52
54
  end
53
- ar_spans.each do |span|
54
- if span[:data][:activerecord][:sql] == sql
55
- found = true
56
- end
55
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
56
+ span[:data][:activerecord][:sql] == sql
57
57
  end
58
- assert found
59
58
 
60
59
  found = false
61
60
  if ::Rails::VERSION::MAJOR == 3
@@ -63,12 +62,73 @@ class ActiveRecordTest < Minitest::Test
63
62
  else
64
63
  sql = "DELETE FROM \"blocks\" WHERE \"blocks\".\"id\" = $?"
65
64
  end
65
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
66
+ span[:data][:activerecord][:sql] == sql
67
+ end
68
+ end
69
+
70
+ def test_postgresql_without_sanitize
71
+ skip unless ::Instana::Test.postgresql?
72
+
73
+ # Shut SQL sanitization off
74
+ ::Instana.config[:sanitize_sql] = false
75
+ # Pause so the thread can syncronize values
76
+ sleep 1
77
+
78
+ clear_all!
79
+
80
+ Net::HTTP.get(URI.parse('http://localhost:3205/test/db'))
81
+
82
+ spans = Instana.processor.queued_spans
83
+ assert_equal 6, spans.length
84
+ rack_span = find_first_span_by_name(spans, :rack)
85
+
86
+ ar_spans = find_spans_by_name(spans, :activerecord)
87
+ assert_equal 3, ar_spans.length
88
+
66
89
  ar_spans.each do |span|
67
- if span[:data][:activerecord][:sql] == sql
68
- found = true
69
- end
90
+ assert_equal "postgresql", span[:data][:activerecord][:adapter]
91
+ assert span[:data][:activerecord].key?(:host)
92
+ assert span[:data][:activerecord].key?(:username)
93
+ end
94
+
95
+ if ::Rails::VERSION::MAJOR < 4
96
+ sql = "INSERT INTO \"blocks\" (\"color\", \"created_at\", \"name\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"id\""
97
+ else
98
+ sql = "INSERT INTO \"blocks\" (\"name\", \"color\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"id\""
70
99
  end
71
- assert found
100
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
101
+ span[:data][:activerecord][:sql] == sql
102
+ end
103
+ assert ar_span[:data][:activerecord].key?(:binds)
104
+ assert ar_span[:data][:activerecord][:binds].is_a?(Array)
105
+ assert_equal 4, ar_span[:data][:activerecord][:binds].length
106
+
107
+ if ::Rails::VERSION::MAJOR >= 5
108
+ sql = "SELECT \"blocks\".* FROM \"blocks\" WHERE \"blocks\".\"name\" = $1 ORDER BY \"blocks\".\"id\" ASC LIMIT $2"
109
+ elsif ::Rails::VERSION::MAJOR == 4
110
+ sql = "SELECT \"blocks\".* FROM \"blocks\" WHERE \"blocks\".\"name\" = $? ORDER BY \"blocks\".\"id\" ASC LIMIT ?"
111
+ else
112
+ sql = "SELECT \"blocks\".* FROM \"blocks\" WHERE \"blocks\".\"name\" = ? LIMIT ?"
113
+ end
114
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
115
+ span[:data][:activerecord][:sql] == sql
116
+ end
117
+ assert ar_span[:data][:activerecord].key?(:binds)
118
+ assert ar_span[:data][:activerecord][:binds].is_a?(Array)
119
+ assert_equal 2, ar_span[:data][:activerecord][:binds].length
120
+
121
+ if ::Rails::VERSION::MAJOR == 3
122
+ sql = "DELETE FROM \"blocks\" WHERE \"blocks\".\"id\" = 1"
123
+ else
124
+ sql = "DELETE FROM \"blocks\" WHERE \"blocks\".\"id\" = $1"
125
+ end
126
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
127
+ span[:data][:activerecord][:sql] == sql
128
+ end
129
+ assert ar_span[:data][:activerecord].key?(:binds)
130
+ assert ar_span[:data][:activerecord][:binds].is_a?(Array)
131
+ assert_equal 1, ar_span[:data][:activerecord][:binds].length
72
132
  end
73
133
 
74
134
  def test_postgresql_lock_table
@@ -93,21 +153,13 @@ class ActiveRecordTest < Minitest::Test
93
153
  assert_equal "postgres", ar_span[:data][:activerecord][:username]
94
154
  end
95
155
 
96
- found = false
97
- ar_spans.each do |span|
98
- if span[:data][:activerecord][:sql] == "LOCK blocks IN ACCESS EXCLUSIVE MODE"
99
- found = true
100
- end
156
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
157
+ span[:data][:activerecord][:sql] == "LOCK blocks IN ACCESS EXCLUSIVE MODE"
101
158
  end
102
- assert found
103
159
 
104
- found = false
105
- ar_spans.each do |span|
106
- if span[:data][:activerecord][:sql] == "SELECT ?"
107
- found = true
108
- end
160
+ ar_span = find_first_span_by_qualifier(ar_spans) do |span|
161
+ span[:data][:activerecord][:sql] == "SELECT ?"
109
162
  end
110
- assert found
111
163
  end
112
164
 
113
165
  def test_postgresql_raw_execute
@@ -40,5 +40,19 @@ if defined?(::Roda)
40
40
  assert first_span[:data][:http].key?(:host)
41
41
  assert_equal "example.org", first_span[:data][:http][:host]
42
42
  end
43
+
44
+ def test_path_template
45
+ clear_all!
46
+
47
+ r = get '/greet/instana'
48
+ assert last_response.ok?
49
+
50
+ spans = ::Instana.processor.queued_spans
51
+ assert_equal 1, spans.count
52
+
53
+ first_span = spans.first
54
+ assert_equal :rack, first_span[:n]
55
+ assert_equal '/greet/{name}', first_span[:data][:http][:path_tpl]
56
+ end
43
57
  end
44
58
  end