datadog-ci 1.1.0 → 1.3.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/CHANGELOG.md +31 -2
- data/ext/datadog_cov/datadog_cov.c +259 -67
- data/lib/datadog/ci/configuration/components.rb +149 -80
- data/lib/datadog/ci/configuration/settings.rb +6 -0
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +13 -9
- data/lib/datadog/ci/contrib/minitest/runnable.rb +5 -1
- data/lib/datadog/ci/contrib/minitest/runner.rb +6 -2
- data/lib/datadog/ci/contrib/minitest/test.rb +7 -3
- data/lib/datadog/ci/contrib/rspec/example.rb +6 -2
- data/lib/datadog/ci/contrib/rspec/example_group.rb +5 -1
- data/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +6 -2
- data/lib/datadog/ci/contrib/rspec/runner.rb +6 -2
- data/lib/datadog/ci/ext/environment/providers/appveyor.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/aws_code_pipeline.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/azure.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/bitrise.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/buddy.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/buildkite.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/circleci.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/codefresh.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/github_actions.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/gitlab.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/jenkins.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/teamcity.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/travis.rb +1 -1
- data/lib/datadog/ci/ext/environment.rb +17 -0
- data/lib/datadog/ci/ext/settings.rb +1 -0
- data/lib/datadog/ci/ext/telemetry.rb +120 -0
- data/lib/datadog/ci/git/local_repository.rb +116 -25
- data/lib/datadog/ci/git/search_commits.rb +20 -1
- data/lib/datadog/ci/git/telemetry.rb +37 -0
- data/lib/datadog/ci/git/tree_uploader.rb +7 -0
- data/lib/datadog/ci/git/upload_packfile.rb +22 -1
- data/lib/datadog/ci/span.rb +3 -3
- data/lib/datadog/ci/test.rb +6 -1
- data/lib/datadog/ci/test_module.rb +1 -1
- data/lib/datadog/ci/{itr/runner.rb → test_optimisation/component.rb} +29 -12
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/ddcov.rb +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/event.rb +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/transport.rb +11 -2
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/writer.rb +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/skippable.rb +25 -1
- data/lib/datadog/ci/test_optimisation/telemetry.rb +56 -0
- data/lib/datadog/ci/test_session.rb +1 -1
- data/lib/datadog/ci/test_suite.rb +1 -1
- data/lib/datadog/ci/test_visibility/component.rb +282 -0
- data/lib/datadog/ci/test_visibility/{recorder.rb → context.rb} +39 -187
- data/lib/datadog/ci/test_visibility/{null_recorder.rb → null_component.rb} +6 -4
- data/lib/datadog/ci/test_visibility/{context → store}/global.rb +1 -1
- data/lib/datadog/ci/test_visibility/{context → store}/local.rb +1 -1
- data/lib/datadog/ci/test_visibility/telemetry.rb +69 -0
- data/lib/datadog/ci/test_visibility/transport.rb +9 -10
- data/lib/datadog/ci/transport/adapters/net.rb +42 -11
- data/lib/datadog/ci/transport/adapters/net_http_client.rb +17 -0
- data/lib/datadog/ci/transport/adapters/telemetry_webmock_safe_adapter.rb +28 -0
- data/lib/datadog/ci/transport/event_platform_transport.rb +42 -5
- data/lib/datadog/ci/transport/http.rb +49 -21
- data/lib/datadog/ci/transport/remote_settings_api.rb +39 -1
- data/lib/datadog/ci/transport/telemetry.rb +93 -0
- data/lib/datadog/ci/utils/identity.rb +20 -0
- data/lib/datadog/ci/utils/parsing.rb +2 -1
- data/lib/datadog/ci/utils/telemetry.rb +23 -0
- data/lib/datadog/ci/version.rb +1 -1
- data/lib/datadog/ci.rb +45 -15
- metadata +24 -14
@@ -4,87 +4,49 @@ require "datadog/tracing"
|
|
4
4
|
require "datadog/tracing/contrib/component"
|
5
5
|
require "datadog/tracing/trace_digest"
|
6
6
|
|
7
|
-
|
7
|
+
require_relative "store/global"
|
8
|
+
require_relative "store/local"
|
8
9
|
|
9
|
-
require_relative "context/global"
|
10
|
-
require_relative "context/local"
|
11
|
-
|
12
|
-
require_relative "../codeowners/parser"
|
13
|
-
require_relative "../contrib/contrib"
|
14
10
|
require_relative "../ext/app_types"
|
15
|
-
require_relative "../ext/test"
|
16
11
|
require_relative "../ext/environment"
|
17
|
-
require_relative "../
|
12
|
+
require_relative "../ext/test"
|
18
13
|
|
19
14
|
require_relative "../span"
|
20
15
|
require_relative "../test"
|
21
16
|
require_relative "../test_session"
|
22
17
|
require_relative "../test_module"
|
23
18
|
require_relative "../test_suite"
|
24
|
-
require_relative "../worker"
|
25
19
|
|
26
20
|
module Datadog
|
27
21
|
module CI
|
28
22
|
module TestVisibility
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
remote_settings_api:,
|
37
|
-
git_tree_upload_worker: DummyWorker.new,
|
38
|
-
test_suite_level_visibility_enabled: false,
|
39
|
-
codeowners: Codeowners::Parser.new(Git::LocalRepository.root).parse
|
40
|
-
)
|
41
|
-
@test_suite_level_visibility_enabled = test_suite_level_visibility_enabled
|
42
|
-
|
43
|
-
@environment_tags = Ext::Environment.tags(ENV).freeze
|
44
|
-
@local_context = Context::Local.new
|
45
|
-
@global_context = Context::Global.new
|
46
|
-
|
47
|
-
@codeowners = codeowners
|
48
|
-
|
49
|
-
@itr = itr
|
50
|
-
@remote_settings_api = remote_settings_api
|
51
|
-
@git_tree_upload_worker = git_tree_upload_worker
|
52
|
-
end
|
53
|
-
|
54
|
-
def shutdown!
|
55
|
-
@git_tree_upload_worker.stop
|
23
|
+
# Manages current in-memory context for test visibility (such as active test session, suite, test, etc.).
|
24
|
+
# Its responsibility includes building domain models for test visibility as well.
|
25
|
+
# Internally it uses Datadog::Tracing module to create spans.
|
26
|
+
class Context
|
27
|
+
def initialize
|
28
|
+
@local_context = Store::Local.new
|
29
|
+
@global_context = Store::Global.new
|
56
30
|
end
|
57
31
|
|
58
32
|
def start_test_session(service: nil, tags: {})
|
59
|
-
return skip_tracing unless test_suite_level_visibility_enabled
|
60
|
-
|
61
|
-
# finds and instruments additional test libraries that we support (ex: selenium-webdriver)
|
62
|
-
Contrib.auto_instrument_on_session_start!
|
63
|
-
|
64
33
|
@global_context.fetch_or_activate_test_session do
|
65
34
|
tracer_span = start_datadog_tracer_span(
|
66
|
-
"test.session",
|
35
|
+
"test.session", build_tracing_span_options(service, Ext::AppTypes::TYPE_TEST_SESSION)
|
67
36
|
)
|
68
37
|
set_session_context(tags, tracer_span)
|
69
38
|
|
70
|
-
|
71
|
-
|
72
|
-
@git_tree_upload_worker.perform(test_session.git_repository_url)
|
73
|
-
configure_library(test_session)
|
74
|
-
|
75
|
-
test_session
|
39
|
+
build_test_session(tracer_span, tags)
|
76
40
|
end
|
77
41
|
end
|
78
42
|
|
79
43
|
def start_test_module(test_module_name, service: nil, tags: {})
|
80
|
-
return skip_tracing unless test_suite_level_visibility_enabled
|
81
|
-
|
82
44
|
@global_context.fetch_or_activate_test_module do
|
83
45
|
set_inherited_globals(tags)
|
84
46
|
set_session_context(tags)
|
85
47
|
|
86
48
|
tracer_span = start_datadog_tracer_span(
|
87
|
-
test_module_name,
|
49
|
+
test_module_name, build_tracing_span_options(service, Ext::AppTypes::TYPE_TEST_MODULE)
|
88
50
|
)
|
89
51
|
set_module_context(tags, tracer_span)
|
90
52
|
|
@@ -93,15 +55,13 @@ module Datadog
|
|
93
55
|
end
|
94
56
|
|
95
57
|
def start_test_suite(test_suite_name, service: nil, tags: {})
|
96
|
-
return skip_tracing unless test_suite_level_visibility_enabled
|
97
|
-
|
98
58
|
@global_context.fetch_or_activate_test_suite(test_suite_name) do
|
99
59
|
set_inherited_globals(tags)
|
100
60
|
set_session_context(tags)
|
101
61
|
set_module_context(tags)
|
102
62
|
|
103
63
|
tracer_span = start_datadog_tracer_span(
|
104
|
-
test_suite_name,
|
64
|
+
test_suite_name, build_tracing_span_options(service, Ext::AppTypes::TYPE_TEST_SUITE)
|
105
65
|
)
|
106
66
|
set_suite_context(tags, span: tracer_span)
|
107
67
|
|
@@ -118,7 +78,7 @@ module Datadog
|
|
118
78
|
tags[Ext::Test::TAG_NAME] = test_name
|
119
79
|
tags[Ext::Test::TAG_TYPE] ||= Ext::Test::Type::TEST
|
120
80
|
|
121
|
-
span_options =
|
81
|
+
span_options = build_tracing_span_options(
|
122
82
|
service,
|
123
83
|
Ext::AppTypes::TYPE_TEST,
|
124
84
|
# :resource is needed for the agent APM protocol to work correctly (for older agent versions)
|
@@ -131,25 +91,19 @@ module Datadog
|
|
131
91
|
test = build_test(tracer_span, tags)
|
132
92
|
|
133
93
|
@local_context.activate_test(test) do
|
134
|
-
|
135
|
-
res = block.call(test)
|
136
|
-
on_test_finished(test)
|
137
|
-
res
|
94
|
+
block.call(test)
|
138
95
|
end
|
139
96
|
end
|
140
97
|
else
|
141
98
|
tracer_span = start_datadog_tracer_span(test_name, span_options)
|
142
99
|
test = build_test(tracer_span, tags)
|
143
|
-
|
144
100
|
@local_context.activate_test(test)
|
145
|
-
on_test_started(test)
|
146
|
-
|
147
101
|
test
|
148
102
|
end
|
149
103
|
end
|
150
104
|
|
151
105
|
def trace(span_name, type: "span", tags: {}, &block)
|
152
|
-
span_options =
|
106
|
+
span_options = build_tracing_span_options(
|
153
107
|
nil, # service name is completely optional for custom spans
|
154
108
|
type,
|
155
109
|
{resource: span_name}
|
@@ -187,17 +141,15 @@ module Datadog
|
|
187
141
|
@global_context.active_test_suite(test_suite_name)
|
188
142
|
end
|
189
143
|
|
190
|
-
def
|
191
|
-
|
192
|
-
|
144
|
+
def single_active_test_suite
|
145
|
+
@global_context.fetch_single_test_suite
|
146
|
+
end
|
193
147
|
|
148
|
+
def deactivate_test
|
194
149
|
@local_context.deactivate_test
|
195
150
|
end
|
196
151
|
|
197
152
|
def deactivate_test_session
|
198
|
-
test_session = active_test_session
|
199
|
-
on_test_session_finished(test_session) if test_session
|
200
|
-
|
201
153
|
@global_context.deactivate_test_session!
|
202
154
|
end
|
203
155
|
|
@@ -209,47 +161,9 @@ module Datadog
|
|
209
161
|
@global_context.deactivate_test_suite!(test_suite_name)
|
210
162
|
end
|
211
163
|
|
212
|
-
def itr_enabled?
|
213
|
-
@itr.enabled?
|
214
|
-
end
|
215
|
-
|
216
164
|
private
|
217
165
|
|
218
|
-
|
219
|
-
# this will change when EFD is implemented
|
220
|
-
return unless itr_enabled?
|
221
|
-
|
222
|
-
remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
|
223
|
-
# sometimes we can skip code coverage for default branch if there are no changes in the repository
|
224
|
-
# backend needs git metadata uploaded for this test session to check if we can skip code coverage
|
225
|
-
if remote_configuration.require_git?
|
226
|
-
Datadog.logger.debug { "Library configuration endpoint requires git upload to be finished, waiting..." }
|
227
|
-
@git_tree_upload_worker.wait_until_done
|
228
|
-
|
229
|
-
Datadog.logger.debug { "Requesting library configuration again..." }
|
230
|
-
remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
|
231
|
-
|
232
|
-
if remote_configuration.require_git?
|
233
|
-
Datadog.logger.debug { "git metadata upload did not complete in time when configuring library" }
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
@itr.configure(
|
238
|
-
remote_configuration.payload,
|
239
|
-
test_session: test_session,
|
240
|
-
git_tree_upload_worker: @git_tree_upload_worker
|
241
|
-
)
|
242
|
-
end
|
243
|
-
|
244
|
-
def skip_tracing(block = nil)
|
245
|
-
block&.call(nil)
|
246
|
-
end
|
247
|
-
|
248
|
-
# Sets trace's origin to ciapp-test
|
249
|
-
def set_trace_origin(trace)
|
250
|
-
trace&.origin = Ext::Test::CONTEXT_ORIGIN
|
251
|
-
end
|
252
|
-
|
166
|
+
# BUILDING DOMAIN MODELS
|
253
167
|
def build_test_session(tracer_span, tags)
|
254
168
|
test_session = TestSession.new(tracer_span)
|
255
169
|
set_initial_tags(test_session, tags)
|
@@ -271,14 +185,6 @@ module Datadog
|
|
271
185
|
def build_test(tracer_span, tags)
|
272
186
|
test = Test.new(tracer_span)
|
273
187
|
set_initial_tags(test, tags)
|
274
|
-
|
275
|
-
# sometimes test suite is not being assigned correctly
|
276
|
-
# fix it by fetching the one single running test suite from the global context
|
277
|
-
fix_test_suite!(test) if test.test_suite_id.nil?
|
278
|
-
|
279
|
-
validate_test_suite_level_visibility_correctness(test)
|
280
|
-
set_codeowners(test)
|
281
|
-
|
282
188
|
test
|
283
189
|
end
|
284
190
|
|
@@ -288,13 +194,18 @@ module Datadog
|
|
288
194
|
span
|
289
195
|
end
|
290
196
|
|
291
|
-
|
292
|
-
|
293
|
-
|
197
|
+
# TAGGING
|
198
|
+
def set_initial_tags(ci_span, tags)
|
199
|
+
@environment_tags ||= Ext::Environment.tags(ENV).freeze
|
294
200
|
|
295
|
-
|
201
|
+
ci_span.set_default_tags
|
202
|
+
ci_span.set_environment_runtime_tags
|
203
|
+
|
204
|
+
ci_span.set_tags(tags)
|
205
|
+
ci_span.set_tags(@environment_tags)
|
296
206
|
end
|
297
207
|
|
208
|
+
# PROPAGATING CONTEXT FROM TOP-LEVEL TO THE LOWER LEVELS
|
298
209
|
def set_inherited_globals(tags)
|
299
210
|
# this code achieves the same as @global_context.inheritable_session_tags.merge(tags)
|
300
211
|
# but without allocating a new hash
|
@@ -303,14 +214,6 @@ module Datadog
|
|
303
214
|
end
|
304
215
|
end
|
305
216
|
|
306
|
-
def set_initial_tags(ci_span, tags)
|
307
|
-
ci_span.set_default_tags
|
308
|
-
ci_span.set_environment_runtime_tags
|
309
|
-
|
310
|
-
ci_span.set_tags(tags)
|
311
|
-
ci_span.set_tags(environment_tags)
|
312
|
-
end
|
313
|
-
|
314
217
|
def set_session_context(tags, test_session = nil)
|
315
218
|
test_session ||= active_test_session
|
316
219
|
tags[Ext::Test::TAG_TEST_SESSION_ID] = test_session.id.to_s if test_session
|
@@ -324,12 +227,6 @@ module Datadog
|
|
324
227
|
end
|
325
228
|
end
|
326
229
|
|
327
|
-
def set_codeowners(test)
|
328
|
-
source = test.source_file
|
329
|
-
owners = @codeowners.list_owners(source) if source
|
330
|
-
test.set_tag(Ext::Test::TAG_CODEOWNERS, owners) unless owners.nil?
|
331
|
-
end
|
332
|
-
|
333
230
|
def set_suite_context(tags, span: nil, name: nil)
|
334
231
|
return if span.nil? && name.nil?
|
335
232
|
|
@@ -343,24 +240,7 @@ module Datadog
|
|
343
240
|
end
|
344
241
|
end
|
345
242
|
|
346
|
-
|
347
|
-
test_suite = @global_context.fetch_single_test_suite
|
348
|
-
unless test_suite
|
349
|
-
Datadog.logger.debug do
|
350
|
-
"Trying to fix test suite for test [#{test.name}] but no single test suite is running."
|
351
|
-
end
|
352
|
-
return
|
353
|
-
end
|
354
|
-
|
355
|
-
Datadog.logger.debug do
|
356
|
-
"For test [#{test.name}]: expected test suite [#{test.test_suite_name}] to be running, " \
|
357
|
-
"but it was not found. Fixing it by assigning test suite [#{test_suite.name}] to the test."
|
358
|
-
end
|
359
|
-
|
360
|
-
test.set_tag(Ext::Test::TAG_TEST_SUITE_ID, test_suite.id.to_s)
|
361
|
-
test.set_tag(Ext::Test::TAG_SUITE, test_suite.name)
|
362
|
-
end
|
363
|
-
|
243
|
+
# INTERACTIONS WITH TRACING
|
364
244
|
def start_datadog_tracer_span(span_name, span_options, &block)
|
365
245
|
if block
|
366
246
|
Datadog::Tracing.trace(span_name, **span_options) do |tracer_span, trace|
|
@@ -377,44 +257,16 @@ module Datadog
|
|
377
257
|
end
|
378
258
|
end
|
379
259
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
if test.test_suite_id.nil?
|
384
|
-
Datadog.logger.debug do
|
385
|
-
"Test [#{test.name}] does not have a test suite associated with it. " \
|
386
|
-
"Expected test suite [#{test.test_suite_name}] to be running."
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
if test.test_module_id.nil?
|
391
|
-
Datadog.logger.debug do
|
392
|
-
"Test [#{test.name}] does not have a test module associated with it. " \
|
393
|
-
"Make sure that there is a test module running within a session."
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
if test.test_session_id.nil?
|
398
|
-
Datadog.logger.debug do
|
399
|
-
"Test [#{test.name}] does not have a test session associated with it. " \
|
400
|
-
"Make sure that there is a test session running."
|
401
|
-
end
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
# TODO: use kind of event system to notify about test finished?
|
406
|
-
def on_test_finished(test)
|
407
|
-
@itr.stop_coverage(test)
|
408
|
-
@itr.count_skipped_test(test)
|
260
|
+
# Sets trace's origin to ciapp-test because tracing requires so
|
261
|
+
def set_trace_origin(trace)
|
262
|
+
trace&.origin = Ext::Test::CONTEXT_ORIGIN
|
409
263
|
end
|
410
264
|
|
411
|
-
def
|
412
|
-
@
|
413
|
-
|
414
|
-
end
|
265
|
+
def build_tracing_span_options(service, type, other_options = {})
|
266
|
+
other_options[:service] = service || @global_context.service
|
267
|
+
other_options[:type] = type
|
415
268
|
|
416
|
-
|
417
|
-
@itr.write_test_session_tags(test_session)
|
269
|
+
other_options
|
418
270
|
end
|
419
271
|
end
|
420
272
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "recorder"
|
4
|
-
|
5
3
|
module Datadog
|
6
4
|
module CI
|
7
5
|
module TestVisibility
|
8
|
-
# Special
|
9
|
-
class
|
6
|
+
# Special test visibility component that does not record anything
|
7
|
+
class NullComponent
|
10
8
|
def start_test_session(service: nil, tags: {})
|
11
9
|
skip_tracing
|
12
10
|
end
|
@@ -45,6 +43,10 @@ module Datadog
|
|
45
43
|
def shutdown!
|
46
44
|
end
|
47
45
|
|
46
|
+
def itr_enabled?
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
48
50
|
private
|
49
51
|
|
50
52
|
def skip_tracing(block = nil)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../ext/app_types"
|
4
|
+
require_relative "../ext/environment"
|
5
|
+
require_relative "../ext/telemetry"
|
6
|
+
require_relative "../ext/test"
|
7
|
+
require_relative "../utils/telemetry"
|
8
|
+
|
9
|
+
module Datadog
|
10
|
+
module CI
|
11
|
+
module TestVisibility
|
12
|
+
# Telemetry for test visibility
|
13
|
+
module Telemetry
|
14
|
+
SPAN_TYPE_TO_TELEMETRY_EVENT_TYPE = {
|
15
|
+
Ext::AppTypes::TYPE_TEST => Ext::Telemetry::EventType::TEST,
|
16
|
+
Ext::AppTypes::TYPE_TEST_SUITE => Ext::Telemetry::EventType::SUITE,
|
17
|
+
Ext::AppTypes::TYPE_TEST_MODULE => Ext::Telemetry::EventType::MODULE,
|
18
|
+
Ext::AppTypes::TYPE_TEST_SESSION => Ext::Telemetry::EventType::SESSION
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
def self.event_created(span)
|
22
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_EVENT_CREATED, 1, event_tags_from_span(span))
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.event_finished(span)
|
26
|
+
tags = event_tags_from_span(span)
|
27
|
+
add_browser_tags!(span, tags)
|
28
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_EVENT_FINISHED, 1, tags)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.test_session_started(test_session)
|
32
|
+
Utils::Telemetry.inc(
|
33
|
+
Ext::Telemetry::METRIC_TEST_SESSION,
|
34
|
+
1,
|
35
|
+
{
|
36
|
+
Ext::Telemetry::TAG_AUTO_INJECTED => "false", # ruby doesn't support auto injection yet
|
37
|
+
Ext::Telemetry::TAG_PROVIDER =>
|
38
|
+
test_session.get_tag(Ext::Environment::TAG_PROVIDER_NAME) ||
|
39
|
+
Ext::Telemetry::Provider::UNSUPPORTED
|
40
|
+
}
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.event_tags_from_span(span)
|
45
|
+
# base tags for span
|
46
|
+
# @type var tags: Hash[String, String]
|
47
|
+
tags = {
|
48
|
+
Ext::Telemetry::TAG_EVENT_TYPE => SPAN_TYPE_TO_TELEMETRY_EVENT_TYPE.fetch(span.type, "unknown"),
|
49
|
+
Ext::Telemetry::TAG_TEST_FRAMEWORK => span.get_tag(Ext::Test::TAG_FRAMEWORK)
|
50
|
+
}
|
51
|
+
|
52
|
+
# ci provider tag
|
53
|
+
tags[Ext::Telemetry::TAG_IS_UNSUPPORTED_CI] = "true" if span.get_tag(Ext::Environment::TAG_PROVIDER_NAME).nil?
|
54
|
+
|
55
|
+
# codeowner tag
|
56
|
+
tags[Ext::Telemetry::TAG_HAS_CODEOWNER] = "true" if span.get_tag(Ext::Test::TAG_CODEOWNERS)
|
57
|
+
|
58
|
+
tags
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.add_browser_tags!(span, tags)
|
62
|
+
tags[Ext::Telemetry::TAG_IS_RUM] = "true" if span.get_tag(Ext::Test::TAG_IS_RUM_ACTIVE)
|
63
|
+
browser_driver = span.get_tag(Ext::Test::TAG_BROWSER_DRIVER)
|
64
|
+
tags[Ext::Telemetry::TAG_BROWSER_DRIVER] = browser_driver if browser_driver
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -3,8 +3,10 @@
|
|
3
3
|
require "datadog/core/environment/identity"
|
4
4
|
|
5
5
|
require_relative "serializers/factories/test_level"
|
6
|
+
require_relative "../ext/telemetry"
|
6
7
|
require_relative "../ext/transport"
|
7
8
|
require_relative "../transport/event_platform_transport"
|
9
|
+
require_relative "../transport/telemetry"
|
8
10
|
|
9
11
|
module Datadog
|
10
12
|
module CI
|
@@ -31,6 +33,10 @@ module Datadog
|
|
31
33
|
|
32
34
|
private
|
33
35
|
|
36
|
+
def telemetry_endpoint_tag
|
37
|
+
Ext::Telemetry::Endpoint::TEST_CYCLE
|
38
|
+
end
|
39
|
+
|
34
40
|
def send_payload(encoded_payload)
|
35
41
|
api.citestcycle_request(
|
36
42
|
path: Datadog::CI::Ext::Transport::TEST_VISIBILITY_INTAKE_PATH,
|
@@ -46,21 +52,14 @@ module Datadog
|
|
46
52
|
|
47
53
|
def encode_span(trace, span)
|
48
54
|
serializer = serializers_factory.serializer(trace, span, options: {itr_correlation_id: itr&.correlation_id})
|
49
|
-
|
50
55
|
if serializer.valid?
|
51
56
|
encoded = encoder.encode(serializer)
|
52
|
-
|
53
|
-
if encoded.size > max_payload_size
|
54
|
-
# This single event is too large, we can't flush it
|
55
|
-
Datadog.logger.warn("Dropping test event. Payload too large: '#{span.inspect}'")
|
56
|
-
Datadog.logger.warn(encoded)
|
57
|
-
|
58
|
-
return nil
|
59
|
-
end
|
57
|
+
return nil if event_too_large?(span, encoded)
|
60
58
|
|
61
59
|
encoded
|
62
60
|
else
|
63
61
|
Datadog.logger.warn("Invalid event skipped: #{serializer} Errors: #{serializer.validation_errors}")
|
62
|
+
CI::Transport::Telemetry.endpoint_payload_dropped(1, endpoint: telemetry_endpoint_tag)
|
64
63
|
nil
|
65
64
|
end
|
66
65
|
end
|
@@ -100,7 +99,7 @@ module Datadog
|
|
100
99
|
end
|
101
100
|
|
102
101
|
def itr
|
103
|
-
@
|
102
|
+
@test_optimisation ||= Datadog::CI.send(:test_optimisation)
|
104
103
|
end
|
105
104
|
end
|
106
105
|
end
|
@@ -3,7 +3,9 @@
|
|
3
3
|
require "datadog/core/transport/response"
|
4
4
|
require "datadog/core/transport/ext"
|
5
5
|
|
6
|
+
require_relative "net_http_client"
|
6
7
|
require_relative "../gzip"
|
8
|
+
require_relative "../../ext/telemetry"
|
7
9
|
require_relative "../../ext/transport"
|
8
10
|
|
9
11
|
module Datadog
|
@@ -26,7 +28,7 @@ module Datadog
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def open(&block)
|
29
|
-
req =
|
31
|
+
req = NetHttpClient.original_net_http.new(hostname, port)
|
30
32
|
|
31
33
|
req.use_ssl = ssl
|
32
34
|
req.open_timeout = req.read_timeout = timeout
|
@@ -63,6 +65,8 @@ module Datadog
|
|
63
65
|
include Datadog::Core::Transport::Response
|
64
66
|
|
65
67
|
attr_reader :http_response
|
68
|
+
# Stats for telemetry
|
69
|
+
attr_accessor :duration_ms, :request_compressed, :request_size
|
66
70
|
|
67
71
|
def initialize(http_response)
|
68
72
|
@http_response = http_response
|
@@ -77,6 +81,10 @@ module Datadog
|
|
77
81
|
@decompressed_payload = Gzip.decompress(http_response.body)
|
78
82
|
end
|
79
83
|
|
84
|
+
def response_size
|
85
|
+
http_response.body.bytesize
|
86
|
+
end
|
87
|
+
|
80
88
|
def header(name)
|
81
89
|
http_response[name]
|
82
90
|
end
|
@@ -86,7 +94,10 @@ module Datadog
|
|
86
94
|
end
|
87
95
|
|
88
96
|
def ok?
|
89
|
-
code
|
97
|
+
http_code = code
|
98
|
+
return false if http_code.nil?
|
99
|
+
|
100
|
+
http_code.between?(200, 299)
|
90
101
|
end
|
91
102
|
|
92
103
|
def unsupported?
|
@@ -98,11 +109,17 @@ module Datadog
|
|
98
109
|
end
|
99
110
|
|
100
111
|
def client_error?
|
101
|
-
code
|
112
|
+
http_code = code
|
113
|
+
return false if http_code.nil?
|
114
|
+
|
115
|
+
http_code.between?(400, 499)
|
102
116
|
end
|
103
117
|
|
104
118
|
def server_error?
|
105
|
-
code
|
119
|
+
http_code = code
|
120
|
+
return false if http_code.nil?
|
121
|
+
|
122
|
+
http_code.between?(500, 599)
|
106
123
|
end
|
107
124
|
|
108
125
|
def gzipped_content?
|
@@ -119,17 +136,31 @@ module Datadog
|
|
119
136
|
first_bytes.b == Ext::Transport::GZIP_MAGIC_NUMBER
|
120
137
|
end
|
121
138
|
|
122
|
-
def
|
123
|
-
|
139
|
+
def error
|
140
|
+
nil
|
124
141
|
end
|
125
|
-
end
|
126
142
|
|
127
|
-
|
143
|
+
def telemetry_error_type
|
144
|
+
return nil if ok?
|
145
|
+
|
146
|
+
case error
|
147
|
+
when nil
|
148
|
+
Ext::Telemetry::ErrorType::STATUS_CODE
|
149
|
+
when Timeout::Error
|
150
|
+
Ext::Telemetry::ErrorType::TIMEOUT
|
151
|
+
else
|
152
|
+
Ext::Telemetry::ErrorType::NETWORK
|
153
|
+
end
|
154
|
+
end
|
128
155
|
|
129
|
-
|
130
|
-
|
156
|
+
# compatibility with Datadog::Tracing transport layer
|
157
|
+
def trace_count
|
158
|
+
0
|
159
|
+
end
|
131
160
|
|
132
|
-
|
161
|
+
def inspect
|
162
|
+
"#{super}, http_response:#{http_response}"
|
163
|
+
end
|
133
164
|
end
|
134
165
|
end
|
135
166
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module CI
|
5
|
+
module Transport
|
6
|
+
module Adapters
|
7
|
+
module NetHttpClient
|
8
|
+
def self.original_net_http
|
9
|
+
return ::Net::HTTP unless defined?(WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP)
|
10
|
+
|
11
|
+
WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "net_http_client"
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module CI
|
7
|
+
module Transport
|
8
|
+
module Adapters
|
9
|
+
module TelemetryWebmockSafeAdapter
|
10
|
+
def self.included(base)
|
11
|
+
base.prepend(InstanceMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def open(&block)
|
16
|
+
req = NetHttpClient.original_net_http.new(@hostname, @port)
|
17
|
+
|
18
|
+
req.use_ssl = @ssl
|
19
|
+
req.open_timeout = req.read_timeout = @timeout
|
20
|
+
|
21
|
+
req.start(&block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|