datadog-ci 0.3.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +89 -1
  3. data/README.md +57 -34
  4. data/lib/datadog/ci/concurrent_span.rb +59 -0
  5. data/lib/datadog/ci/configuration/components.rb +40 -1
  6. data/lib/datadog/ci/configuration/extensions.rb +21 -0
  7. data/lib/datadog/ci/configuration/settings.rb +7 -1
  8. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +12 -1
  9. data/lib/datadog/ci/contrib/cucumber/formatter.rb +22 -29
  10. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +10 -1
  11. data/lib/datadog/ci/contrib/minitest/hooks.rb +15 -25
  12. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +10 -1
  13. data/lib/datadog/ci/contrib/rspec/example.rb +13 -18
  14. data/lib/datadog/ci/contrib/settings.rb +2 -0
  15. data/lib/datadog/ci/ext/app_types.rb +5 -0
  16. data/lib/datadog/ci/ext/environment/extractor.rb +5 -10
  17. data/lib/datadog/ci/ext/environment/providers/github_actions.rb +13 -4
  18. data/lib/datadog/ci/ext/settings.rb +11 -0
  19. data/lib/datadog/ci/ext/test.rb +12 -1
  20. data/lib/datadog/ci/null_span.rb +63 -0
  21. data/lib/datadog/ci/span.rb +117 -0
  22. data/lib/datadog/ci/test.rb +25 -0
  23. data/lib/datadog/ci/test_module.rb +23 -0
  24. data/lib/datadog/ci/test_session.rb +36 -0
  25. data/lib/datadog/ci/test_suite.rb +25 -0
  26. data/lib/datadog/ci/test_visibility/context/global.rb +82 -0
  27. data/lib/datadog/ci/test_visibility/context/local.rb +52 -0
  28. data/lib/datadog/ci/test_visibility/recorder.rb +293 -0
  29. data/lib/datadog/ci/test_visibility/serializers/base.rb +100 -12
  30. data/lib/datadog/ci/test_visibility/serializers/factories/test_suite_level.rb +37 -0
  31. data/lib/datadog/ci/test_visibility/serializers/span.rb +2 -16
  32. data/lib/datadog/ci/test_visibility/serializers/test_module.rb +46 -0
  33. data/lib/datadog/ci/test_visibility/serializers/test_session.rb +46 -0
  34. data/lib/datadog/ci/test_visibility/serializers/test_suite.rb +46 -0
  35. data/lib/datadog/ci/test_visibility/serializers/test_v1.rb +3 -17
  36. data/lib/datadog/ci/test_visibility/serializers/test_v2.rb +38 -0
  37. data/lib/datadog/ci/test_visibility/transport.rb +4 -4
  38. data/lib/datadog/ci/utils/test_run.rb +15 -0
  39. data/lib/datadog/ci/utils/url.rb +15 -0
  40. data/lib/datadog/ci/version.rb +2 -2
  41. data/lib/datadog/ci.rb +378 -7
  42. data/sig/datadog/ci/concurrent_span.rbs +23 -0
  43. data/sig/datadog/ci/configuration/components.rbs +6 -0
  44. data/sig/datadog/ci/configuration/extensions.rbs +9 -0
  45. data/sig/datadog/ci/ext/app_types.rbs +6 -1
  46. data/sig/datadog/ci/ext/environment/extractor.rbs +0 -2
  47. data/sig/datadog/ci/ext/environment/providers/github_actions.rbs +5 -0
  48. data/sig/datadog/ci/ext/settings.rbs +3 -0
  49. data/sig/datadog/ci/ext/test.rbs +15 -0
  50. data/sig/datadog/ci/null_span.rbs +37 -0
  51. data/sig/datadog/ci/span.rbs +39 -0
  52. data/sig/datadog/ci/test.rbs +7 -0
  53. data/sig/datadog/ci/test_module.rbs +6 -0
  54. data/sig/datadog/ci/test_session.rbs +9 -0
  55. data/sig/datadog/ci/test_suite.rbs +6 -0
  56. data/sig/datadog/ci/test_visibility/context/global.rbs +39 -0
  57. data/sig/datadog/ci/test_visibility/context/local.rbs +23 -0
  58. data/sig/datadog/ci/test_visibility/recorder.rbs +85 -0
  59. data/sig/datadog/ci/test_visibility/serializers/base.rbs +26 -5
  60. data/sig/datadog/ci/test_visibility/serializers/factories/test_suite_level.rbs +13 -0
  61. data/sig/datadog/ci/test_visibility/serializers/test_module.rbs +26 -0
  62. data/sig/datadog/ci/test_visibility/serializers/test_session.rbs +26 -0
  63. data/sig/datadog/ci/test_visibility/serializers/test_suite.rbs +26 -0
  64. data/sig/datadog/ci/test_visibility/serializers/test_v1.rbs +1 -1
  65. data/sig/datadog/ci/test_visibility/serializers/test_v2.rbs +25 -0
  66. data/sig/datadog/ci/test_visibility/transport.rbs +3 -3
  67. data/sig/datadog/ci/utils/test_run.rbs +11 -0
  68. data/sig/datadog/ci/utils/url.rbs +9 -0
  69. data/sig/datadog/ci.rbs +31 -3
  70. metadata +38 -6
  71. data/lib/datadog/ci/extensions.rb +0 -19
  72. data/lib/datadog/ci/recorder.rb +0 -83
  73. data/sig/datadog/ci/extensions.rbs +0 -7
  74. data/sig/datadog/ci/recorder.rbs +0 -18
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module TestVisibility
6
+ module Context
7
+ # This context is shared between threads and represents the current test session and test module.
8
+ class Global
9
+ def initialize
10
+ # we are using Monitor instead of Mutex because it is reentrant
11
+ @mutex = Monitor.new
12
+
13
+ @test_session = nil
14
+ @test_module = nil
15
+ @test_suites = {}
16
+ end
17
+
18
+ def fetch_or_activate_test_suite(test_suite_name, &block)
19
+ @mutex.synchronize do
20
+ @test_suites[test_suite_name] ||= block.call
21
+ end
22
+ end
23
+
24
+ def fetch_or_activate_test_module(&block)
25
+ @mutex.synchronize do
26
+ @test_module ||= block.call
27
+ end
28
+ end
29
+
30
+ def fetch_or_activate_test_session(&block)
31
+ @mutex.synchronize do
32
+ @test_session ||= block.call
33
+ end
34
+ end
35
+
36
+ def active_test_module
37
+ @test_module
38
+ end
39
+
40
+ def active_test_session
41
+ @test_session
42
+ end
43
+
44
+ def active_test_suite(test_suite_name)
45
+ @mutex.synchronize { @test_suites[test_suite_name] }
46
+ end
47
+
48
+ def service
49
+ @mutex.synchronize do
50
+ # thank you RBS for this weirdness
51
+ test_session = @test_session
52
+ test_session.service if test_session
53
+ end
54
+ end
55
+
56
+ def inheritable_session_tags
57
+ @mutex.synchronize do
58
+ test_session = @test_session
59
+ if test_session
60
+ test_session.inheritable_tags
61
+ else
62
+ {}
63
+ end
64
+ end
65
+ end
66
+
67
+ def deactivate_test_session!
68
+ @mutex.synchronize { @test_session = nil }
69
+ end
70
+
71
+ def deactivate_test_module!
72
+ @mutex.synchronize { @test_module = nil }
73
+ end
74
+
75
+ def deactivate_test_suite!(test_suite_name)
76
+ @mutex.synchronize { @test_suites.delete(test_suite_name) }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module TestVisibility
6
+ module Context
7
+ class Local
8
+ def initialize
9
+ @key = :datadog_ci_active_test
10
+
11
+ self.active_test = nil
12
+ end
13
+
14
+ def activate_test!(test)
15
+ raise "Nested tests are not supported. Currently active test: #{active_test}" unless active_test.nil?
16
+
17
+ if block_given?
18
+ begin
19
+ self.active_test = test
20
+ yield
21
+ ensure
22
+ self.active_test = nil
23
+ end
24
+ else
25
+ self.active_test = test
26
+ end
27
+ end
28
+
29
+ def deactivate_test!(test)
30
+ return if active_test.nil?
31
+
32
+ if active_test == test
33
+ self.active_test = nil
34
+ else
35
+ raise "Trying to deactivate test #{test}, but currently active test is #{active_test}"
36
+ end
37
+ end
38
+
39
+ def active_test
40
+ Thread.current[@key]
41
+ end
42
+
43
+ private
44
+
45
+ def active_test=(test)
46
+ Thread.current[@key] = test
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,293 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing"
4
+ require "datadog/tracing/trace_digest"
5
+
6
+ require "rbconfig"
7
+
8
+ require_relative "context/global"
9
+ require_relative "context/local"
10
+
11
+ require_relative "../ext/app_types"
12
+ require_relative "../ext/test"
13
+ require_relative "../ext/environment"
14
+
15
+ require_relative "../span"
16
+ require_relative "../null_span"
17
+ require_relative "../test"
18
+ require_relative "../test_session"
19
+ require_relative "../test_module"
20
+ require_relative "../test_suite"
21
+
22
+ module Datadog
23
+ module CI
24
+ module TestVisibility
25
+ # Common behavior for CI tests
26
+ # Note: this class has too many responsibilities and should be split into multiple classes
27
+ class Recorder
28
+ attr_reader :environment_tags, :test_suite_level_visibility_enabled, :enabled
29
+
30
+ def initialize(enabled: true, test_suite_level_visibility_enabled: false)
31
+ @enabled = enabled
32
+ @test_suite_level_visibility_enabled = enabled && test_suite_level_visibility_enabled
33
+
34
+ @environment_tags = @enabled ? Ext::Environment.tags(ENV).freeze : {}
35
+ @local_context = Context::Local.new
36
+ @global_context = Context::Global.new
37
+ end
38
+
39
+ def start_test_session(service: nil, tags: {})
40
+ return skip_tracing unless test_suite_level_visibility_enabled
41
+
42
+ @global_context.fetch_or_activate_test_session do
43
+ tracer_span = start_datadog_tracer_span(
44
+ "test.session", build_span_options(service, Ext::AppTypes::TYPE_TEST_SESSION)
45
+ )
46
+ set_session_context(tags, tracer_span)
47
+
48
+ build_test_session(tracer_span, tags)
49
+ end
50
+ end
51
+
52
+ def start_test_module(test_module_name, service: nil, tags: {})
53
+ return skip_tracing unless test_suite_level_visibility_enabled
54
+
55
+ @global_context.fetch_or_activate_test_module do
56
+ set_inherited_globals(tags)
57
+ set_session_context(tags)
58
+
59
+ tracer_span = start_datadog_tracer_span(
60
+ test_module_name, build_span_options(service, Ext::AppTypes::TYPE_TEST_MODULE)
61
+ )
62
+ set_module_context(tags, tracer_span)
63
+
64
+ build_test_module(tracer_span, tags)
65
+ end
66
+ end
67
+
68
+ def start_test_suite(test_suite_name, service: nil, tags: {})
69
+ return skip_tracing unless test_suite_level_visibility_enabled
70
+
71
+ @global_context.fetch_or_activate_test_suite(test_suite_name) do
72
+ set_inherited_globals(tags)
73
+ set_session_context(tags)
74
+ set_module_context(tags)
75
+
76
+ tracer_span = start_datadog_tracer_span(
77
+ test_suite_name, build_span_options(service, Ext::AppTypes::TYPE_TEST_SUITE)
78
+ )
79
+ set_suite_context(tags, span: tracer_span)
80
+
81
+ build_test_suite(tracer_span, tags)
82
+ end
83
+ end
84
+
85
+ def trace_test(test_name, test_suite_name, service: nil, tags: {}, &block)
86
+ return skip_tracing(block) unless enabled
87
+
88
+ set_inherited_globals(tags)
89
+ set_session_context(tags)
90
+ set_module_context(tags)
91
+ set_suite_context(tags, name: test_suite_name)
92
+
93
+ tags[Ext::Test::TAG_NAME] = test_name
94
+
95
+ span_options = build_span_options(
96
+ service,
97
+ Ext::AppTypes::TYPE_TEST,
98
+ # :resource is needed for the agent APM protocol to work correctly (for older agent versions)
99
+ # :continue_from is required to start a new trace for each test
100
+ {resource: test_name, continue_from: Datadog::Tracing::TraceDigest.new}
101
+ )
102
+
103
+ if block
104
+ start_datadog_tracer_span(test_name, span_options) do |tracer_span|
105
+ test = build_test(tracer_span, tags)
106
+
107
+ @local_context.activate_test!(test) do
108
+ block.call(test)
109
+ end
110
+ end
111
+ else
112
+ tracer_span = start_datadog_tracer_span(test_name, span_options)
113
+
114
+ test = build_test(tracer_span, tags)
115
+ @local_context.activate_test!(test)
116
+ test
117
+ end
118
+ end
119
+
120
+ def trace(span_type, span_name, tags: {}, &block)
121
+ return skip_tracing(block) unless enabled
122
+
123
+ span_options = build_span_options(
124
+ nil, # service name is completely optional for custom spans
125
+ span_type,
126
+ {resource: span_name}
127
+ )
128
+
129
+ if block
130
+ start_datadog_tracer_span(span_name, span_options) do |tracer_span|
131
+ block.call(build_span(tracer_span, tags))
132
+ end
133
+ else
134
+ tracer_span = start_datadog_tracer_span(span_name, span_options)
135
+
136
+ build_span(tracer_span, tags)
137
+ end
138
+ end
139
+
140
+ def active_span
141
+ tracer_span = Datadog::Tracing.active_span
142
+ Span.new(tracer_span) if tracer_span
143
+ end
144
+
145
+ def active_test
146
+ @local_context.active_test
147
+ end
148
+
149
+ def active_test_session
150
+ @global_context.active_test_session
151
+ end
152
+
153
+ def active_test_module
154
+ @global_context.active_test_module
155
+ end
156
+
157
+ def active_test_suite(test_suite_name)
158
+ @global_context.active_test_suite(test_suite_name)
159
+ end
160
+
161
+ def deactivate_test(test)
162
+ @local_context.deactivate_test!(test)
163
+ end
164
+
165
+ def deactivate_test_session
166
+ @global_context.deactivate_test_session!
167
+ end
168
+
169
+ def deactivate_test_module
170
+ @global_context.deactivate_test_module!
171
+ end
172
+
173
+ def deactivate_test_suite(test_suite_name)
174
+ @global_context.deactivate_test_suite!(test_suite_name)
175
+ end
176
+
177
+ private
178
+
179
+ def skip_tracing(block = nil)
180
+ if block
181
+ block.call(null_span)
182
+ else
183
+ null_span
184
+ end
185
+ end
186
+
187
+ # Sets trace's origin to ciapp-test
188
+ def set_trace_origin(trace)
189
+ trace.origin = Ext::Test::CONTEXT_ORIGIN if trace
190
+ end
191
+
192
+ def build_test_session(tracer_span, tags)
193
+ test_session = TestSession.new(tracer_span)
194
+ set_initial_tags(test_session, tags)
195
+ test_session
196
+ end
197
+
198
+ def build_test_module(tracer_span, tags)
199
+ test_module = TestModule.new(tracer_span)
200
+ set_initial_tags(test_module, tags)
201
+ test_module
202
+ end
203
+
204
+ def build_test_suite(tracer_span, tags)
205
+ test_suite = TestSuite.new(tracer_span)
206
+ set_initial_tags(test_suite, tags)
207
+ test_suite
208
+ end
209
+
210
+ def build_test(tracer_span, tags)
211
+ test = Test.new(tracer_span)
212
+ set_initial_tags(test, tags)
213
+ test
214
+ end
215
+
216
+ def build_span(tracer_span, tags)
217
+ span = Span.new(tracer_span)
218
+ set_initial_tags(span, tags)
219
+ span
220
+ end
221
+
222
+ def build_span_options(service, span_type, other_options = {})
223
+ other_options[:service] = service || @global_context.service
224
+ other_options[:span_type] = span_type
225
+
226
+ other_options
227
+ end
228
+
229
+ def set_inherited_globals(tags)
230
+ # this code achieves the same as @global_context.inheritable_session_tags.merge(tags)
231
+ # but without allocating a new hash
232
+ @global_context.inheritable_session_tags.each do |key, value|
233
+ tags[key] = value unless tags.key?(key)
234
+ end
235
+ end
236
+
237
+ def set_initial_tags(ci_span, tags)
238
+ ci_span.set_default_tags
239
+ ci_span.set_environment_runtime_tags
240
+
241
+ ci_span.set_tags(tags)
242
+ ci_span.set_tags(environment_tags)
243
+ end
244
+
245
+ def set_session_context(tags, test_session = nil)
246
+ test_session ||= active_test_session
247
+ tags[Ext::Test::TAG_TEST_SESSION_ID] = test_session.id.to_s if test_session
248
+ end
249
+
250
+ def set_module_context(tags, test_module = nil)
251
+ test_module ||= active_test_module
252
+ if test_module
253
+ tags[Ext::Test::TAG_TEST_MODULE_ID] = test_module.id.to_s
254
+ tags[Ext::Test::TAG_MODULE] = test_module.name
255
+ end
256
+ end
257
+
258
+ def set_suite_context(tags, span: nil, name: nil)
259
+ return if span.nil? && name.nil?
260
+
261
+ test_suite = span || active_test_suite(name)
262
+
263
+ if test_suite
264
+ tags[Ext::Test::TAG_TEST_SUITE_ID] = test_suite.id.to_s
265
+ tags[Ext::Test::TAG_SUITE] = test_suite.name
266
+ else
267
+ tags[Ext::Test::TAG_SUITE] = name
268
+ end
269
+ end
270
+
271
+ def start_datadog_tracer_span(span_name, span_options, &block)
272
+ if block
273
+ Datadog::Tracing.trace(span_name, **span_options) do |tracer_span, trace|
274
+ set_trace_origin(trace)
275
+
276
+ yield tracer_span
277
+ end
278
+ else
279
+ tracer_span = Datadog::Tracing.trace(span_name, **span_options)
280
+ trace = Datadog::Tracing.active_trace
281
+ set_trace_origin(trace)
282
+
283
+ tracer_span
284
+ end
285
+ end
286
+
287
+ def null_span
288
+ @null_span ||= NullSpan.new
289
+ end
290
+ end
291
+ end
292
+ end
293
+ end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+
5
+ require_relative "../../ext/test"
6
+
3
7
  module Datadog
4
8
  module CI
5
9
  module TestVisibility
@@ -9,11 +13,31 @@ module Datadog
9
13
  MINIMUM_DURATION_NANO = 0
10
14
  MAXIMUM_DURATION_NANO = 9223372036854775807
11
15
 
12
- attr_reader :trace, :span
16
+ CONTENT_FIELDS = [
17
+ "name", "resource", "service",
18
+ "error", "start", "duration",
19
+ "meta", "metrics",
20
+ "type" => "span_type"
21
+ ].freeze
22
+
23
+ REQUIRED_FIELDS = [
24
+ "error",
25
+ "name",
26
+ "resource",
27
+ "start",
28
+ "duration"
29
+ ].freeze
30
+
31
+ attr_reader :trace, :span, :meta
13
32
 
14
33
  def initialize(trace, span)
15
34
  @trace = trace
16
35
  @span = span
36
+
37
+ @meta = @span.meta.reject { |key, _| Ext::Test::SPECIAL_TAGS.include?(key) }
38
+
39
+ @errors = {}
40
+ @validated = false
17
41
  end
18
42
 
19
43
  def to_msgpack(packer = nil)
@@ -40,7 +64,23 @@ module Datadog
40
64
 
41
65
  # validates according to citestcycle json schema
42
66
  def valid?
43
- required_fields_present? && valid_start_time? && valid_duration?
67
+ validate! unless @validated
68
+
69
+ @errors.empty?
70
+ end
71
+
72
+ def validate!
73
+ @errors.clear
74
+
75
+ validate_required_fields!
76
+ validate_start_time!
77
+ validate_duration!
78
+
79
+ @validated = true
80
+ end
81
+
82
+ def validation_errors
83
+ @errors
44
84
  end
45
85
 
46
86
  def content_fields
@@ -67,6 +107,18 @@ module Datadog
67
107
  @span.parent_id
68
108
  end
69
109
 
110
+ def test_session_id
111
+ to_integer(@span.get_tag(Ext::Test::TAG_TEST_SESSION_ID))
112
+ end
113
+
114
+ def test_module_id
115
+ to_integer(@span.get_tag(Ext::Test::TAG_TEST_MODULE_ID))
116
+ end
117
+
118
+ def test_suite_id
119
+ to_integer(@span.get_tag(Ext::Test::TAG_TEST_SUITE_ID))
120
+ end
121
+
70
122
  def type
71
123
  end
72
124
 
@@ -98,10 +150,6 @@ module Datadog
98
150
  @duration ||= duration_nano(@span.duration)
99
151
  end
100
152
 
101
- def meta
102
- @span.meta
103
- end
104
-
105
153
  def metrics
106
154
  @span.metrics
107
155
  end
@@ -122,16 +170,48 @@ module Datadog
122
170
 
123
171
  private
124
172
 
125
- def valid_start_time?
126
- !start.nil? && start >= MINIMUM_TIMESTAMP_NANO
173
+ def validate_start_time!
174
+ validate_required!("start")
175
+ validate_greater_than_or_equal!("start", MINIMUM_TIMESTAMP_NANO)
176
+ end
177
+
178
+ def validate_duration!
179
+ validate_required!("duration")
180
+ validate_greater_than_or_equal!("duration", MINIMUM_DURATION_NANO)
181
+ validate_less_than_or_equal!("duration", MAXIMUM_DURATION_NANO)
182
+ end
183
+
184
+ def validate_required_fields!
185
+ required_fields.each do |field|
186
+ validate_required!(field)
187
+ end
127
188
  end
128
189
 
129
- def valid_duration?
130
- !duration.nil? && duration >= MINIMUM_DURATION_NANO && duration <= MAXIMUM_DURATION_NANO
190
+ def validate_required!(field)
191
+ if send(field).nil?
192
+ add_error(field, "is required")
193
+ end
131
194
  end
132
195
 
133
- def required_fields_present?
134
- required_fields.all? { |field| !send(field).nil? }
196
+ def validate_greater_than_or_equal!(field, value)
197
+ return if send(field).nil?
198
+
199
+ if send(field) < value
200
+ add_error(field, "must be greater than or equal to #{value}")
201
+ end
202
+ end
203
+
204
+ def validate_less_than_or_equal!(field, value)
205
+ return if send(field).nil?
206
+
207
+ if send(field) > value
208
+ add_error(field, "must be less than or equal to #{value}")
209
+ end
210
+ end
211
+
212
+ def add_error(field, message)
213
+ @errors[field] ||= Set.new
214
+ @errors[field] << message
135
215
  end
136
216
 
137
217
  def required_fields
@@ -154,6 +234,14 @@ module Datadog
154
234
  def duration_nano(duration)
155
235
  (duration * 1e9).to_i
156
236
  end
237
+
238
+ def to_s
239
+ "#{self.class.name}(id:#{span_id},name:#{name})"
240
+ end
241
+
242
+ def to_integer(value)
243
+ value.to_i if value
244
+ end
157
245
  end
158
246
  end
159
247
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../test_v2"
4
+ require_relative "../test_session"
5
+ require_relative "../test_module"
6
+ require_relative "../test_suite"
7
+ require_relative "../span"
8
+
9
+ module Datadog
10
+ module CI
11
+ module TestVisibility
12
+ module Serializers
13
+ module Factories
14
+ # This factory takes care of creating citestcycle serializers when test-suite-level visibility is enabled
15
+ module TestSuiteLevel
16
+ module_function
17
+
18
+ def serializer(trace, span)
19
+ case span.type
20
+ when Datadog::CI::Ext::AppTypes::TYPE_TEST
21
+ Serializers::TestV2.new(trace, span)
22
+ when Datadog::CI::Ext::AppTypes::TYPE_TEST_SESSION
23
+ Serializers::TestSession.new(trace, span)
24
+ when Datadog::CI::Ext::AppTypes::TYPE_TEST_MODULE
25
+ Serializers::TestModule.new(trace, span)
26
+ when Datadog::CI::Ext::AppTypes::TYPE_TEST_SUITE
27
+ Serializers::TestSuite.new(trace, span)
28
+ else
29
+ Serializers::Span.new(trace, span)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -7,25 +7,11 @@ module Datadog
7
7
  module TestVisibility
8
8
  module Serializers
9
9
  class Span < Base
10
- CONTENT_FIELDS = [
11
- "trace_id", "span_id", "parent_id",
12
- "name", "resource", "service",
13
- "error", "start", "duration",
14
- "meta", "metrics",
15
- "type" => "span_type"
16
- ].freeze
10
+ CONTENT_FIELDS = (["trace_id", "span_id", "parent_id"] + Base::CONTENT_FIELDS).freeze
17
11
 
18
12
  CONTENT_MAP_SIZE = calculate_content_map_size(CONTENT_FIELDS)
19
13
 
20
- REQUIRED_FIELDS = [
21
- "trace_id",
22
- "span_id",
23
- "error",
24
- "name",
25
- "resource",
26
- "start",
27
- "duration"
28
- ].freeze
14
+ REQUIRED_FIELDS = (["trace_id", "span_id"] + Base::REQUIRED_FIELDS).freeze
29
15
 
30
16
  def content_fields
31
17
  CONTENT_FIELDS
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "../../ext/test"
5
+
6
+ module Datadog
7
+ module CI
8
+ module TestVisibility
9
+ module Serializers
10
+ class TestModule < Base
11
+ CONTENT_FIELDS = (["test_session_id", "test_module_id"] + Base::CONTENT_FIELDS).freeze
12
+
13
+ CONTENT_MAP_SIZE = calculate_content_map_size(CONTENT_FIELDS)
14
+
15
+ REQUIRED_FIELDS = (["test_session_id", "test_module_id"] + Base::REQUIRED_FIELDS).freeze
16
+
17
+ def content_fields
18
+ CONTENT_FIELDS
19
+ end
20
+
21
+ def content_map_size
22
+ CONTENT_MAP_SIZE
23
+ end
24
+
25
+ def type
26
+ Ext::AppTypes::TYPE_TEST_MODULE
27
+ end
28
+
29
+ def name
30
+ "#{@span.get_tag(Ext::Test::TAG_FRAMEWORK)}.test_module"
31
+ end
32
+
33
+ def resource
34
+ "#{@span.get_tag(Ext::Test::TAG_FRAMEWORK)}.test_module.#{@span.get_tag(Ext::Test::TAG_MODULE)}"
35
+ end
36
+
37
+ private
38
+
39
+ def required_fields
40
+ REQUIRED_FIELDS
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end