bugsnag-maze-runner 10.7.3 → 10.8.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 +4 -4
- data/bin/maze-runner +5 -0
- data/lib/features/support/internal_hooks.rb +1 -1
- data/lib/features/support/span_support.rb +13 -5
- data/lib/maze/api/model/otel_attribute.rb +69 -0
- data/lib/maze/api/model/otel_attribute_type.rb +36 -0
- data/lib/maze/api/model/span.rb +44 -0
- data/lib/maze/api/model/span_kind.rb +16 -0
- data/lib/maze/api/model/span_set.rb +66 -0
- data/lib/maze/interactive_cli.rb +9 -1
- data/lib/maze/maze_output.rb +48 -0
- data/lib/maze/schemas/trace_validator.rb +41 -19
- data/lib/maze/schemas/validator_base.rb +1 -1
- data/lib/maze.rb +1 -1
- metadata +21 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0de79ce31a9a1b66dfca934d16fb84e0c80ac5a4c5e879e993832f53f9d92c06
|
|
4
|
+
data.tar.gz: f92ab806fac107be92713d90b346b5dda5d326d7b1cbbbfc8c8a247acfceeb5d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a6473e52c80d43cea5b5ee4f9dd49e5caf6db7f849bc926e032fc080c74ec69180553ab2d3973f6dc90028f6cb4ed8c3f0c7f98a6484e9d2e9110a00f4a87b51
|
|
7
|
+
data.tar.gz: 5ce8ec5e75ef9b22460bae6f767d5a9ecc1394c2b53fe70b4273bd8ce7a77b591a2a71b32ba80d101bebfb30356c73d43a0bc20c58d91c3b40997384f8743dd1
|
data/bin/maze-runner
CHANGED
|
@@ -18,6 +18,11 @@ require_relative '../lib/maze/api/appium/file_manager'
|
|
|
18
18
|
require_relative '../lib/maze/api/appium/ui_manager'
|
|
19
19
|
require_relative '../lib/maze/api/cucumber/scenario'
|
|
20
20
|
require_relative '../lib/maze/api/exit_code'
|
|
21
|
+
require_relative '../lib/maze/api/model/span'
|
|
22
|
+
require_relative '../lib/maze/api/model/span_kind'
|
|
23
|
+
require_relative '../lib/maze/api/model/span_set'
|
|
24
|
+
require_relative '../lib/maze/api/model/otel_attribute'
|
|
25
|
+
require_relative '../lib/maze/api/model/otel_attribute_type'
|
|
21
26
|
require_relative '../lib/maze/error_monitor/selenium_error_middleware'
|
|
22
27
|
require_relative '../lib/maze/error_monitor/assert_error_middleware'
|
|
23
28
|
require_relative '../lib/maze/error_monitor/config'
|
|
@@ -172,7 +172,7 @@ After do |scenario|
|
|
|
172
172
|
$success = !scenario.failed?
|
|
173
173
|
|
|
174
174
|
# Log all received requests to file
|
|
175
|
-
Maze::MazeOutput.new(scenario).
|
|
175
|
+
Maze::MazeOutput.new(scenario).write_requests_and_spans if Maze.config.file_log
|
|
176
176
|
|
|
177
177
|
# Invoke the internal hook for the mode of operation
|
|
178
178
|
Maze.internal_hooks.after scenario
|
|
@@ -33,25 +33,33 @@ class SpanSupport
|
|
|
33
33
|
assert_received_spans(minimum, maximum)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def received_spans_names
|
|
37
|
+
spans = spans_from_request_list(Maze::Server.traces)
|
|
38
|
+
names spans.map { |span| span['name'] }
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
36
42
|
def assert_received_named_span(span_name)
|
|
37
43
|
timeout = Maze.config.receive_requests_wait
|
|
38
44
|
wait = Maze::Wait.new(timeout: timeout)
|
|
39
|
-
|
|
40
45
|
received = wait.until { SpanSupport.named_span_exists?(span_name) }
|
|
41
46
|
|
|
47
|
+
spans = Maze::Api::Model::SpanSet.new
|
|
42
48
|
list = Maze::Server.traces
|
|
43
|
-
|
|
49
|
+
list.remaining.each { |t| spans.add_from_trace_hash(t[:body]) }
|
|
50
|
+
names = spans.size == 0 ? '.' : ", with names:\n#{spans.names.sort.join("\n")}"
|
|
44
51
|
|
|
45
52
|
unless received
|
|
46
53
|
raise Test::Unit::AssertionFailedError.new <<-MESSAGE
|
|
47
|
-
Expected span with name #{span_name} not received within the #{timeout}s timeout
|
|
54
|
+
Expected span with name #{span_name} not received within the #{timeout}s timeout. #{spans.size} spans were received#{names}
|
|
55
|
+
|
|
48
56
|
This could indicate that:
|
|
49
57
|
- Bugsnag crashed with a fatal error.
|
|
50
58
|
- Bugsnag did not make the requests that it should have done.
|
|
51
59
|
- The requests were made, but not deemed to be valid (e.g. missing integrity header).
|
|
52
60
|
- The requests made were prevented from being received due to a network or other infrastructure issue.
|
|
53
61
|
Please check the Maze Runner and device logs to confirm.)
|
|
54
|
-
MESSAGE
|
|
62
|
+
MESSAGE
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
Maze::Schemas::Validator.validate_payload_elements(list, 'trace')
|
|
@@ -73,7 +81,7 @@ This could indicate that:
|
|
|
73
81
|
- The requests were made, but not deemed to be valid (e.g. missing integrity header).
|
|
74
82
|
- The requests made were prevented from being received due to a network or other infrastructure issue.
|
|
75
83
|
Please check the Maze Runner and device logs to confirm.)
|
|
76
|
-
MESSAGE
|
|
84
|
+
MESSAGE
|
|
77
85
|
end
|
|
78
86
|
|
|
79
87
|
Maze.check.operator(max_received, :>=, received_count, "#{received_count} spans received") if max_received
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'otel_attribute_type'
|
|
3
|
+
|
|
4
|
+
module Maze
|
|
5
|
+
module Api
|
|
6
|
+
module Model
|
|
7
|
+
# Element of an OTEL attribute array.
|
|
8
|
+
class OtelAttributeArrayElement
|
|
9
|
+
attr_accessor :type, :value
|
|
10
|
+
|
|
11
|
+
def initialize(type, value)
|
|
12
|
+
@type = type
|
|
13
|
+
@value = value
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# OTEL attributes used in both spans and resources
|
|
18
|
+
class OtelAttribute
|
|
19
|
+
attr_accessor :type, :key, :value
|
|
20
|
+
|
|
21
|
+
def initialize(type, key, value)
|
|
22
|
+
@key = key
|
|
23
|
+
@type = type
|
|
24
|
+
@value = value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
# Create an array of OtelAttributeArrayElement from a hash array.
|
|
29
|
+
# @param hash_array [Array<Hash>] Array of hashes representing attribute values.
|
|
30
|
+
# @return [Array<OtelAttributeArrayElement>] Array of OtelAttributeArrayElement objects.
|
|
31
|
+
def array_from_hash(hash_array)
|
|
32
|
+
array = []
|
|
33
|
+
hash_array.each do |value_hash|
|
|
34
|
+
type = OtelAttributeType::for_string(value_hash.keys.first)
|
|
35
|
+
value = value_hash.values.first
|
|
36
|
+
array << OtelAttributeArrayElement.new(type, value)
|
|
37
|
+
end
|
|
38
|
+
array
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Create an OtelAttribute from a hash.
|
|
42
|
+
# @param hash [Hash] Hash representing an OTEL attribute.
|
|
43
|
+
# @return [OtelAttribute] OtelAttribute object.
|
|
44
|
+
def from_hash(hash)
|
|
45
|
+
type = OtelAttributeType.for_string(hash['value'].keys.first)
|
|
46
|
+
hash_value = hash['value']
|
|
47
|
+
value = if hash_value.has_key?('arrayValue')
|
|
48
|
+
array_from_hash(hash_value['arrayValue']['values'])
|
|
49
|
+
elsif hash_value.has_key?('boolValue')
|
|
50
|
+
hash_value['boolValue']
|
|
51
|
+
elsif hash_value.has_key?('doubleValue')
|
|
52
|
+
hash_value['doubleValue']
|
|
53
|
+
elsif hash_value.has_key?('intValue')
|
|
54
|
+
hash_value['intValue']
|
|
55
|
+
elsif hash_value.has_key?('stringValue')
|
|
56
|
+
hash_value['stringValue']
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
new(
|
|
60
|
+
type,
|
|
61
|
+
hash['key'],
|
|
62
|
+
value
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Maze
|
|
4
|
+
module Api
|
|
5
|
+
module Model
|
|
6
|
+
# OTEL attribute types.
|
|
7
|
+
module OtelAttributeType
|
|
8
|
+
ARRAY = 0
|
|
9
|
+
BOOL = 1
|
|
10
|
+
DOUBLE = 2
|
|
11
|
+
INT = 3
|
|
12
|
+
STRING = 4
|
|
13
|
+
|
|
14
|
+
# Get the OTEL attribute type constant for a given string.
|
|
15
|
+
# @param type_string [String] OTEL attribute type as a string.
|
|
16
|
+
# @return [Integer, nil] OTEL attribute type constant or nil if not found.
|
|
17
|
+
def self.for_string(type_string)
|
|
18
|
+
case type_string
|
|
19
|
+
when 'arrayValue'
|
|
20
|
+
ARRAY
|
|
21
|
+
when 'boolValue'
|
|
22
|
+
BOOL
|
|
23
|
+
when 'doubleValue'
|
|
24
|
+
DOUBLE
|
|
25
|
+
when 'intValue'
|
|
26
|
+
INT
|
|
27
|
+
when 'stringValue'
|
|
28
|
+
STRING
|
|
29
|
+
else
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'otel_attribute'
|
|
4
|
+
|
|
5
|
+
module Maze
|
|
6
|
+
module Api
|
|
7
|
+
module Model
|
|
8
|
+
# A single OTEL span.
|
|
9
|
+
class Span
|
|
10
|
+
attr_accessor :id, :kind, :name, :trace_id, :start_time, :end_time, :attributes
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@attributes = {}
|
|
14
|
+
|
|
15
|
+
def add_attribute(attribute)
|
|
16
|
+
@attributes[attribute.key] = attribute
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
# Create a Span from a hash.
|
|
22
|
+
# @param hash [Hash] Hash representing an OTEL span.
|
|
23
|
+
# @return [Span] Span object.
|
|
24
|
+
def from_hash(hash)
|
|
25
|
+
span = new
|
|
26
|
+
span.id = hash['spanId']
|
|
27
|
+
span.kind = hash['kind']
|
|
28
|
+
span.name = hash['name']
|
|
29
|
+
span.trace_id = hash['traceId']
|
|
30
|
+
span.start_time = hash['startTimeUnixNano']
|
|
31
|
+
span.end_time = hash['endTimeUnixNano']
|
|
32
|
+
|
|
33
|
+
hash['attributes'].each do |attribute_hash|
|
|
34
|
+
attribute = OtelAttribute.from_hash(attribute_hash)
|
|
35
|
+
span.add_attribute(attribute)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
span
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'span'
|
|
4
|
+
|
|
5
|
+
module Maze
|
|
6
|
+
module Api
|
|
7
|
+
module Model
|
|
8
|
+
# A collection of spans, typically representing one or more traces.
|
|
9
|
+
class SpanSet
|
|
10
|
+
def initialize
|
|
11
|
+
@spans = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param span [Maze::Api::Model::Span] Span to add to the SpanSet.
|
|
15
|
+
def add(span)
|
|
16
|
+
@spans[span.id] = span
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Add spans from a trace hash to the SpanSet.
|
|
20
|
+
# @param trace_hash [Hash] Trace request payload as a hash.
|
|
21
|
+
def add_from_trace_hash(trace_hash)
|
|
22
|
+
SpanSet.add_trace_hash(trace_hash, self)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @param span_id [String] Id of the span to remove from the SpanSet.
|
|
26
|
+
def remove(span_id)
|
|
27
|
+
@spans.delete(span_id)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Integer] Number of spans in the SpanSet.
|
|
31
|
+
def size
|
|
32
|
+
@spans.size
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [Array<String>] List of span names in the SpanSet.
|
|
36
|
+
def names
|
|
37
|
+
@spans.values.map(&:name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class << self
|
|
41
|
+
# Creates a new SpanSet from a trace hash.
|
|
42
|
+
# @param trace_hash [Hash] Trace request payload as a hash.
|
|
43
|
+
def from_trace_hash(trace_hash)
|
|
44
|
+
span_set = Maze::Api::Model::SpanSet.new
|
|
45
|
+
add_trace_hash(trace_hash, span_set)
|
|
46
|
+
span_set
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Adds spans from a trace hash to an existing SpanSet.
|
|
50
|
+
# @param trace_hash [Hash] Trace request payload as a hash.
|
|
51
|
+
# @param span_set [Maze::Api::Model::SpanSet] SpanSet to add spans to.
|
|
52
|
+
def add_trace_hash(trace_hash, span_set)
|
|
53
|
+
spans = trace_hash['resourceSpans'].flat_map { |r| r['scopeSpans'] }
|
|
54
|
+
.flat_map { |s| s['spans'] }
|
|
55
|
+
.select { |s| !s.nil? }
|
|
56
|
+
|
|
57
|
+
spans.each do |span_hash|
|
|
58
|
+
span = Maze::Api::Model::Span.from_hash(span_hash)
|
|
59
|
+
span_set.add(span)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/maze/interactive_cli.rb
CHANGED
|
@@ -19,7 +19,10 @@ module Maze
|
|
|
19
19
|
|
|
20
20
|
# @!attribute [r] current_buffer
|
|
21
21
|
# @return [String] A string representation of the current output present in the terminal
|
|
22
|
-
attr_reader :current_buffer
|
|
22
|
+
# attr_reader :current_buffer
|
|
23
|
+
def current_buffer
|
|
24
|
+
strip_nonprintable(@current_buffer)
|
|
25
|
+
end
|
|
23
26
|
|
|
24
27
|
# Creates an InteractiveCLI instance
|
|
25
28
|
#
|
|
@@ -169,5 +172,10 @@ module Maze
|
|
|
169
172
|
# @boring.scrub(line.strip)
|
|
170
173
|
line.strip
|
|
171
174
|
end
|
|
175
|
+
|
|
176
|
+
def strip_nonprintable(str)
|
|
177
|
+
# keep: space..tilde, Tab, CR, LF
|
|
178
|
+
str.gsub(/[^\x20-\x7E\t\r\n]/, '')
|
|
179
|
+
end
|
|
172
180
|
end
|
|
173
181
|
end
|
data/lib/maze/maze_output.rb
CHANGED
|
@@ -7,6 +7,11 @@ module Maze
|
|
|
7
7
|
@scenario = scenario
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
def write_requests_and_spans
|
|
11
|
+
write_requests
|
|
12
|
+
write_spans
|
|
13
|
+
end
|
|
14
|
+
|
|
10
15
|
# Writes each list of requests to a separate file under, e.g:
|
|
11
16
|
# maze_output/failed/scenario_name/errors.log
|
|
12
17
|
def write_requests
|
|
@@ -91,6 +96,49 @@ module Maze
|
|
|
91
96
|
end
|
|
92
97
|
end
|
|
93
98
|
|
|
99
|
+
# Writes each list of requests to a separate file under, e.g:
|
|
100
|
+
# maze_output/failed/scenario_name/errors.log
|
|
101
|
+
def write_spans
|
|
102
|
+
list = Maze::Server.traces.all
|
|
103
|
+
return if list.empty?
|
|
104
|
+
|
|
105
|
+
path = output_folder
|
|
106
|
+
filepath = File.join(path, 'spans.log')
|
|
107
|
+
|
|
108
|
+
File.open(filepath, 'w+') do |file|
|
|
109
|
+
spans = spans_from_request_list(list)
|
|
110
|
+
|
|
111
|
+
# File summary
|
|
112
|
+
file.puts "=== Spans Summary ==="
|
|
113
|
+
file.puts
|
|
114
|
+
file.puts "Id Name"
|
|
115
|
+
spans.each do |span|
|
|
116
|
+
file.puts "#{span['spanId']} #{span['name']}"
|
|
117
|
+
end
|
|
118
|
+
file.puts
|
|
119
|
+
file.puts
|
|
120
|
+
|
|
121
|
+
# Write the spans
|
|
122
|
+
counter = 1
|
|
123
|
+
spans.each do |span|
|
|
124
|
+
file.puts "=== Span #{counter} of #{spans.size} ==="
|
|
125
|
+
file.puts
|
|
126
|
+
file.puts JSON.pretty_generate(span)
|
|
127
|
+
file.puts
|
|
128
|
+
file.puts
|
|
129
|
+
|
|
130
|
+
counter += 1
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def spans_from_request_list(list)
|
|
136
|
+
list.flat_map { |req| req[:body]['resourceSpans'] }
|
|
137
|
+
.flat_map { |r| r['scopeSpans'] }
|
|
138
|
+
.flat_map { |s| s['spans'] }
|
|
139
|
+
.select { |s| !s.nil? }
|
|
140
|
+
end
|
|
141
|
+
|
|
94
142
|
# Determines the output folder for the scenario
|
|
95
143
|
def output_folder
|
|
96
144
|
folder1 = File.join(Dir.pwd, 'maze_output')
|
|
@@ -18,25 +18,7 @@ module Maze
|
|
|
18
18
|
@success = true
|
|
19
19
|
verify_against_schema
|
|
20
20
|
validate_headers
|
|
21
|
-
|
|
22
|
-
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.traceId', HEX_STRING_32)
|
|
23
|
-
element_int_in_range('resourceSpans.0.scopeSpans.0.spans.0.kind', 0..5)
|
|
24
|
-
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.startTimeUnixNano', '^[0-9]+$')
|
|
25
|
-
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.endTimeUnixNano', '^[0-9]+$')
|
|
26
|
-
each_span_element_contains('resourceSpans.0.scopeSpans.0.spans', 'attributes', 'bugsnag.sampling.p')
|
|
27
|
-
span_element_contains('resourceSpans.0.resource.attributes', 'deployment.environment')
|
|
28
|
-
span_element_contains('resourceSpans.0.resource.attributes', 'telemetry.sdk.name')
|
|
29
|
-
span_element_contains('resourceSpans.0.resource.attributes', 'telemetry.sdk.version')
|
|
30
|
-
validate_timestamp('resourceSpans.0.scopeSpans.0.spans.0.startTimeUnixNano', HOUR_TOLERANCE)
|
|
31
|
-
validate_timestamp('resourceSpans.0.scopeSpans.0.spans.0.endTimeUnixNano', HOUR_TOLERANCE)
|
|
32
|
-
element_a_greater_or_equal_element_b(
|
|
33
|
-
'resourceSpans.0.scopeSpans.0.spans.0.endTimeUnixNano',
|
|
34
|
-
'resourceSpans.0.scopeSpans.0.spans.0.startTimeUnixNano'
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
if Maze.config.client_mode_validation
|
|
38
|
-
span_element_contains('resourceSpans.0.resource.attributes', 'device.id')
|
|
39
|
-
end
|
|
21
|
+
validate_fields
|
|
40
22
|
end
|
|
41
23
|
|
|
42
24
|
def verify_against_schema
|
|
@@ -84,6 +66,46 @@ module Maze
|
|
|
84
66
|
end
|
|
85
67
|
end
|
|
86
68
|
|
|
69
|
+
def validate_fields
|
|
70
|
+
resource_spans = Maze::Helper.read_key_path(@body, 'resourceSpans')
|
|
71
|
+
|
|
72
|
+
# Loop through all resource spans
|
|
73
|
+
(0...resource_spans.size).each do |rs|
|
|
74
|
+
|
|
75
|
+
if Maze.config.client_mode_validation
|
|
76
|
+
span_element_contains("resourceSpans.#{rs}.resource.attributes", 'device.id')
|
|
77
|
+
end
|
|
78
|
+
span_element_contains("resourceSpans.#{rs}.resource.attributes", 'deployment.environment')
|
|
79
|
+
span_element_contains("resourceSpans.#{rs}.resource.attributes", 'telemetry.sdk.name')
|
|
80
|
+
span_element_contains("resourceSpans.#{rs}.resource.attributes", 'telemetry.sdk.version')
|
|
81
|
+
|
|
82
|
+
# Loop through all scope spans
|
|
83
|
+
scope_spans = Maze::Helper.read_key_path(@body, "resourceSpans.#{rs}.scopeSpans")
|
|
84
|
+
(0...scope_spans.size).each do |ss|
|
|
85
|
+
|
|
86
|
+
each_span_element_contains("resourceSpans.#{rs}.scopeSpans.#{ss}.spans", 'attributes', 'bugsnag.sampling.p')
|
|
87
|
+
|
|
88
|
+
# Loop through all spans
|
|
89
|
+
spans = Maze::Helper.read_key_path(@body, "resourceSpans.#{rs}.scopeSpans.#{ss}.spans")
|
|
90
|
+
(0...spans.size).each do |s|
|
|
91
|
+
|
|
92
|
+
# Field validations
|
|
93
|
+
regex_comparison("resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.spanId", HEX_STRING_16)
|
|
94
|
+
regex_comparison("resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.traceId", HEX_STRING_32)
|
|
95
|
+
element_int_in_range("resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.kind", 0..5)
|
|
96
|
+
regex_comparison("resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.startTimeUnixNano", '^[0-9]+$')
|
|
97
|
+
regex_comparison("resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.endTimeUnixNano", '^[0-9]+$')
|
|
98
|
+
validate_timestamp("resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.startTimeUnixNano", HOUR_TOLERANCE)
|
|
99
|
+
validate_timestamp("resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.endTimeUnixNano", HOUR_TOLERANCE)
|
|
100
|
+
element_a_greater_or_equal_element_b(
|
|
101
|
+
"resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.endTimeUnixNano",
|
|
102
|
+
"resourceSpans.#{rs}.scopeSpans.#{ss}.spans.#{s}.startTimeUnixNano"
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
87
109
|
def span_element_contains(path, key_value, value_type=nil, possible_values=nil)
|
|
88
110
|
container = Maze::Helper.read_key_path(@body, path)
|
|
89
111
|
if container.nil? || !container.kind_of?(Array)
|
|
@@ -129,7 +129,7 @@ module Maze
|
|
|
129
129
|
time_in_nanos = Time.now.to_i * 1000000000
|
|
130
130
|
unless (time_in_nanos - parsed_timestamp).abs < tolerance
|
|
131
131
|
@success = false
|
|
132
|
-
@errors << "Timestamp was expected to be within #{tolerance} nanoseconds of the current time (#{time_in_nanos}), was '#{
|
|
132
|
+
@errors << "Timestamp was expected to be within #{tolerance} nanoseconds of the current time (#{time_in_nanos}), was '#{timestamp}'"
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
|
data/lib/maze.rb
CHANGED
|
@@ -8,7 +8,7 @@ require_relative 'maze/timers'
|
|
|
8
8
|
# providing an alternative to the proliferation of global variables or singletons.
|
|
9
9
|
module Maze
|
|
10
10
|
|
|
11
|
-
VERSION = '10.
|
|
11
|
+
VERSION = '10.8.0'
|
|
12
12
|
|
|
13
13
|
class << self
|
|
14
14
|
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address,
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bugsnag-maze-runner
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 10.
|
|
4
|
+
version: 10.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Steve Kirkland
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-
|
|
12
|
+
date: 2025-12-03 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: cucumber
|
|
@@ -221,6 +221,20 @@ dependencies:
|
|
|
221
221
|
- - "~>"
|
|
222
222
|
- !ruby/object:Gem::Version
|
|
223
223
|
version: 0.2.24
|
|
224
|
+
- !ruby/object:Gem::Dependency
|
|
225
|
+
name: openssl
|
|
226
|
+
requirement: !ruby/object:Gem::Requirement
|
|
227
|
+
requirements:
|
|
228
|
+
- - "~>"
|
|
229
|
+
- !ruby/object:Gem::Version
|
|
230
|
+
version: 3.3.0
|
|
231
|
+
type: :runtime
|
|
232
|
+
prerelease: false
|
|
233
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
234
|
+
requirements:
|
|
235
|
+
- - "~>"
|
|
236
|
+
- !ruby/object:Gem::Version
|
|
237
|
+
version: 3.3.0
|
|
224
238
|
- !ruby/object:Gem::Dependency
|
|
225
239
|
name: rubyzip
|
|
226
240
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -438,6 +452,11 @@ files:
|
|
|
438
452
|
- lib/maze/api/appium/ui_manager.rb
|
|
439
453
|
- lib/maze/api/cucumber/scenario.rb
|
|
440
454
|
- lib/maze/api/exit_code.rb
|
|
455
|
+
- lib/maze/api/model/otel_attribute.rb
|
|
456
|
+
- lib/maze/api/model/otel_attribute_type.rb
|
|
457
|
+
- lib/maze/api/model/span.rb
|
|
458
|
+
- lib/maze/api/model/span_kind.rb
|
|
459
|
+
- lib/maze/api/model/span_set.rb
|
|
441
460
|
- lib/maze/appium_server.rb
|
|
442
461
|
- lib/maze/assertions/request_set_assertions.rb
|
|
443
462
|
- lib/maze/aws/sam.rb
|