instana 1.9.6 → 1.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Configuration.md +2 -2
  3. data/Troubleshooting.md +1 -1
  4. data/lib/instana/agent.rb +4 -4
  5. data/lib/instana/agent/helpers.rb +2 -2
  6. data/lib/instana/base.rb +0 -16
  7. data/lib/instana/collector.rb +1 -1
  8. data/lib/instana/config.rb +1 -1
  9. data/lib/instana/instrumentation/net-http.rb +1 -1
  10. data/lib/instana/instrumentation/rack.rb +4 -3
  11. data/lib/instana/tracer.rb +4 -5
  12. data/lib/instana/tracing/processor.rb +1 -1
  13. data/lib/instana/tracing/trace.rb +3 -8
  14. data/lib/instana/version.rb +1 -1
  15. data/test/frameworks/rack_test.rb +4 -2
  16. data/test/frameworks/rails/actioncontroller_test.rb +10 -10
  17. data/test/frameworks/rails/actionview3_test.rb +22 -22
  18. data/test/frameworks/rails/actionview4_test.rb +22 -22
  19. data/test/frameworks/rails/actionview5_test.rb +22 -22
  20. data/test/frameworks/rails/activerecord3_test.rb +6 -6
  21. data/test/frameworks/rails/activerecord4_test.rb +6 -6
  22. data/test/frameworks/rails/activerecord5_test.rb +4 -4
  23. data/test/instrumentation/dalli_test.rb +14 -14
  24. data/test/instrumentation/excon_test.rb +7 -7
  25. data/test/instrumentation/grpc_test.rb +2 -2
  26. data/test/instrumentation/net-http_test.rb +7 -7
  27. data/test/instrumentation/redis_test.rb +1 -1
  28. data/test/instrumentation/resque_test.rb +5 -5
  29. data/test/instrumentation/rest-client_test.rb +2 -2
  30. data/test/instrumentation/sidekiq-client_test.rb +2 -2
  31. data/test/instrumentation/sidekiq-worker_test.rb +3 -3
  32. data/test/test_helper.rb +1 -1
  33. data/test/tracing/custom_test.rb +3 -3
  34. data/test/tracing/opentracing_test.rb +14 -14
  35. data/test/tracing/tracer_async_test.rb +3 -3
  36. data/test/tracing/tracer_test.rb +8 -8
  37. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3d6441f6a619ad0643ea9a9afbcebefd86d57171dc14cc12eccd71dbbbb0db8
4
- data.tar.gz: b4b5ea14c821e9a3b53cc9e41b4a0e5e4a9026ec586b8c5753055f292d631cea
3
+ metadata.gz: 556dea91963ad3942c67bd242df34c6121623f74055a09e88891adbabe7aff5a
4
+ data.tar.gz: 2de597f123eaf230c7cf6733efe8d4622e59300b69597478c99fe878d665849e
5
5
  SHA512:
6
- metadata.gz: a416ce7dd571f2eb2dff56d1460dabb528cd0683bd5e9d09534db2bdd352ddd400bbd79c1ddfae804908df725cafa1587e5cc91c5fec26eff5ce44477aa090d8
7
- data.tar.gz: c8eff792dba833a94420b58d3a27f55402aa90dd94a99594565c0b4a7610de1fa3c76a7b410d582dac4351783afcff362410e2718c793611fcef203c78dde1e9
6
+ metadata.gz: 14a5cfc91e47192e928eb6fc407ad0dc5788f8471c593fcfdc34617c9e20f58c7509e3ffaa6eecc4a004f5c9af58d6af9adb9be71794c3bd14cce3ecd110370d
7
+ data.tar.gz: a3b2301b94d016965d054b66c383edd8823b340390114a1f011a1874281a61e19bd4c0be0aca7ce40f7ced5c36fa2f265e3c67f81bd7bbe836335e8914fbdd25
data/Configuration.md CHANGED
@@ -108,7 +108,7 @@ end
108
108
 
109
109
  ### Caveat
110
110
 
111
- In the case of forking webservers such as Unicorn or Puma in clustered mode, the agent detects the pid change and re-spawns the background thread. If you are managing the background thread yourself with the steps above _and_ you are using a forking webserver (or anything else that may fork the original process), you should also do the following.
111
+ In the case of forking web servers such as Unicorn or Puma in clustered mode, the agent detects the pid change and re-spawns the background thread. If you are managing the background thread yourself with the steps above _and_ you are using a forking webserver (or anything else that may fork the original process), you should also do the following.
112
112
 
113
113
  When a fork is detected, the agent handles the re-initialization and then calls `::Agent.instana.spawn_background_thread`. This by default uses the standard `Thread.new`. If you wish to control this, you should override this method by re-defining that method. For example:
114
114
 
@@ -145,5 +145,5 @@ The gem can be configured to use your application logger instead:
145
145
 
146
146
  #### Environment Variable
147
147
 
148
- Setting `INSTANA_GEM_DEV` to a non nil value will enable extra logging output generally useful
148
+ Setting `INSTANA_DEBUG` to a non nil value will enable extra logging output generally useful
149
149
  for development.
data/Troubleshooting.md CHANGED
@@ -11,7 +11,7 @@ supported components can be found in the [documentation](https://docs.instana.io
11
11
  # Logging & Environment Variables
12
12
 
13
13
  By default, the gem will log informational messages on boot that will indicate if any problems were encountered. If you
14
- set the `INSTANA_GEM_DEV` environment variable, it will increase the amount of logging output.
14
+ set the `INSTANA_DEBUG` environment variable, it will increase the amount of logging output.
15
15
 
16
16
  ![instana console output](https://s3.amazonaws.com/instana/Instana+Ruby+boot+console+logging+output.png)
17
17
 
data/lib/instana/agent.rb CHANGED
@@ -156,7 +156,7 @@ module Instana
156
156
  end
157
157
  end
158
158
 
159
- loop do
159
+ while true
160
160
  if @state == :unannounced
161
161
  @collect_timer.pause
162
162
  @announce_timer.resume
@@ -199,7 +199,7 @@ module Instana
199
199
  announce_payload[:name] = @process[:name]
200
200
  announce_payload[:args] = @process[:arguments]
201
201
 
202
- if @is_linux && !::Instana.test?
202
+ if @is_linux && !ENV.key?('INSTANA_TEST')
203
203
  # We create an open socket to the host agent in case we are running in a container
204
204
  # and the real pid needs to be detected.
205
205
  socket = TCPSocket.new @discovered[:agent_host], @discovered[:agent_port]
@@ -329,7 +329,7 @@ module Instana
329
329
  false
330
330
  rescue => e
331
331
  Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
332
- Instana.logger.debug e.backtrace.join("\r\n") unless ::Instana.test?
332
+ Instana.logger.debug e.backtrace.join("\r\n") unless ENV.key?('INSTANA_TEST')
333
333
  return false
334
334
  end
335
335
 
@@ -435,7 +435,7 @@ module Instana
435
435
  return nil
436
436
  rescue => e
437
437
  Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
438
- Instana.logger.debug e.backtrace.join("\r\n") unless ::Instana.test?
438
+ Instana.logger.debug e.backtrace.join("\r\n") unless ENV.key?('INSTANA_TEST')
439
439
  return nil
440
440
  end
441
441
  end
@@ -42,7 +42,7 @@ module AgentHelpers
42
42
  #
43
43
  def ready?
44
44
  # In test, we're always ready :-)
45
- return true if ENV['INSTANA_GEM_TEST']
45
+ return true if ENV.key?('INSTANA_TEST')
46
46
 
47
47
  if !@is_resque_worker && forked?
48
48
  ::Instana.logger.debug "Instana: detected fork. (this pid: #{Process.pid}/#{Process.ppid}) Calling after_fork"
@@ -52,7 +52,7 @@ module AgentHelpers
52
52
  @state == :announced
53
53
  rescue => e
54
54
  Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
55
- Instana.logger.debug e.backtrace.join("\r\n") unless ::Instana.test?
55
+ Instana.logger.debug e.backtrace.join("\r\n") unless ENV.key?('INSTANA_TEST')
56
56
  return false
57
57
  end
58
58
  end
data/lib/instana/base.rb CHANGED
@@ -25,22 +25,6 @@ module Instana
25
25
  @processor = ::Instana::Processor.new
26
26
  @collector = ::Instana::Collector.new
27
27
  end
28
-
29
- # Indicates whether we are running in a development environment.
30
- #
31
- # @return Boolean
32
- #
33
- def debug?
34
- ENV.key?('INSTANA_GEM_DEV')
35
- end
36
-
37
- # Indicates whether we are running in the test environment.
38
- #
39
- # @return Boolean
40
- #
41
- def test?
42
- ENV.key?('INSTANA_GEM_TEST')
43
- end
44
28
  end
45
29
  end
46
30
 
@@ -77,7 +77,7 @@ module Instana
77
77
  payload = enforce_deltas(payload, @last_values)
78
78
  end
79
79
 
80
- if ENV['INSTANA_GEM_TEST']
80
+ if ENV.key?('INSTANA_TEST')
81
81
  true
82
82
  else
83
83
  # Report all the collected goodies
@@ -28,7 +28,7 @@ module Instana
28
28
  # Enable/disable tracing (default: enabled)
29
29
  @config[:tracing] = { :enabled => true }
30
30
 
31
- if ENV.key?('INSTANA_GEM_DEV')
31
+ if ENV.key?('INSTANA_DEBUG')
32
32
  @config[:collector] = { :enabled => true, :interval => 3 }
33
33
  else
34
34
  @config[:collector] = { :enabled => true, :interval => 1 }
@@ -37,7 +37,7 @@ if defined?(::Net::HTTP) && ::Instana.config[:nethttp][:enabled]
37
37
  response = request_without_instana(*args, &block)
38
38
 
39
39
  # Debug only check: Pickup response headers; convert back to base 10 integer and validate
40
- if ::Instana.debug? && response.key?('X-Instana-T')
40
+ if ENV.key?('INSTANA_DEBUG') && response.key?('X-Instana-T')
41
41
  if ::Instana.tracer.trace_id != ::Instana::Util.header_to_id(response.header['X-Instana-T'])
42
42
  ::Instana.logger.debug "#{Thread.current}: Trace ID mismatch on net/http response! ours: #{::Instana.tracer.trace_id} theirs: #{their_trace_id}"
43
43
  end
@@ -24,13 +24,14 @@ module Instana
24
24
  end
25
25
 
26
26
  if ::Instana.agent.extra_headers
27
- for custom_header in ::Instana.agent.extra_headers
27
+ ::Instana.agent.extra_headers.each { |custom_header|
28
28
  # Headers are available in this format: HTTP_X_CAPTURE_THIS
29
- rack_header = ('HTTP_' + custom_header.upcase).gsub('-', '_')
29
+ rack_header = 'HTTP_' + custom_header.upcase
30
+ rack_header.tr!('-', '_')
30
31
  if env.key?(rack_header)
31
32
  kvs["http.#{custom_header}"] = env[rack_header]
32
33
  end
33
- end
34
+ }
34
35
  end
35
36
 
36
37
  # Check incoming context
@@ -37,7 +37,7 @@ module Instana
37
37
  #
38
38
  def start_or_continue_trace(name, kvs = {}, incoming_context = {}, &block)
39
39
  log_start_or_continue(name, kvs, incoming_context)
40
- block.call
40
+ yield
41
41
  rescue Exception => e
42
42
  log_error(e)
43
43
  raise
@@ -58,8 +58,7 @@ module Instana
58
58
  #
59
59
  def trace(name, kvs = {}, &block)
60
60
  log_entry(name, kvs)
61
- result = block.call
62
- result
61
+ yield
63
62
  rescue Exception => e
64
63
  log_error(e)
65
64
  raise
@@ -128,7 +127,7 @@ module Instana
128
127
  def log_exit(name, kvs = {})
129
128
  return unless tracing?
130
129
 
131
- if ::Instana.debug? || ::Instana.test?
130
+ if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST')
132
131
  unless current_span_name?(name)
133
132
  ::Instana.logger.debug "Span mismatch: Attempt to exit #{name} span but #{current_span.name} is active."
134
133
  end
@@ -149,7 +148,7 @@ module Instana
149
148
  def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms)
150
149
  return unless tracing?
151
150
 
152
- if ::Instana.debug? || ::Instana.test?
151
+ if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST')
153
152
  unless current_span_name?(name)
154
153
  ::Instana.logger.debug "Span mismatch: Attempt to end #{name} span but #{current_span.name} is active."
155
154
  end
@@ -81,7 +81,7 @@ module Instana
81
81
  # - Prevent another run of the timer while this is running
82
82
  #
83
83
  def send
84
- return if @queue.empty? || ENV['INSTANA_GEM_TEST']
84
+ return if @queue.empty? || ENV.key?('INSTANA_TEST')
85
85
 
86
86
  size = @queue.size
87
87
  if size > 200
@@ -7,6 +7,9 @@ module Instana
7
7
  # @return [Set] the collection of spans for this trace
8
8
  attr_reader :spans
9
9
 
10
+ # The currently active span
11
+ attr_reader :current_span
12
+
10
13
  # Initializes a new instance of Trace
11
14
  #
12
15
  # @param name [String] the name of the span to start
@@ -223,14 +226,6 @@ module Instana
223
226
  false
224
227
  end
225
228
 
226
- # Get the current span.
227
- #
228
- # @return [Span]
229
- #
230
- def current_span
231
- @current_span
232
- end
233
-
234
229
  # Get the ID of the current span for this trace.
235
230
  # Used often to place in HTTP response headers.
236
231
  #
@@ -1,4 +1,4 @@
1
1
  module Instana
2
- VERSION = "1.9.6"
2
+ VERSION = "1.9.7"
3
3
  VERSION_FULL = "instana-#{VERSION}"
4
4
  end
@@ -19,6 +19,8 @@ class RackTest < Minitest::Test
19
19
 
20
20
  def test_basic_get
21
21
  clear_all!
22
+ ::Instana.config[:collect_backtraces] = true
23
+
22
24
  get '/mrlobster'
23
25
  assert last_response.ok?
24
26
 
@@ -44,7 +46,7 @@ class RackTest < Minitest::Test
44
46
  # Backtrace fingerprint validation
45
47
  assert first_span.key?(:stack)
46
48
  assert_equal 2, first_span[:stack].count
47
- refute_nil first_span[:stack].first[:f].match(/instana\/instrumentation\/rack.rb/)
49
+ refute_nil first_span[:stack].first[:c].match(/instana\/instrumentation\/rack.rb/)
48
50
  end
49
51
 
50
52
  def test_basic_get_with_custom_service_name
@@ -157,7 +159,7 @@ class RackTest < Minitest::Test
157
159
  get '/mrlobster?blah=2&wilma=1&betty=2;fred=3'
158
160
 
159
161
  traces = ::Instana.processor.queued_traces
160
- assert_equal 1, traces.count
162
+ assert_equal 1, traces.length
161
163
 
162
164
  trace = traces[0]
163
165
  refute_nil trace.spans.first.key?(:data)
@@ -13,10 +13,10 @@ class ActionControllerTest < Minitest::Test
13
13
  Net::HTTP.get(URI.parse('http://localhost:3205/test/world'))
14
14
 
15
15
  traces = Instana.processor.queued_traces
16
- assert_equal 1, traces.count
16
+ assert_equal 1, traces.length
17
17
  trace = traces.first
18
18
 
19
- assert_equal 3, trace.spans.count
19
+ assert_equal 3, trace.spans.length
20
20
  spans = trace.spans.to_a
21
21
  first_span = spans[0]
22
22
  second_span = spans[1]
@@ -34,10 +34,10 @@ class ActionControllerTest < Minitest::Test
34
34
  Net::HTTP.get(URI.parse('http://localhost:3205/test/error'))
35
35
 
36
36
  traces = Instana.processor.queued_traces
37
- assert_equal 1, traces.count
37
+ assert_equal 1, traces.length
38
38
  trace = traces.first
39
39
 
40
- assert_equal 2, trace.spans.count
40
+ assert_equal 2, trace.spans.length
41
41
  spans = trace.spans.to_a
42
42
  first_span = spans[0]
43
43
  second_span = spans[1]
@@ -62,10 +62,10 @@ class ActionControllerTest < Minitest::Test
62
62
  Net::HTTP.get(URI.parse('http://localhost:3205/api/world'))
63
63
 
64
64
  traces = Instana.processor.queued_traces
65
- assert_equal 1, traces.count
65
+ assert_equal 1, traces.length
66
66
  trace = traces.first
67
67
 
68
- assert_equal 3, trace.spans.count
68
+ assert_equal 3, trace.spans.length
69
69
  spans = trace.spans.to_a
70
70
  first_span = spans[0]
71
71
  second_span = spans[1]
@@ -86,10 +86,10 @@ class ActionControllerTest < Minitest::Test
86
86
  Net::HTTP.get(URI.parse('http://localhost:3205/api/error'))
87
87
 
88
88
  traces = Instana.processor.queued_traces
89
- assert_equal 1, traces.count
89
+ assert_equal 1, traces.length
90
90
  trace = traces.first
91
91
 
92
- assert_equal 2, trace.spans.count
92
+ assert_equal 2, trace.spans.length
93
93
  spans = trace.spans.to_a
94
94
  first_span = spans[0]
95
95
  second_span = spans[1]
@@ -111,10 +111,10 @@ class ActionControllerTest < Minitest::Test
111
111
  Net::HTTP.get(URI.parse('http://localhost:3205/test/404'))
112
112
 
113
113
  traces = Instana.processor.queued_traces
114
- assert_equal 1, traces.count
114
+ assert_equal 1, traces.length
115
115
  trace = traces.first
116
116
 
117
- assert_equal 1, trace.spans.count
117
+ assert_equal 1, trace.spans.length
118
118
  spans = trace.spans.to_a
119
119
  first_span = spans[0]
120
120
 
@@ -13,10 +13,10 @@ class ActionViewTest < Minitest::Test
13
13
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_view'))
14
14
 
15
15
  traces = Instana.processor.queued_traces
16
- assert_equal 1, traces.count
16
+ assert_equal 1, traces.length
17
17
  trace = traces.first
18
18
 
19
- assert_equal 3, trace.spans.count
19
+ assert_equal 3, trace.spans.length
20
20
  spans = trace.spans.to_a
21
21
  first_span = spans[0]
22
22
  second_span = spans[1]
@@ -33,10 +33,10 @@ class ActionViewTest < Minitest::Test
33
33
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_nothing'))
34
34
 
35
35
  traces = Instana.processor.queued_traces
36
- assert_equal 1, traces.count
36
+ assert_equal 1, traces.length
37
37
  trace = traces.first
38
38
 
39
- assert_equal 3, trace.spans.count
39
+ assert_equal 3, trace.spans.length
40
40
  spans = trace.spans.to_a
41
41
  first_span = spans[0]
42
42
  second_span = spans[1]
@@ -54,10 +54,10 @@ class ActionViewTest < Minitest::Test
54
54
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_file'))
55
55
 
56
56
  traces = Instana.processor.queued_traces
57
- assert_equal 1, traces.count
57
+ assert_equal 1, traces.length
58
58
  trace = traces.first
59
59
 
60
- assert_equal 3, trace.spans.count
60
+ assert_equal 3, trace.spans.length
61
61
  spans = trace.spans.to_a
62
62
  first_span = spans[0]
63
63
  second_span = spans[1]
@@ -75,10 +75,10 @@ class ActionViewTest < Minitest::Test
75
75
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_json'))
76
76
 
77
77
  traces = Instana.processor.queued_traces
78
- assert_equal 1, traces.count
78
+ assert_equal 1, traces.length
79
79
  trace = traces.first
80
80
 
81
- assert_equal 3, trace.spans.count
81
+ assert_equal 3, trace.spans.length
82
82
  spans = trace.spans.to_a
83
83
  first_span = spans[0]
84
84
  second_span = spans[1]
@@ -96,10 +96,10 @@ class ActionViewTest < Minitest::Test
96
96
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_xml'))
97
97
 
98
98
  traces = Instana.processor.queued_traces
99
- assert_equal 1, traces.count
99
+ assert_equal 1, traces.length
100
100
  trace = traces.first
101
101
 
102
- assert_equal 3, trace.spans.count
102
+ assert_equal 3, trace.spans.length
103
103
  spans = trace.spans.to_a
104
104
  first_span = spans[0]
105
105
  second_span = spans[1]
@@ -117,10 +117,10 @@ class ActionViewTest < Minitest::Test
117
117
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_rawbody'))
118
118
 
119
119
  traces = Instana.processor.queued_traces
120
- assert_equal 1, traces.count
120
+ assert_equal 1, traces.length
121
121
  trace = traces.first
122
122
 
123
- assert_equal 3, trace.spans.count
123
+ assert_equal 3, trace.spans.length
124
124
  spans = trace.spans.to_a
125
125
  first_span = spans[0]
126
126
  second_span = spans[1]
@@ -138,10 +138,10 @@ class ActionViewTest < Minitest::Test
138
138
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_js'))
139
139
 
140
140
  traces = Instana.processor.queued_traces
141
- assert_equal 1, traces.count
141
+ assert_equal 1, traces.length
142
142
  trace = traces.first
143
143
 
144
- assert_equal 3, trace.spans.count
144
+ assert_equal 3, trace.spans.length
145
145
  spans = trace.spans.to_a
146
146
  first_span = spans[0]
147
147
  second_span = spans[1]
@@ -159,10 +159,10 @@ class ActionViewTest < Minitest::Test
159
159
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_alternate_layout'))
160
160
 
161
161
  traces = Instana.processor.queued_traces
162
- assert_equal 1, traces.count
162
+ assert_equal 1, traces.length
163
163
  trace = traces.first
164
164
 
165
- assert_equal 3, trace.spans.count
165
+ assert_equal 3, trace.spans.length
166
166
  spans = trace.spans.to_a
167
167
  first_span = spans[0]
168
168
  second_span = spans[1]
@@ -180,10 +180,10 @@ class ActionViewTest < Minitest::Test
180
180
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_partial'))
181
181
 
182
182
  traces = Instana.processor.queued_traces
183
- assert_equal 1, traces.count
183
+ assert_equal 1, traces.length
184
184
  trace = traces.first
185
185
 
186
- assert_equal 4, trace.spans.count
186
+ assert_equal 4, trace.spans.length
187
187
  spans = trace.spans.to_a
188
188
  first_span = spans[0]
189
189
  second_span = spans[1]
@@ -204,10 +204,10 @@ class ActionViewTest < Minitest::Test
204
204
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_partial_that_errors'))
205
205
 
206
206
  traces = Instana.processor.queued_traces
207
- assert_equal 1, traces.count
207
+ assert_equal 1, traces.length
208
208
  trace = traces.first
209
209
 
210
- assert_equal 4, trace.spans.count
210
+ assert_equal 4, trace.spans.length
211
211
  spans = trace.spans.to_a
212
212
  first_span = spans[0]
213
213
  second_span = spans[1]
@@ -232,10 +232,10 @@ class ActionViewTest < Minitest::Test
232
232
  Net::HTTP.get(URI.parse('http://localhost:3205/test/render_collection'))
233
233
 
234
234
  traces = Instana.processor.queued_traces
235
- assert_equal 1, traces.count
235
+ assert_equal 1, traces.length
236
236
  trace = traces.first
237
237
 
238
- assert_equal 5, trace.spans.count
238
+ assert_equal 5, trace.spans.length
239
239
  spans = trace.spans.to_a
240
240
  first_span = spans[0]
241
241
  second_span = spans[1]