datadog-ci 0.3.0 → 0.5.1

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.
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