datadog-ci 1.2.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 +24 -2
- data/lib/datadog/ci/configuration/components.rb +30 -3
- 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/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/test.rb +5 -0
- data/lib/datadog/ci/test_optimisation/component.rb +16 -2
- data/lib/datadog/ci/test_optimisation/coverage/transport.rb +10 -1
- data/lib/datadog/ci/test_optimisation/skippable.rb +24 -0
- data/lib/datadog/ci/test_optimisation/telemetry.rb +56 -0
- data/lib/datadog/ci/test_visibility/component.rb +95 -235
- data/lib/datadog/ci/test_visibility/context.rb +274 -0
- 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 +8 -9
- 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 +30 -0
- metadata +16 -6
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module CI
|
5
|
+
module Ext
|
6
|
+
module Telemetry
|
7
|
+
NAMESPACE = "civisibility"
|
8
|
+
|
9
|
+
METRIC_EVENT_CREATED = "event_created"
|
10
|
+
METRIC_EVENT_FINISHED = "event_finished"
|
11
|
+
|
12
|
+
METRIC_MANUAL_API_EVENTS = "manual_api_events"
|
13
|
+
|
14
|
+
METRIC_EVENTS_ENQUEUED = "events_enqueued_for_serialization"
|
15
|
+
METRIC_ENDPOINT_PAYLOAD_REQUESTS = "endpoint_payload.requests"
|
16
|
+
METRIC_ENDPOINT_PAYLOAD_REQUESTS_MS = "endpoint_payload.requests_ms"
|
17
|
+
METRIC_ENDPOINT_PAYLOAD_REQUESTS_ERRORS = "endpoint_payload.requests_errors"
|
18
|
+
METRIC_ENDPOINT_PAYLOAD_BYTES = "endpoint_payload.bytes"
|
19
|
+
METRIC_ENDPOINT_PAYLOAD_EVENTS_COUNT = "endpoint_payload.events_count"
|
20
|
+
METRIC_ENDPOINT_PAYLOAD_EVENTS_SERIALIZATION_MS = "endpoint_payload.events_serialization_ms"
|
21
|
+
METRIC_ENDPOINT_PAYLOAD_DROPPED = "endpoint_payload.dropped"
|
22
|
+
|
23
|
+
METRIC_GIT_COMMAND = "git.command"
|
24
|
+
METRIC_GIT_COMMAND_ERRORS = "git.command_errors"
|
25
|
+
METRIC_GIT_COMMAND_MS = "git.command_ms"
|
26
|
+
|
27
|
+
METRIC_GIT_REQUESTS_SEARCH_COMMITS = "git_requests.search_commits"
|
28
|
+
METRIC_GIT_REQUESTS_SEARCH_COMMITS_MS = "git_requests.search_commits_ms"
|
29
|
+
METRIC_GIT_REQUESTS_SEARCH_COMMITS_ERRORS = "git_requests.search_commits_errors"
|
30
|
+
|
31
|
+
METRIC_GIT_REQUESTS_OBJECT_PACK = "git_requests.objects_pack"
|
32
|
+
METRIC_GIT_REQUESTS_OBJECT_PACK_MS = "git_requests.objects_pack_ms"
|
33
|
+
METRIC_GIT_REQUESTS_OBJECT_PACK_ERRORS = "git_requests.objects_pack_errors"
|
34
|
+
METRIC_GIT_REQUESTS_OBJECT_PACK_BYTES = "git_requests.objects_pack_bytes"
|
35
|
+
METRIC_GIT_REQUESTS_OBJECT_PACK_FILES = "git_requests.objects_pack_files"
|
36
|
+
|
37
|
+
METRIC_GIT_REQUESTS_SETTINGS = "git_requests.settings"
|
38
|
+
METRIC_GIT_REQUESTS_SETTINGS_MS = "git_requests.settings_ms"
|
39
|
+
METRIC_GIT_REQUESTS_SETTINGS_ERRORS = "git_requests.settings_errors"
|
40
|
+
METRIC_GIT_REQUESTS_SETTINGS_RESPONSE = "git_requests.settings_response"
|
41
|
+
|
42
|
+
METRIC_ITR_SKIPPABLE_TESTS_REQUEST = "itr_skippable_tests.request"
|
43
|
+
METRIC_ITR_SKIPPABLE_TESTS_REQUEST_MS = "itr_skippable_tests.request_ms"
|
44
|
+
METRIC_ITR_SKIPPABLE_TESTS_REQUEST_ERRORS = "itr_skippable_tests.request_errors"
|
45
|
+
METRIC_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES = "itr_skippable_tests.response_bytes"
|
46
|
+
METRIC_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS = "itr_skippable_tests.response_tests"
|
47
|
+
|
48
|
+
METRIC_ITR_SKIPPED = "itr_skipped"
|
49
|
+
METRIC_ITR_UNSKIPPABLE = "itr_unskippable"
|
50
|
+
METRIC_ITR_FORCED_RUN = "itr_forced_run"
|
51
|
+
|
52
|
+
METRIC_CODE_COVERAGE_STARTED = "code_coverage_started"
|
53
|
+
METRIC_CODE_COVERAGE_FINISHED = "code_coverage_finished"
|
54
|
+
METRIC_CODE_COVERAGE_IS_EMPTY = "code_coverage.is_empty"
|
55
|
+
METRIC_CODE_COVERAGE_FILES = "code_coverage.files"
|
56
|
+
|
57
|
+
METRIC_TEST_SESSION = "test_session"
|
58
|
+
|
59
|
+
TAG_TEST_FRAMEWORK = "test_framework"
|
60
|
+
TAG_EVENT_TYPE = "event_type"
|
61
|
+
TAG_HAS_CODEOWNER = "has_codeowner"
|
62
|
+
TAG_IS_UNSUPPORTED_CI = "is_unsupported_ci"
|
63
|
+
TAG_BROWSER_DRIVER = "browser_driver"
|
64
|
+
TAG_IS_RUM = "is_rum"
|
65
|
+
TAG_LIBRARY = "library"
|
66
|
+
TAG_ENDPOINT = "endpoint"
|
67
|
+
TAG_ERROR_TYPE = "error_type"
|
68
|
+
TAG_EXIT_CODE = "exit_code"
|
69
|
+
TAG_STATUS_CODE = "status_code"
|
70
|
+
TAG_REQUEST_COMPRESSED = "rq_compressed"
|
71
|
+
TAG_RESPONSE_COMPRESSED = "rs_compressed"
|
72
|
+
TAG_COMMAND = "command"
|
73
|
+
TAG_COVERAGE_ENABLED = "coverage_enabled"
|
74
|
+
TAG_ITR_SKIP_ENABLED = "itrskip_enabled"
|
75
|
+
TAG_PROVIDER = "provider"
|
76
|
+
TAG_AUTO_INJECTED = "auto_injected"
|
77
|
+
|
78
|
+
module EventType
|
79
|
+
TEST = "test"
|
80
|
+
SUITE = "suite"
|
81
|
+
MODULE = "module"
|
82
|
+
SESSION = "session"
|
83
|
+
end
|
84
|
+
|
85
|
+
module Library
|
86
|
+
CUSTOM = "custom"
|
87
|
+
end
|
88
|
+
|
89
|
+
module Endpoint
|
90
|
+
CODE_COVERAGE = "code_coverage"
|
91
|
+
TEST_CYCLE = "test_cycle"
|
92
|
+
end
|
93
|
+
|
94
|
+
module ErrorType
|
95
|
+
NETWORK = "network"
|
96
|
+
TIMEOUT = "timeout"
|
97
|
+
STATUS_CODE = "status_code"
|
98
|
+
end
|
99
|
+
|
100
|
+
module ExitCode
|
101
|
+
MISSING = "missing"
|
102
|
+
end
|
103
|
+
|
104
|
+
module Command
|
105
|
+
GET_REPOSITORY = "get_repository"
|
106
|
+
GET_BRANCH = "get_branch"
|
107
|
+
CHECK_SHALLOW = "check_shallow"
|
108
|
+
UNSHALLOW = "unshallow"
|
109
|
+
GET_LOCAL_COMMITS = "get_local_commits"
|
110
|
+
GET_OBJECTS = "get_objects"
|
111
|
+
PACK_OBJECTS = "pack_objects"
|
112
|
+
end
|
113
|
+
|
114
|
+
module Provider
|
115
|
+
UNSUPPORTED = "unsupported"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -3,12 +3,25 @@
|
|
3
3
|
require "open3"
|
4
4
|
require "pathname"
|
5
5
|
|
6
|
+
require_relative "../ext/telemetry"
|
7
|
+
require_relative "telemetry"
|
6
8
|
require_relative "user"
|
7
9
|
|
8
10
|
module Datadog
|
9
11
|
module CI
|
10
12
|
module Git
|
11
13
|
module LocalRepository
|
14
|
+
class GitCommandExecutionError < StandardError
|
15
|
+
attr_reader :output, :command, :status
|
16
|
+
def initialize(message, output:, command:, status:)
|
17
|
+
super(message)
|
18
|
+
|
19
|
+
@output = output
|
20
|
+
@command = command
|
21
|
+
@status = status
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
12
25
|
COMMAND_RETRY_COUNT = 3
|
13
26
|
|
14
27
|
def self.root
|
@@ -48,9 +61,18 @@ module Datadog
|
|
48
61
|
end
|
49
62
|
|
50
63
|
def self.git_repository_url
|
51
|
-
|
64
|
+
Telemetry.git_command(Ext::Telemetry::Command::GET_REPOSITORY)
|
65
|
+
res = nil
|
66
|
+
|
67
|
+
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
68
|
+
res = exec_git_command("git ls-remote --get-url")
|
69
|
+
end
|
70
|
+
|
71
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::GET_REPOSITORY, duration_ms)
|
72
|
+
res
|
52
73
|
rescue => e
|
53
74
|
log_failure(e, "git repository url")
|
75
|
+
telemetry_track_error(e, Ext::Telemetry::Command::GET_REPOSITORY)
|
54
76
|
nil
|
55
77
|
end
|
56
78
|
|
@@ -69,9 +91,18 @@ module Datadog
|
|
69
91
|
end
|
70
92
|
|
71
93
|
def self.git_branch
|
72
|
-
|
94
|
+
Telemetry.git_command(Ext::Telemetry::Command::GET_BRANCH)
|
95
|
+
res = nil
|
96
|
+
|
97
|
+
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
98
|
+
res = exec_git_command("git rev-parse --abbrev-ref HEAD")
|
99
|
+
end
|
100
|
+
|
101
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::GET_BRANCH, duration_ms)
|
102
|
+
res
|
73
103
|
rescue => e
|
74
104
|
log_failure(e, "git branch")
|
105
|
+
telemetry_track_error(e, Ext::Telemetry::Command::GET_BRANCH)
|
75
106
|
nil
|
76
107
|
end
|
77
108
|
|
@@ -116,29 +147,49 @@ module Datadog
|
|
116
147
|
|
117
148
|
# returns maximum of 1000 latest commits in the last month
|
118
149
|
def self.git_commits
|
119
|
-
|
150
|
+
Telemetry.git_command(Ext::Telemetry::Command::GET_LOCAL_COMMITS)
|
151
|
+
|
152
|
+
output = nil
|
153
|
+
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
154
|
+
output = exec_git_command("git log --format=%H -n 1000 --since=\"1 month ago\"")
|
155
|
+
end
|
156
|
+
|
157
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::GET_LOCAL_COMMITS, duration_ms)
|
158
|
+
|
120
159
|
return [] if output.nil?
|
121
160
|
|
161
|
+
# @type var output: String
|
122
162
|
output.split("\n")
|
123
163
|
rescue => e
|
124
164
|
log_failure(e, "git commits")
|
165
|
+
telemetry_track_error(e, Ext::Telemetry::Command::GET_LOCAL_COMMITS)
|
125
166
|
[]
|
126
167
|
end
|
127
168
|
|
128
169
|
def self.git_commits_rev_list(included_commits:, excluded_commits:)
|
170
|
+
Telemetry.git_command(Ext::Telemetry::Command::GET_OBJECTS)
|
129
171
|
included_commits = filter_invalid_commits(included_commits).join(" ")
|
130
172
|
excluded_commits = filter_invalid_commits(excluded_commits).map! { |sha| "^#{sha}" }.join(" ")
|
131
173
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
174
|
+
res = nil
|
175
|
+
|
176
|
+
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
177
|
+
res = exec_git_command(
|
178
|
+
"git rev-list " \
|
179
|
+
"--objects " \
|
180
|
+
"--no-object-names " \
|
181
|
+
"--filter=blob:none " \
|
182
|
+
"--since=\"1 month ago\" " \
|
183
|
+
"#{excluded_commits} #{included_commits}"
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::GET_OBJECTS, duration_ms)
|
188
|
+
|
189
|
+
res
|
140
190
|
rescue => e
|
141
191
|
log_failure(e, "git commits rev list")
|
192
|
+
telemetry_track_error(e, Ext::Telemetry::Command::GET_OBJECTS)
|
142
193
|
nil
|
143
194
|
end
|
144
195
|
|
@@ -150,35 +201,59 @@ module Datadog
|
|
150
201
|
|
151
202
|
basename = SecureRandom.hex(4)
|
152
203
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
204
|
+
Telemetry.git_command(Ext::Telemetry::Command::PACK_OBJECTS)
|
205
|
+
|
206
|
+
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
207
|
+
exec_git_command(
|
208
|
+
"git pack-objects --compression=9 --max-pack-size=3m #{path}/#{basename}",
|
209
|
+
stdin: commit_tree
|
210
|
+
)
|
211
|
+
end
|
212
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::PACK_OBJECTS, duration_ms)
|
157
213
|
|
158
214
|
basename
|
159
215
|
rescue => e
|
160
216
|
log_failure(e, "git generate packfiles")
|
217
|
+
telemetry_track_error(e, Ext::Telemetry::Command::PACK_OBJECTS)
|
161
218
|
nil
|
162
219
|
end
|
163
220
|
|
164
221
|
def self.git_shallow_clone?
|
165
|
-
|
222
|
+
Telemetry.git_command(Ext::Telemetry::Command::CHECK_SHALLOW)
|
223
|
+
res = false
|
224
|
+
|
225
|
+
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
226
|
+
res = exec_git_command("git rev-parse --is-shallow-repository") == "true"
|
227
|
+
end
|
228
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::CHECK_SHALLOW, duration_ms)
|
229
|
+
|
230
|
+
res
|
166
231
|
rescue => e
|
167
232
|
log_failure(e, "git shallow clone")
|
233
|
+
telemetry_track_error(e, Ext::Telemetry::Command::CHECK_SHALLOW)
|
168
234
|
false
|
169
235
|
end
|
170
236
|
|
171
237
|
def self.git_unshallow
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
238
|
+
Telemetry.git_command(Ext::Telemetry::Command::UNSHALLOW)
|
239
|
+
res = nil
|
240
|
+
|
241
|
+
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
242
|
+
res = exec_git_command(
|
243
|
+
"git fetch " \
|
244
|
+
"--shallow-since=\"1 month ago\" " \
|
245
|
+
"--update-shallow " \
|
246
|
+
"--filter=\"blob:none\" " \
|
247
|
+
"--recurse-submodules=no " \
|
248
|
+
"$(git config --default origin --get clone.defaultRemoteName) $(git rev-parse HEAD)"
|
249
|
+
)
|
250
|
+
end
|
251
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::UNSHALLOW, duration_ms)
|
252
|
+
|
253
|
+
res
|
180
254
|
rescue => e
|
181
255
|
log_failure(e, "git unshallow")
|
256
|
+
telemetry_track_error(e, Ext::Telemetry::Command::UNSHALLOW)
|
182
257
|
nil
|
183
258
|
end
|
184
259
|
|
@@ -209,7 +284,12 @@ module Datadog
|
|
209
284
|
end
|
210
285
|
|
211
286
|
if status.nil? || !status.success?
|
212
|
-
raise
|
287
|
+
raise GitCommandExecutionError.new(
|
288
|
+
"Failed to run git command [#{cmd}] with input [#{stdin}] and output [#{out}]",
|
289
|
+
output: out,
|
290
|
+
command: cmd,
|
291
|
+
status: status
|
292
|
+
)
|
213
293
|
end
|
214
294
|
|
215
295
|
# Sometimes Encoding.default_external is somehow set to US-ASCII which breaks
|
@@ -231,6 +311,17 @@ module Datadog
|
|
231
311
|
"Unable to perform #{action}: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
232
312
|
)
|
233
313
|
end
|
314
|
+
|
315
|
+
def telemetry_track_error(e, command)
|
316
|
+
case e
|
317
|
+
when Errno::ENOENT
|
318
|
+
Telemetry.git_command_errors(command, executable_missing: true)
|
319
|
+
when GitCommandExecutionError
|
320
|
+
Telemetry.git_command_errors(command, exit_code: e.status&.to_i)
|
321
|
+
else
|
322
|
+
Telemetry.git_command_errors(command, exit_code: -9000)
|
323
|
+
end
|
324
|
+
end
|
234
325
|
end
|
235
326
|
end
|
236
327
|
end
|
@@ -3,8 +3,11 @@
|
|
3
3
|
require "json"
|
4
4
|
require "set"
|
5
5
|
|
6
|
+
require_relative "../ext/telemetry"
|
6
7
|
require_relative "../ext/transport"
|
8
|
+
require_relative "../transport/telemetry"
|
7
9
|
require_relative "../utils/git"
|
10
|
+
require_relative "../utils/telemetry"
|
8
11
|
|
9
12
|
module Datadog
|
10
13
|
module CI
|
@@ -25,7 +28,23 @@ module Datadog
|
|
25
28
|
path: Ext::Transport::DD_API_GIT_SEARCH_COMMITS_PATH,
|
26
29
|
payload: request_payload(repository_url, commits)
|
27
30
|
)
|
28
|
-
|
31
|
+
|
32
|
+
Transport::Telemetry.api_requests(
|
33
|
+
Ext::Telemetry::METRIC_GIT_REQUESTS_SEARCH_COMMITS,
|
34
|
+
1,
|
35
|
+
compressed: http_response.request_compressed
|
36
|
+
)
|
37
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_GIT_REQUESTS_SEARCH_COMMITS_MS, http_response.duration_ms)
|
38
|
+
|
39
|
+
unless http_response.ok?
|
40
|
+
Transport::Telemetry.api_requests_errors(
|
41
|
+
Ext::Telemetry::METRIC_GIT_REQUESTS_SEARCH_COMMITS_ERRORS,
|
42
|
+
1,
|
43
|
+
error_type: http_response.telemetry_error_type,
|
44
|
+
status_code: http_response.code
|
45
|
+
)
|
46
|
+
raise ApiError, "Failed to search commits: #{http_response.inspect}"
|
47
|
+
end
|
29
48
|
|
30
49
|
response_payload = parse_json_response(http_response)
|
31
50
|
extract_commits(response_payload)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module CI
|
5
|
+
module Git
|
6
|
+
module Telemetry
|
7
|
+
def self.git_command(command)
|
8
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_GIT_COMMAND, 1, tags_for_command(command))
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.git_command_errors(command, exit_code: nil, executable_missing: false)
|
12
|
+
tags = tags_for_command(command)
|
13
|
+
|
14
|
+
exit_code_tag_value = exit_code_for(exit_code: exit_code, executable_missing: executable_missing)
|
15
|
+
tags[Ext::Telemetry::TAG_EXIT_CODE] = exit_code_tag_value if exit_code_tag_value
|
16
|
+
|
17
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_GIT_COMMAND_ERRORS, 1, tags)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.git_command_ms(command, duration_ms)
|
21
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_GIT_COMMAND_MS, duration_ms, tags_for_command(command))
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.tags_for_command(command)
|
25
|
+
{Ext::Telemetry::TAG_COMMAND => command}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.exit_code_for(exit_code: nil, executable_missing: false)
|
29
|
+
return Ext::Telemetry::ExitCode::MISSING if executable_missing
|
30
|
+
return exit_code.to_s if exit_code
|
31
|
+
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -8,6 +8,9 @@ require_relative "search_commits"
|
|
8
8
|
require_relative "upload_packfile"
|
9
9
|
require_relative "packfiles"
|
10
10
|
|
11
|
+
require_relative "../ext/telemetry"
|
12
|
+
require_relative "../utils/telemetry"
|
13
|
+
|
11
14
|
module Datadog
|
12
15
|
module CI
|
13
16
|
module Git
|
@@ -63,12 +66,16 @@ module Datadog
|
|
63
66
|
head_commit_sha: head_commit,
|
64
67
|
repository_url: repository_url
|
65
68
|
)
|
69
|
+
packfiles_count = 0
|
66
70
|
Packfiles.generate(included_commits: new_commits, excluded_commits: known_commits) do |filepath|
|
71
|
+
packfiles_count += 1
|
67
72
|
uploader.call(filepath: filepath)
|
68
73
|
rescue UploadPackfile::ApiError => e
|
69
74
|
Datadog.logger.debug("Packfile upload failed with #{e}")
|
70
75
|
break
|
71
76
|
end
|
77
|
+
|
78
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_GIT_REQUESTS_OBJECT_PACK_FILES, packfiles_count.to_f)
|
72
79
|
ensure
|
73
80
|
Datadog.logger.debug("Git tree upload finished")
|
74
81
|
end
|
@@ -3,6 +3,11 @@
|
|
3
3
|
require "json"
|
4
4
|
require "securerandom"
|
5
5
|
|
6
|
+
require_relative "../ext/transport"
|
7
|
+
require_relative "../ext/telemetry"
|
8
|
+
require_relative "../transport/telemetry"
|
9
|
+
require_relative "../utils/telemetry"
|
10
|
+
|
6
11
|
module Datadog
|
7
12
|
module CI
|
8
13
|
module Git
|
@@ -34,7 +39,23 @@ module Datadog
|
|
34
39
|
headers: {Ext::Transport::HEADER_CONTENT_TYPE => content_type}
|
35
40
|
)
|
36
41
|
|
37
|
-
|
42
|
+
Transport::Telemetry.api_requests(
|
43
|
+
Ext::Telemetry::METRIC_GIT_REQUESTS_OBJECT_PACK,
|
44
|
+
1,
|
45
|
+
compressed: http_response.request_compressed
|
46
|
+
)
|
47
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_GIT_REQUESTS_OBJECT_PACK_MS, http_response.duration_ms)
|
48
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_GIT_REQUESTS_OBJECT_PACK_BYTES, http_response.request_size.to_f)
|
49
|
+
|
50
|
+
unless http_response.ok?
|
51
|
+
Transport::Telemetry.api_requests_errors(
|
52
|
+
Ext::Telemetry::METRIC_GIT_REQUESTS_OBJECT_PACK_ERRORS,
|
53
|
+
1,
|
54
|
+
error_type: http_response.telemetry_error_type,
|
55
|
+
status_code: http_response.code
|
56
|
+
)
|
57
|
+
raise ApiError, "Failed to upload packfile: #{http_response.inspect}"
|
58
|
+
end
|
38
59
|
end
|
39
60
|
|
40
61
|
private
|
data/lib/datadog/ci/test.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "json"
|
4
4
|
|
5
5
|
require_relative "span"
|
6
|
+
require_relative "test_optimisation/telemetry"
|
6
7
|
require_relative "utils/test_run"
|
7
8
|
|
8
9
|
module Datadog
|
@@ -80,9 +81,13 @@ module Datadog
|
|
80
81
|
#
|
81
82
|
# @return [void]
|
82
83
|
def itr_unskippable!
|
84
|
+
TestOptimisation::Telemetry.itr_unskippable
|
83
85
|
set_tag(Ext::Test::TAG_ITR_UNSKIPPABLE, "true")
|
86
|
+
|
84
87
|
if skipped_by_itr?
|
85
88
|
clear_tag(Ext::Test::TAG_ITR_SKIPPED_BY_ITR)
|
89
|
+
|
90
|
+
TestOptimisation::Telemetry.itr_forced_run
|
86
91
|
set_tag(Ext::Test::TAG_ITR_FORCED_RUN, "true")
|
87
92
|
end
|
88
93
|
end
|
@@ -5,14 +5,17 @@ require "pp"
|
|
5
5
|
require "datadog/core/utils/forking"
|
6
6
|
|
7
7
|
require_relative "../ext/test"
|
8
|
+
require_relative "../ext/telemetry"
|
8
9
|
require_relative "../ext/transport"
|
9
10
|
|
10
11
|
require_relative "../git/local_repository"
|
11
12
|
|
12
13
|
require_relative "../utils/parsing"
|
14
|
+
require_relative "../utils/telemetry"
|
13
15
|
|
14
16
|
require_relative "coverage/event"
|
15
17
|
require_relative "skippable"
|
18
|
+
require_relative "telemetry"
|
16
19
|
|
17
20
|
module Datadog
|
18
21
|
module CI
|
@@ -104,15 +107,20 @@ module Datadog
|
|
104
107
|
|
105
108
|
def start_coverage(test)
|
106
109
|
return if !enabled? || !code_coverage?
|
107
|
-
|
110
|
+
Telemetry.code_coverage_started(test)
|
108
111
|
coverage_collector&.start
|
109
112
|
end
|
110
113
|
|
111
114
|
def stop_coverage(test)
|
112
115
|
return if !enabled? || !code_coverage?
|
113
116
|
|
117
|
+
Telemetry.code_coverage_finished(test)
|
118
|
+
|
114
119
|
coverage = coverage_collector&.stop
|
115
|
-
|
120
|
+
if coverage.nil? || coverage.empty?
|
121
|
+
Telemetry.code_coverage_is_empty
|
122
|
+
return
|
123
|
+
end
|
116
124
|
|
117
125
|
return if test.skipped?
|
118
126
|
|
@@ -121,6 +129,8 @@ module Datadog
|
|
121
129
|
# cucumber's gherkin files are not covered by the code coverage collector
|
122
130
|
ensure_test_source_covered(test_source_file, coverage) unless test_source_file.nil?
|
123
131
|
|
132
|
+
Telemetry.code_coverage_files(coverage.size)
|
133
|
+
|
124
134
|
event = Coverage::Event.new(
|
125
135
|
test_id: test.id.to_s,
|
126
136
|
test_suite_id: test.test_suite_id.to_s,
|
@@ -162,6 +172,8 @@ module Datadog
|
|
162
172
|
end
|
163
173
|
|
164
174
|
@mutex.synchronize do
|
175
|
+
Telemetry.itr_skipped
|
176
|
+
|
165
177
|
@skipped_tests_count += 1
|
166
178
|
end
|
167
179
|
end
|
@@ -229,6 +241,8 @@ module Datadog
|
|
229
241
|
Datadog.logger.debug { "Fetched skippable tests: \n #{@skippable_tests}" }
|
230
242
|
Datadog.logger.debug { "Found #{@skippable_tests.count} skippable tests." }
|
231
243
|
Datadog.logger.debug { "ITR correlation ID: #{@correlation_id}" }
|
244
|
+
|
245
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS, @skippable_tests.count)
|
232
246
|
end
|
233
247
|
|
234
248
|
def code_coverage_mode
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "event"
|
4
|
+
require_relative "../../ext/telemetry"
|
4
5
|
require_relative "../../transport/event_platform_transport"
|
6
|
+
require_relative "../../transport/telemetry"
|
5
7
|
|
6
8
|
module Datadog
|
7
9
|
module CI
|
@@ -10,6 +12,10 @@ module Datadog
|
|
10
12
|
class Transport < Datadog::CI::Transport::EventPlatformTransport
|
11
13
|
private
|
12
14
|
|
15
|
+
def telemetry_endpoint_tag
|
16
|
+
Ext::Telemetry::Endpoint::CODE_COVERAGE
|
17
|
+
end
|
18
|
+
|
13
19
|
def send_payload(encoded_payload)
|
14
20
|
api.citestcov_request(
|
15
21
|
path: Ext::Transport::TEST_COVERAGE_INTAKE_PATH,
|
@@ -19,7 +25,10 @@ module Datadog
|
|
19
25
|
|
20
26
|
def encode_events(events)
|
21
27
|
events.filter_map do |event|
|
22
|
-
|
28
|
+
unless event.valid?
|
29
|
+
CI::Transport::Telemetry.endpoint_payload_dropped(1, endpoint: telemetry_endpoint_tag)
|
30
|
+
next
|
31
|
+
end
|
23
32
|
|
24
33
|
encoded = encoder.encode(event)
|
25
34
|
next if event_too_large?(event, encoded)
|
@@ -2,9 +2,12 @@
|
|
2
2
|
|
3
3
|
require "json"
|
4
4
|
|
5
|
+
require_relative "../ext/telemetry"
|
5
6
|
require_relative "../ext/transport"
|
6
7
|
require_relative "../ext/test"
|
8
|
+
require_relative "../transport/telemetry"
|
7
9
|
require_relative "../utils/test_run"
|
10
|
+
require_relative "../utils/telemetry"
|
8
11
|
|
9
12
|
module Datadog
|
10
13
|
module CI
|
@@ -75,6 +78,27 @@ module Datadog
|
|
75
78
|
payload: request_payload
|
76
79
|
)
|
77
80
|
|
81
|
+
Transport::Telemetry.api_requests(
|
82
|
+
Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_REQUEST,
|
83
|
+
1,
|
84
|
+
compressed: http_response.request_compressed
|
85
|
+
)
|
86
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_REQUEST_MS, http_response.duration_ms)
|
87
|
+
Utils::Telemetry.distribution(
|
88
|
+
Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES,
|
89
|
+
http_response.response_size.to_f,
|
90
|
+
{Ext::Telemetry::TAG_RESPONSE_COMPRESSED => http_response.gzipped_content?.to_s}
|
91
|
+
)
|
92
|
+
|
93
|
+
unless http_response.ok?
|
94
|
+
Transport::Telemetry.api_requests_errors(
|
95
|
+
Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_REQUEST_ERRORS,
|
96
|
+
1,
|
97
|
+
error_type: http_response.telemetry_error_type,
|
98
|
+
status_code: http_response.code
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
78
102
|
Response.new(http_response)
|
79
103
|
end
|
80
104
|
|