datadog-ci 1.15.0 → 1.16.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 +17 -2
- data/lib/datadog/ci/async_writer.rb +112 -0
- data/lib/datadog/ci/configuration/components.rb +34 -5
- data/lib/datadog/ci/configuration/settings.rb +11 -0
- data/lib/datadog/ci/contrib/activesupport/configuration/settings.rb +25 -0
- data/lib/datadog/ci/contrib/activesupport/ext.rb +14 -0
- data/lib/datadog/ci/contrib/activesupport/integration.rb +43 -0
- data/lib/datadog/ci/contrib/activesupport/logs_formatter.rb +41 -0
- data/lib/datadog/ci/contrib/activesupport/patcher.rb +50 -0
- data/lib/datadog/ci/contrib/lograge/configuration/settings.rb +25 -0
- data/lib/datadog/ci/contrib/lograge/ext.rb +14 -0
- data/lib/datadog/ci/contrib/lograge/integration.rb +43 -0
- data/lib/datadog/ci/contrib/lograge/log_subscriber.rb +41 -0
- data/lib/datadog/ci/contrib/lograge/patcher.rb +32 -0
- data/lib/datadog/ci/contrib/parallel_tests/patcher.rb +0 -1
- data/lib/datadog/ci/contrib/semantic_logger/configuration/settings.rb +25 -0
- data/lib/datadog/ci/contrib/semantic_logger/ext.rb +14 -0
- data/lib/datadog/ci/contrib/semantic_logger/integration.rb +42 -0
- data/lib/datadog/ci/contrib/semantic_logger/logger.rb +32 -0
- data/lib/datadog/ci/contrib/semantic_logger/patcher.rb +32 -0
- data/lib/datadog/ci/ext/settings.rb +2 -0
- data/lib/datadog/ci/ext/test.rb +3 -2
- data/lib/datadog/ci/ext/transport.rb +2 -0
- data/lib/datadog/ci/logs/component.rb +46 -0
- data/lib/datadog/ci/logs/transport.rb +73 -0
- data/lib/datadog/ci/test.rb +10 -0
- data/lib/datadog/ci/test_retries/driver/retry_new.rb +1 -1
- data/lib/datadog/ci/test_visibility/null_component.rb +3 -1
- data/lib/datadog/ci/transport/api/agentless.rb +8 -1
- data/lib/datadog/ci/transport/api/base.rb +4 -0
- data/lib/datadog/ci/transport/api/builder.rb +5 -1
- data/lib/datadog/ci/transport/api/evp_proxy.rb +4 -0
- data/lib/datadog/ci/version.rb +1 -1
- data/lib/datadog/ci.rb +3 -0
- metadata +20 -3
- data/lib/datadog/ci/test_optimisation/coverage/writer.rb +0 -116
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f7cf7ed07d7a4543498333996a19347f64010eef7900f53d5790ad6e4fe2aaf
|
4
|
+
data.tar.gz: 7b3ebdaaf30c557ac23f3720f72ef56ab1b9c1f9686e8f62dc597e3c938cfe35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9412f518c4bba62d062448950f10b956abebe22e33680341454f60f67fd48c25b155d9e0ed3f7d378bcb33f21ee0fa586bee2ff03f3a2ad3f4b753a8a24bb36c
|
7
|
+
data.tar.gz: eb8710ab135550d9c26e1742aefb5ebb05b2c8a1f91e9175e44b0181c4934f1ff5453749820b8720e1febe5c79502e2489d46442f80c4836e56a394c931f7143
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.16.0] - 2025-04-15
|
4
|
+
|
5
|
+
|
6
|
+
### Added
|
7
|
+
|
8
|
+
* agentless logs submission for tests ([#306][])
|
9
|
+
* lograge support for agentless logs feature ([#308][])
|
10
|
+
* semantic_logger instrumentation for agentless logs feature ([#311][])
|
11
|
+
* retry reason "external" ([#312][])
|
12
|
+
|
3
13
|
## [1.15.0] - 2025-03-25
|
4
14
|
|
5
15
|
|
@@ -417,7 +427,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
417
427
|
|
418
428
|
- Ruby versions < 2.7 no longer supported ([#8][])
|
419
429
|
|
420
|
-
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.
|
430
|
+
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.16.0...main
|
431
|
+
[1.16.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.15.0...v1.16.0
|
421
432
|
[1.15.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.14.0...v1.15.0
|
422
433
|
[1.14.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.13.0...v1.14.0
|
423
434
|
[1.13.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.12.0...v1.13.0
|
@@ -597,4 +608,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
597
608
|
[#298]: https://github.com/DataDog/datadog-ci-rb/issues/298
|
598
609
|
[#299]: https://github.com/DataDog/datadog-ci-rb/issues/299
|
599
610
|
[#300]: https://github.com/DataDog/datadog-ci-rb/issues/300
|
600
|
-
[#301]: https://github.com/DataDog/datadog-ci-rb/issues/301
|
611
|
+
[#301]: https://github.com/DataDog/datadog-ci-rb/issues/301
|
612
|
+
[#306]: https://github.com/DataDog/datadog-ci-rb/issues/306
|
613
|
+
[#308]: https://github.com/DataDog/datadog-ci-rb/issues/308
|
614
|
+
[#311]: https://github.com/DataDog/datadog-ci-rb/issues/311
|
615
|
+
[#312]: https://github.com/DataDog/datadog-ci-rb/issues/312
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "datadog/core/workers/async"
|
4
|
+
require "datadog/core/workers/queue"
|
5
|
+
require "datadog/core/workers/polling"
|
6
|
+
|
7
|
+
require "datadog/core/buffer/cruby"
|
8
|
+
require "datadog/core/buffer/thread_safe"
|
9
|
+
|
10
|
+
require "datadog/core/environment/ext"
|
11
|
+
|
12
|
+
module Datadog
|
13
|
+
module CI
|
14
|
+
class AsyncWriter
|
15
|
+
include Core::Workers::Queue
|
16
|
+
include Core::Workers::Polling
|
17
|
+
|
18
|
+
attr_reader :transport
|
19
|
+
|
20
|
+
DEFAULT_BUFFER_MAX_SIZE = 10_000
|
21
|
+
DEFAULT_SHUTDOWN_TIMEOUT = 60
|
22
|
+
|
23
|
+
DEFAULT_INTERVAL = 3
|
24
|
+
|
25
|
+
def initialize(transport:, options: {})
|
26
|
+
@transport = transport
|
27
|
+
|
28
|
+
# Workers::Polling settings
|
29
|
+
self.enabled = options.fetch(:enabled, true)
|
30
|
+
|
31
|
+
# Workers::Async::Thread settings
|
32
|
+
self.fork_policy = Core::Workers::Async::Thread::FORK_POLICY_RESTART
|
33
|
+
|
34
|
+
# Workers::IntervalLoop settings
|
35
|
+
self.loop_base_interval = options[:interval] || DEFAULT_INTERVAL
|
36
|
+
self.loop_back_off_ratio = options[:back_off_ratio] if options.key?(:back_off_ratio)
|
37
|
+
self.loop_back_off_max = options[:back_off_max] if options.key?(:back_off_max)
|
38
|
+
|
39
|
+
@buffer_size = options.fetch(:buffer_size, DEFAULT_BUFFER_MAX_SIZE)
|
40
|
+
|
41
|
+
self.buffer = buffer_klass.new(@buffer_size)
|
42
|
+
|
43
|
+
@shutdown_timeout = options.fetch(:shutdown_timeout, DEFAULT_SHUTDOWN_TIMEOUT)
|
44
|
+
|
45
|
+
@stopped = false
|
46
|
+
end
|
47
|
+
|
48
|
+
def write(event)
|
49
|
+
return if @stopped
|
50
|
+
|
51
|
+
# Start worker thread. If the process has forked, it will trigger #after_fork to
|
52
|
+
# reconfigure the worker accordingly.
|
53
|
+
perform
|
54
|
+
|
55
|
+
enqueue(event)
|
56
|
+
end
|
57
|
+
|
58
|
+
def perform(*events)
|
59
|
+
responses = transport.send_events(events)
|
60
|
+
|
61
|
+
if responses.find(&:server_error?)
|
62
|
+
loop_back_off!
|
63
|
+
Datadog.logger.warn { "Encountered server error while sending events: #{responses}" }
|
64
|
+
end
|
65
|
+
|
66
|
+
nil
|
67
|
+
rescue => e
|
68
|
+
Datadog.logger.warn { "Error while sending events: #{e}" }
|
69
|
+
loop_back_off!
|
70
|
+
end
|
71
|
+
|
72
|
+
def stop(force_stop = false, timeout = @shutdown_timeout)
|
73
|
+
@stopped = true
|
74
|
+
|
75
|
+
buffer.close if running?
|
76
|
+
|
77
|
+
super
|
78
|
+
end
|
79
|
+
|
80
|
+
def enqueue(event)
|
81
|
+
buffer.push(event)
|
82
|
+
end
|
83
|
+
|
84
|
+
def dequeue
|
85
|
+
buffer.pop
|
86
|
+
end
|
87
|
+
|
88
|
+
def work_pending?
|
89
|
+
!buffer.empty?
|
90
|
+
end
|
91
|
+
|
92
|
+
def async?
|
93
|
+
true
|
94
|
+
end
|
95
|
+
|
96
|
+
def after_fork
|
97
|
+
# In multiprocess environments, forks will share the same buffer until its written to.
|
98
|
+
# A.K.A. copy-on-write. We don't want forks to write events generated from another process.
|
99
|
+
# Instead, we reset it after the fork. (Make sure any enqueue operations happen after this.)
|
100
|
+
self.buffer = buffer_klass.new(@buffer_size)
|
101
|
+
end
|
102
|
+
|
103
|
+
def buffer_klass
|
104
|
+
if Core::Environment::Ext::RUBY_ENGINE == "ruby"
|
105
|
+
Core::Buffer::CRuby
|
106
|
+
else
|
107
|
+
Core::Buffer::ThreadSafe
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -4,6 +4,8 @@ require "datadog/core/telemetry/ext"
|
|
4
4
|
|
5
5
|
require_relative "../ext/settings"
|
6
6
|
require_relative "../git/tree_uploader"
|
7
|
+
require_relative "../logs/component"
|
8
|
+
require_relative "../logs/transport"
|
7
9
|
require_relative "../remote/component"
|
8
10
|
require_relative "../remote/library_settings_client"
|
9
11
|
require_relative "../test_management/component"
|
@@ -11,7 +13,6 @@ require_relative "../test_management/null_component"
|
|
11
13
|
require_relative "../test_management/tests_properties"
|
12
14
|
require_relative "../test_optimisation/component"
|
13
15
|
require_relative "../test_optimisation/coverage/transport"
|
14
|
-
require_relative "../test_optimisation/coverage/writer"
|
15
16
|
require_relative "../test_retries/component"
|
16
17
|
require_relative "../test_retries/null_component"
|
17
18
|
require_relative "../test_visibility/component"
|
@@ -20,12 +21,13 @@ require_relative "../test_visibility/known_tests"
|
|
20
21
|
require_relative "../test_visibility/null_component"
|
21
22
|
require_relative "../test_visibility/serializers/factories/test_level"
|
22
23
|
require_relative "../test_visibility/serializers/factories/test_suite_level"
|
24
|
+
require_relative "../test_visibility/null_transport"
|
23
25
|
require_relative "../test_visibility/transport"
|
24
26
|
require_relative "../transport/adapters/telemetry_webmock_safe_adapter"
|
25
|
-
require_relative "../test_visibility/null_transport"
|
26
27
|
require_relative "../transport/api/builder"
|
27
28
|
require_relative "../utils/parsing"
|
28
29
|
require_relative "../utils/test_run"
|
30
|
+
require_relative "../async_writer"
|
29
31
|
require_relative "../worker"
|
30
32
|
|
31
33
|
module Datadog
|
@@ -33,7 +35,8 @@ module Datadog
|
|
33
35
|
module Configuration
|
34
36
|
# Adds CI behavior to Datadog trace components
|
35
37
|
module Components
|
36
|
-
attr_reader :test_visibility, :test_optimisation, :git_tree_upload_worker, :ci_remote, :test_retries,
|
38
|
+
attr_reader :test_visibility, :test_optimisation, :git_tree_upload_worker, :ci_remote, :test_retries,
|
39
|
+
:test_management, :agentless_logs_submission
|
37
40
|
|
38
41
|
def initialize(settings)
|
39
42
|
@test_optimisation = nil
|
@@ -56,6 +59,7 @@ module Datadog
|
|
56
59
|
|
57
60
|
@test_visibility&.shutdown!
|
58
61
|
@test_optimisation&.shutdown!
|
62
|
+
@agentless_logs_submission&.shutdown!
|
59
63
|
@git_tree_upload_worker&.stop
|
60
64
|
end
|
61
65
|
|
@@ -132,6 +136,8 @@ module Datadog
|
|
132
136
|
known_tests_client: build_known_tests_client(settings, test_visibility_api),
|
133
137
|
context_service_uri: settings.ci.test_visibility_drb_server_uri
|
134
138
|
)
|
139
|
+
|
140
|
+
@agentless_logs_submission = build_agentless_logs_component(settings, test_visibility_api)
|
135
141
|
end
|
136
142
|
|
137
143
|
def build_test_optimisation(settings, test_visibility_api)
|
@@ -224,7 +230,7 @@ module Datadog
|
|
224
230
|
# nil means that coverage event will be ignored
|
225
231
|
return nil if api.nil? || settings.ci.discard_traces
|
226
232
|
|
227
|
-
|
233
|
+
AsyncWriter.new(
|
228
234
|
transport: TestOptimisation::Coverage::Transport.new(api: api)
|
229
235
|
)
|
230
236
|
end
|
@@ -256,6 +262,29 @@ module Datadog
|
|
256
262
|
)
|
257
263
|
end
|
258
264
|
|
265
|
+
def build_agentless_logs_component(settings, api)
|
266
|
+
if settings.ci.agentless_logs_submission_enabled && !settings.ci.agentless_mode_enabled
|
267
|
+
Datadog.logger.warn(
|
268
|
+
"Agentless logs submission is enabled but agentless mode is not enabled. " \
|
269
|
+
"Logs will not be submitted. " \
|
270
|
+
"Please make sure to set DD_CIVISIBILITY_AGENTLESS_ENABLED to true if you want to submit logs in agentless mode. " \
|
271
|
+
"Otherwise, set DD_AGENTLESS_LOG_SUBMISSION_ENABLED to 0 and use Datadog Agent to submit logs."
|
272
|
+
)
|
273
|
+
settings.ci.agentless_logs_submission_enabled = false
|
274
|
+
end
|
275
|
+
|
276
|
+
Logs::Component.new(
|
277
|
+
enabled: settings.ci.agentless_logs_submission_enabled,
|
278
|
+
writer: build_logs_writer(settings, api)
|
279
|
+
)
|
280
|
+
end
|
281
|
+
|
282
|
+
def build_logs_writer(settings, api)
|
283
|
+
return nil if api.nil? || settings.ci.discard_traces
|
284
|
+
|
285
|
+
AsyncWriter.new(transport: Logs::Transport.new(api: api), options: {buffer_size: 1024})
|
286
|
+
end
|
287
|
+
|
259
288
|
# fetch custom tags provided by the user in DD_TAGS env var
|
260
289
|
# with prefix test.configuration.
|
261
290
|
def custom_configuration(settings)
|
@@ -298,7 +327,7 @@ module Datadog
|
|
298
327
|
|
299
328
|
# patch gem's telemetry transport layer to use Net::HTTP instead of WebMock's Net::HTTP
|
300
329
|
Core::Telemetry::Http::Adapters::Net.include(CI::Transport::Adapters::TelemetryWebmockSafeAdapter)
|
301
|
-
rescue => e
|
330
|
+
rescue LoadError, StandardError => e
|
302
331
|
Datadog.logger.warn("Failed to patch Datadog gem's telemetry layer: #{e}")
|
303
332
|
end
|
304
333
|
end
|
@@ -128,6 +128,17 @@ module Datadog
|
|
128
128
|
o.default 20
|
129
129
|
end
|
130
130
|
|
131
|
+
option :agentless_logs_submission_enabled do |o|
|
132
|
+
o.type :bool
|
133
|
+
o.env CI::Ext::Settings::ENV_AGENTLESS_LOGS_SUBMISSION_ENABLED
|
134
|
+
o.default false
|
135
|
+
end
|
136
|
+
|
137
|
+
option :agentless_logs_submission_url do |o|
|
138
|
+
o.type :string, nilable: true
|
139
|
+
o.env CI::Ext::Settings::ENV_AGENTLESS_LOGS_SUBMISSION_URL
|
140
|
+
end
|
141
|
+
|
131
142
|
# internal only
|
132
143
|
option :discard_traces do |o|
|
133
144
|
o.type :bool
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../ext"
|
4
|
+
require_relative "../../settings"
|
5
|
+
require_relative "../../../utils/configuration"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module ActiveSupport
|
11
|
+
module Configuration
|
12
|
+
# Custom settings for the ActiveSupport integration
|
13
|
+
# @public_api
|
14
|
+
class Settings < Datadog::CI::Contrib::Settings
|
15
|
+
option :enabled do |o|
|
16
|
+
o.type :bool
|
17
|
+
o.env Ext::ENV_ENABLED
|
18
|
+
o.default true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../integration"
|
4
|
+
require_relative "configuration/settings"
|
5
|
+
require_relative "patcher"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module ActiveSupport
|
11
|
+
# Description of ActiveSupport integration
|
12
|
+
class Integration < Datadog::CI::Contrib::Integration
|
13
|
+
MINIMUM_VERSION = Gem::Version.new("5.0")
|
14
|
+
|
15
|
+
def version
|
16
|
+
Gem.loaded_specs["activesupport"]&.version
|
17
|
+
end
|
18
|
+
|
19
|
+
def loaded?
|
20
|
+
!defined?(::Rails).nil? && !defined?(::ActiveSupport).nil? && !defined?(::ActiveSupport::TaggedLogging).nil? &&
|
21
|
+
!defined?(::ActiveSupport::TaggedLogging::Formatter).nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def compatible?
|
25
|
+
super && version >= MINIMUM_VERSION
|
26
|
+
end
|
27
|
+
|
28
|
+
def late_instrument?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_configuration
|
33
|
+
Configuration::Settings.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def patcher
|
37
|
+
Patcher
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module CI
|
5
|
+
module Contrib
|
6
|
+
module ActiveSupport
|
7
|
+
module LogsFormatter
|
8
|
+
def call(severity, timestamp, progname, msg)
|
9
|
+
# don't even construct an object for every log message if agentless logs submission is not enabled
|
10
|
+
return super unless datadog_logs_component.enabled
|
11
|
+
return super unless datadog_configuration[:enabled]
|
12
|
+
|
13
|
+
# additional precaution because we cannot use targeted prepend in Ruby 2.7, so method :tags_text might
|
14
|
+
# not be available (highly unlikely, but not unimaginable)
|
15
|
+
#
|
16
|
+
# (see Datadog::CI::Contrib::ActiveSupport::Patcher for explanation)
|
17
|
+
return super unless respond_to?(:tags_text)
|
18
|
+
|
19
|
+
message = "#{msg} #{tags_text}"
|
20
|
+
return super unless message.include?("dd.trace_id")
|
21
|
+
|
22
|
+
datadog_logs_component.write({
|
23
|
+
message: message,
|
24
|
+
level: severity
|
25
|
+
})
|
26
|
+
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def datadog_logs_component
|
31
|
+
Datadog.send(:components).agentless_logs_submission
|
32
|
+
end
|
33
|
+
|
34
|
+
def datadog_configuration
|
35
|
+
Datadog.configuration.ci[:activesupport]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../patcher"
|
4
|
+
require_relative "logs_formatter"
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module CI
|
8
|
+
module Contrib
|
9
|
+
module ActiveSupport
|
10
|
+
# Patcher enables patching of activesupport module
|
11
|
+
module Patcher
|
12
|
+
include Datadog::CI::Contrib::Patcher
|
13
|
+
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def patch
|
17
|
+
unless datadog_logs_component.enabled
|
18
|
+
Datadog.logger.debug("Datadog logs submission is disabled, skipping activesupport patching")
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
unless ::Rails.logger.formatter.is_a?(::ActiveSupport::TaggedLogging::Formatter)
|
23
|
+
Datadog.logger.debug {
|
24
|
+
"Rails logger formatter is not an instance of ActiveSupport::TaggedLogging::Formatter, skipping activesupport patching. " \
|
25
|
+
"Formatter: #{::Rails.logger.formatter.class}"
|
26
|
+
}
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
# Before Ruby 3.0, prepending to a module did not change existing instances where this module was included
|
31
|
+
# It means that for Ruby 2.7 we have to patch formatter's class directly
|
32
|
+
#
|
33
|
+
# Context:
|
34
|
+
# - https://bugs.ruby-lang.org/issues/9573
|
35
|
+
# - https://rubyreferences.github.io/rubychanges/3.0.html#include-and-prepend-now-affects-modules-including-the-receiver
|
36
|
+
if RUBY_VERSION.start_with?("2.7")
|
37
|
+
Rails.logger.formatter.class.prepend(LogsFormatter)
|
38
|
+
else
|
39
|
+
::ActiveSupport::TaggedLogging::Formatter.prepend(LogsFormatter)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def datadog_logs_component
|
44
|
+
Datadog.send(:components).agentless_logs_submission
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../ext"
|
4
|
+
require_relative "../../settings"
|
5
|
+
require_relative "../../../utils/configuration"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module Lograge
|
11
|
+
module Configuration
|
12
|
+
# Custom settings for the Lograge integration
|
13
|
+
# @public_api
|
14
|
+
class Settings < Datadog::CI::Contrib::Settings
|
15
|
+
option :enabled do |o|
|
16
|
+
o.type :bool
|
17
|
+
o.env Ext::ENV_ENABLED
|
18
|
+
o.default true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../integration"
|
4
|
+
require_relative "configuration/settings"
|
5
|
+
require_relative "patcher"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module Lograge
|
11
|
+
# Description of Lograge integration
|
12
|
+
class Integration < Datadog::CI::Contrib::Integration
|
13
|
+
MINIMUM_VERSION = Gem::Version.new("0.14.0")
|
14
|
+
|
15
|
+
def version
|
16
|
+
Gem.loaded_specs["lograge"]&.version
|
17
|
+
end
|
18
|
+
|
19
|
+
def loaded?
|
20
|
+
!defined?(::Lograge).nil? && !defined?(::Lograge::LogSubscribers).nil? &&
|
21
|
+
!defined?(::Lograge::LogSubscribers::Base).nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def compatible?
|
25
|
+
super && version && version >= MINIMUM_VERSION
|
26
|
+
end
|
27
|
+
|
28
|
+
def late_instrument?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_configuration
|
33
|
+
Configuration::Settings.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def patcher
|
37
|
+
Patcher
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module CI
|
5
|
+
module Contrib
|
6
|
+
module Lograge
|
7
|
+
module LogSubscriber
|
8
|
+
def self.included(base)
|
9
|
+
base.prepend(InstanceMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
private
|
14
|
+
|
15
|
+
def before_format(data, payload)
|
16
|
+
return super unless datadog_logs_component.enabled
|
17
|
+
return super unless datadog_configuration[:enabled]
|
18
|
+
|
19
|
+
result = super
|
20
|
+
|
21
|
+
if result.fetch(:dd, {}).fetch(:trace_id, nil).nil?
|
22
|
+
Datadog.logger.debug { "Discarding uncorrelated log event: #{result.inspect}" }
|
23
|
+
return result
|
24
|
+
end
|
25
|
+
datadog_logs_component.write(result)
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
def datadog_logs_component
|
30
|
+
Datadog.send(:components).agentless_logs_submission
|
31
|
+
end
|
32
|
+
|
33
|
+
def datadog_configuration
|
34
|
+
Datadog.configuration.ci[:lograge]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../patcher"
|
4
|
+
require_relative "log_subscriber"
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module CI
|
8
|
+
module Contrib
|
9
|
+
module Lograge
|
10
|
+
# Patcher enables patching of lograge module
|
11
|
+
module Patcher
|
12
|
+
include Datadog::CI::Contrib::Patcher
|
13
|
+
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def patch
|
17
|
+
unless datadog_logs_component.enabled
|
18
|
+
Datadog.logger.debug("Datadog logs submission is disabled, skipping lograge patching")
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
::Lograge::LogSubscribers::Base.include(LogSubscriber)
|
23
|
+
end
|
24
|
+
|
25
|
+
def datadog_logs_component
|
26
|
+
Datadog.send(:components).agentless_logs_submission
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../ext"
|
4
|
+
require_relative "../../settings"
|
5
|
+
require_relative "../../../utils/configuration"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module SemanticLogger
|
11
|
+
module Configuration
|
12
|
+
# Custom settings for the SemanticLogger integration
|
13
|
+
# @public_api
|
14
|
+
class Settings < Datadog::CI::Contrib::Settings
|
15
|
+
option :enabled do |o|
|
16
|
+
o.type :bool
|
17
|
+
o.env Ext::ENV_ENABLED
|
18
|
+
o.default true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../integration"
|
4
|
+
require_relative "configuration/settings"
|
5
|
+
require_relative "patcher"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module SemanticLogger
|
11
|
+
# Description of SemanticLogger integration
|
12
|
+
class Integration < Datadog::CI::Contrib::Integration
|
13
|
+
MINIMUM_VERSION = Gem::Version.new("4.0")
|
14
|
+
|
15
|
+
def version
|
16
|
+
Gem.loaded_specs["semantic_logger"]&.version
|
17
|
+
end
|
18
|
+
|
19
|
+
def loaded?
|
20
|
+
!defined?(::SemanticLogger).nil? && !defined?(::SemanticLogger::Logger).nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def compatible?
|
24
|
+
super && version >= MINIMUM_VERSION
|
25
|
+
end
|
26
|
+
|
27
|
+
def late_instrument?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def new_configuration
|
32
|
+
Configuration::Settings.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def patcher
|
36
|
+
Patcher
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module CI
|
5
|
+
module Contrib
|
6
|
+
module SemanticLogger
|
7
|
+
module Logger
|
8
|
+
def self.included(base)
|
9
|
+
base.prepend(InstanceMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def log(log, message = nil, progname = nil, &block)
|
14
|
+
return super unless log.is_a?(::SemanticLogger::Log)
|
15
|
+
return super unless datadog_logs_component.enabled
|
16
|
+
|
17
|
+
result = super
|
18
|
+
|
19
|
+
datadog_logs_component.write(log.to_h.clone)
|
20
|
+
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
def datadog_logs_component
|
25
|
+
Datadog.send(:components).agentless_logs_submission
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../patcher"
|
4
|
+
require_relative "logger"
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module CI
|
8
|
+
module Contrib
|
9
|
+
module SemanticLogger
|
10
|
+
# Patcher enables patching of semantic_logger module
|
11
|
+
module Patcher
|
12
|
+
include Datadog::CI::Contrib::Patcher
|
13
|
+
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def patch
|
17
|
+
unless datadog_logs_component.enabled
|
18
|
+
Datadog.logger.debug("Datadog logs submission is disabled, skipping semantic_logger patching")
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
::SemanticLogger::Logger.include(Logger)
|
23
|
+
end
|
24
|
+
|
25
|
+
def datadog_logs_component
|
26
|
+
Datadog.send(:components).agentless_logs_submission
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -23,6 +23,8 @@ module Datadog
|
|
23
23
|
ENV_TEST_MANAGEMENT_ENABLED = "DD_TEST_MANAGEMENT_ENABLED"
|
24
24
|
ENV_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES = "DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES"
|
25
25
|
ENV_TEST_VISIBILITY_DRB_SERVER_URI = "DD_TEST_VISIBILITY_DRB_SERVER_URI"
|
26
|
+
ENV_AGENTLESS_LOGS_SUBMISSION_ENABLED = "DD_AGENTLESS_LOG_SUBMISSION_ENABLED"
|
27
|
+
ENV_AGENTLESS_LOGS_SUBMISSION_URL = "DD_AGENTLESS_LOG_SUBMISSION_URL"
|
26
28
|
|
27
29
|
# Source: https://docs.datadoghq.com/getting_started/site/
|
28
30
|
DD_SITE_ALLOWLIST = %w[
|
data/lib/datadog/ci/ext/test.rb
CHANGED
@@ -151,9 +151,10 @@ module Datadog
|
|
151
151
|
|
152
152
|
# possible reasons why a test was retried
|
153
153
|
module RetryReason
|
154
|
-
|
155
|
-
RETRY_FAILED = "
|
154
|
+
RETRY_DETECT_FLAKY = "early_flake_detection"
|
155
|
+
RETRY_FAILED = "auto_test_retries"
|
156
156
|
RETRY_FLAKY_FIXED = "attempt_to_fix"
|
157
|
+
RETRY_EXTERNAL = "external"
|
157
158
|
end
|
158
159
|
|
159
160
|
# possible reasons why a test was skipped
|
@@ -28,6 +28,8 @@ module Datadog
|
|
28
28
|
TEST_COVERAGE_INTAKE_HOST_PREFIX = "citestcov-intake"
|
29
29
|
TEST_COVERAGE_INTAKE_PATH = "/api/v2/citestcov"
|
30
30
|
|
31
|
+
LOGS_INTAKE_HOST_PREFIX = "http-intake.logs"
|
32
|
+
|
31
33
|
DD_API_HOST_PREFIX = "api"
|
32
34
|
|
33
35
|
DD_API_SETTINGS_PATH = "/api/v2/libraries/tests/services/setting"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "datadog/core/environment/platform"
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module CI
|
7
|
+
module Logs
|
8
|
+
class Component
|
9
|
+
attr_reader :enabled
|
10
|
+
|
11
|
+
def initialize(enabled:, writer:)
|
12
|
+
@enabled = enabled && !writer.nil?
|
13
|
+
@writer = writer
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(event)
|
17
|
+
return unless enabled
|
18
|
+
|
19
|
+
add_common_tags!(event)
|
20
|
+
@writer&.write(event)
|
21
|
+
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def shutdown!
|
26
|
+
@writer&.stop
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def add_common_tags!(event)
|
32
|
+
test_session = test_visibility.active_test_session
|
33
|
+
|
34
|
+
event[:ddsource] ||= "ruby"
|
35
|
+
event[:ddtags] ||= "datadog.product:citest"
|
36
|
+
event[:service] ||= test_session&.service
|
37
|
+
event[:hostname] ||= Datadog::Core::Environment::Platform.hostname
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_visibility
|
41
|
+
::Datadog.send(:components).test_visibility
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
require "datadog/core/chunker"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Logs
|
10
|
+
class Transport
|
11
|
+
DEFAULT_MAX_PAYLOAD_SIZE = 4.5 * 1024 * 1024
|
12
|
+
|
13
|
+
attr_reader :api,
|
14
|
+
:max_payload_size
|
15
|
+
|
16
|
+
def initialize(api:, max_payload_size: DEFAULT_MAX_PAYLOAD_SIZE)
|
17
|
+
@api = api
|
18
|
+
@max_payload_size = max_payload_size
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_events(events)
|
22
|
+
return [] if events.nil? || events.empty?
|
23
|
+
|
24
|
+
Datadog.logger.debug { "[#{self.class.name}] Sending #{events.count} events..." }
|
25
|
+
|
26
|
+
encoded_events = events.filter_map do |event|
|
27
|
+
encoded_event = event.to_json
|
28
|
+
if event_too_large?(event, encoded_event)
|
29
|
+
next
|
30
|
+
end
|
31
|
+
|
32
|
+
encoded_event
|
33
|
+
end
|
34
|
+
|
35
|
+
responses = []
|
36
|
+
Datadog::Core::Chunker.chunk_by_size(encoded_events, max_payload_size).map do |chunk|
|
37
|
+
encoded_payload = pack_events(chunk)
|
38
|
+
Datadog.logger.debug do
|
39
|
+
"[#{self.class.name}] Send chunk of #{chunk.count} events; payload size #{encoded_payload.size}"
|
40
|
+
end
|
41
|
+
|
42
|
+
response = send_payload(encoded_payload)
|
43
|
+
|
44
|
+
responses << response
|
45
|
+
end
|
46
|
+
|
47
|
+
responses
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def pack_events(encoded_events)
|
53
|
+
"[#{encoded_events.join(",")}]"
|
54
|
+
end
|
55
|
+
|
56
|
+
def event_too_large?(event, encoded_event)
|
57
|
+
return false unless encoded_event.size > max_payload_size
|
58
|
+
|
59
|
+
# This single event is too large, we can't flush it
|
60
|
+
Datadog.logger.debug(
|
61
|
+
"[#{self.class.name}] Dropping event for logs intake. Payload too large: '#{event.inspect}'"
|
62
|
+
)
|
63
|
+
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def send_payload(encoded_payload)
|
68
|
+
@api.logs_intake_request(path: "/v1/input", payload: encoded_payload)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/datadog/ci/test.rb
CHANGED
@@ -25,6 +25,10 @@ module Datadog
|
|
25
25
|
# Finishes the current test.
|
26
26
|
# @return [void]
|
27
27
|
def finish
|
28
|
+
if is_retry? && retry_reason.nil?
|
29
|
+
set_tag(Ext::Test::TAG_RETRY_REASON, Ext::Test::RetryReason::RETRY_EXTERNAL)
|
30
|
+
end
|
31
|
+
|
28
32
|
test_visibility.deactivate_test
|
29
33
|
|
30
34
|
super
|
@@ -68,6 +72,12 @@ module Datadog
|
|
68
72
|
get_tag(Ext::Test::TAG_IS_RETRY) == "true"
|
69
73
|
end
|
70
74
|
|
75
|
+
# Returns string with a reason why test was retried
|
76
|
+
# @return [String] retry reason
|
77
|
+
def retry_reason
|
78
|
+
get_tag(Ext::Test::TAG_RETRY_REASON)
|
79
|
+
end
|
80
|
+
|
71
81
|
# Returns "true" if this span represents a test that wasn't known to Datadog before.
|
72
82
|
# @return [Boolean] true if this test is a new one, false otherwise.
|
73
83
|
def is_new?
|
@@ -8,7 +8,9 @@ module Datadog
|
|
8
8
|
def configure(_, _)
|
9
9
|
end
|
10
10
|
|
11
|
-
def start_test_session(
|
11
|
+
def start_test_session(
|
12
|
+
service: nil, tags: {}, estimated_total_tests_count: 0, distributed: false, local_test_suites_mode: true
|
13
|
+
)
|
12
14
|
skip_tracing
|
13
15
|
end
|
14
16
|
|
@@ -10,11 +10,12 @@ module Datadog
|
|
10
10
|
class Agentless < Base
|
11
11
|
attr_reader :api_key
|
12
12
|
|
13
|
-
def initialize(api_key:, citestcycle_url:, api_url:, citestcov_url:)
|
13
|
+
def initialize(api_key:, citestcycle_url:, api_url:, citestcov_url:, logs_intake_url:)
|
14
14
|
@api_key = api_key
|
15
15
|
@citestcycle_http = build_http_client(citestcycle_url, compress: true)
|
16
16
|
@api_http = build_http_client(api_url, compress: false)
|
17
17
|
@citestcov_http = build_http_client(citestcov_url, compress: true)
|
18
|
+
@logs_intake_http = build_http_client(logs_intake_url, compress: true)
|
18
19
|
end
|
19
20
|
|
20
21
|
def citestcycle_request(path:, payload:, headers: {}, verb: "post")
|
@@ -42,6 +43,12 @@ module Datadog
|
|
42
43
|
perform_request(@citestcov_http, path: path, payload: @citestcov_payload, headers: headers, verb: verb)
|
43
44
|
end
|
44
45
|
|
46
|
+
def logs_intake_request(path:, payload:, headers: {}, verb: "post")
|
47
|
+
super
|
48
|
+
|
49
|
+
perform_request(@logs_intake_http, path: path, payload: payload, headers: headers, verb: verb)
|
50
|
+
end
|
51
|
+
|
45
52
|
private
|
46
53
|
|
47
54
|
def perform_request(http_client, path:, payload:, headers:, verb:, accept_compressed_response: false)
|
@@ -38,6 +38,10 @@ module Datadog
|
|
38
38
|
].join("\r\n")
|
39
39
|
end
|
40
40
|
|
41
|
+
def logs_intake_request(path:, payload:, headers: {}, verb: "post")
|
42
|
+
headers[Ext::Transport::HEADER_CONTENT_TYPE] ||= Ext::Transport::CONTENT_TYPE_JSON
|
43
|
+
end
|
44
|
+
|
41
45
|
def headers_with_default(headers)
|
42
46
|
request_headers = default_headers
|
43
47
|
request_headers.merge!(headers)
|
@@ -27,11 +27,15 @@ module Datadog
|
|
27
27
|
citestcov_url = settings.ci.agentless_url ||
|
28
28
|
"https://#{Ext::Transport::TEST_COVERAGE_INTAKE_HOST_PREFIX}.#{dd_site}:443"
|
29
29
|
|
30
|
+
logs_intake_url = settings.ci.agentless_url ||
|
31
|
+
"https://#{Ext::Transport::LOGS_INTAKE_HOST_PREFIX}.#{dd_site}:443"
|
32
|
+
|
30
33
|
Agentless.new(
|
31
34
|
api_key: settings.api_key,
|
32
35
|
citestcycle_url: citestcycle_url,
|
33
36
|
api_url: api_url,
|
34
|
-
citestcov_url: citestcov_url
|
37
|
+
citestcov_url: citestcov_url,
|
38
|
+
logs_intake_url: logs_intake_url
|
35
39
|
)
|
36
40
|
end
|
37
41
|
|
@@ -46,6 +46,10 @@ module Datadog
|
|
46
46
|
perform_request(@agent_intake_http, path: path, payload: @citestcov_payload, headers: headers, verb: verb)
|
47
47
|
end
|
48
48
|
|
49
|
+
def logs_intake_request(path:, payload:, headers: {}, verb: "post")
|
50
|
+
raise NotImplementedError, "Logs intake is not supported in EVP proxy mode"
|
51
|
+
end
|
52
|
+
|
49
53
|
private
|
50
54
|
|
51
55
|
def perform_request(http_client, path:, payload:, headers:, verb:)
|
data/lib/datadog/ci/version.rb
CHANGED
data/lib/datadog/ci.rb
CHANGED
@@ -429,6 +429,9 @@ require_relative "ci/contrib/parallel_tests/integration"
|
|
429
429
|
require_relative "ci/contrib/selenium/integration"
|
430
430
|
require_relative "ci/contrib/cuprite/integration"
|
431
431
|
require_relative "ci/contrib/simplecov/integration"
|
432
|
+
require_relative "ci/contrib/activesupport/integration"
|
433
|
+
require_relative "ci/contrib/lograge/integration"
|
434
|
+
require_relative "ci/contrib/semantic_logger/integration"
|
432
435
|
|
433
436
|
# Configuration extensions
|
434
437
|
require_relative "ci/configuration/extensions"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datadog-ci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-15 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: datadog
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- ext/datadog_cov/datadog_cov.c
|
75
75
|
- ext/datadog_cov/extconf.rb
|
76
76
|
- lib/datadog/ci.rb
|
77
|
+
- lib/datadog/ci/async_writer.rb
|
77
78
|
- lib/datadog/ci/auto_instrument.rb
|
78
79
|
- lib/datadog/ci/cli/cli.rb
|
79
80
|
- lib/datadog/ci/cli/command/base.rb
|
@@ -87,6 +88,11 @@ files:
|
|
87
88
|
- lib/datadog/ci/configuration/components.rb
|
88
89
|
- lib/datadog/ci/configuration/extensions.rb
|
89
90
|
- lib/datadog/ci/configuration/settings.rb
|
91
|
+
- lib/datadog/ci/contrib/activesupport/configuration/settings.rb
|
92
|
+
- lib/datadog/ci/contrib/activesupport/ext.rb
|
93
|
+
- lib/datadog/ci/contrib/activesupport/integration.rb
|
94
|
+
- lib/datadog/ci/contrib/activesupport/logs_formatter.rb
|
95
|
+
- lib/datadog/ci/contrib/activesupport/patcher.rb
|
90
96
|
- lib/datadog/ci/contrib/ciqueue/integration.rb
|
91
97
|
- lib/datadog/ci/contrib/ciqueue/patcher.rb
|
92
98
|
- lib/datadog/ci/contrib/cucumber/configuration/settings.rb
|
@@ -108,6 +114,11 @@ files:
|
|
108
114
|
- lib/datadog/ci/contrib/knapsack/integration.rb
|
109
115
|
- lib/datadog/ci/contrib/knapsack/patcher.rb
|
110
116
|
- lib/datadog/ci/contrib/knapsack/runner.rb
|
117
|
+
- lib/datadog/ci/contrib/lograge/configuration/settings.rb
|
118
|
+
- lib/datadog/ci/contrib/lograge/ext.rb
|
119
|
+
- lib/datadog/ci/contrib/lograge/integration.rb
|
120
|
+
- lib/datadog/ci/contrib/lograge/log_subscriber.rb
|
121
|
+
- lib/datadog/ci/contrib/lograge/patcher.rb
|
111
122
|
- lib/datadog/ci/contrib/minitest/configuration/settings.rb
|
112
123
|
- lib/datadog/ci/contrib/minitest/ext.rb
|
113
124
|
- lib/datadog/ci/contrib/minitest/helpers.rb
|
@@ -138,6 +149,11 @@ files:
|
|
138
149
|
- lib/datadog/ci/contrib/selenium/integration.rb
|
139
150
|
- lib/datadog/ci/contrib/selenium/navigation.rb
|
140
151
|
- lib/datadog/ci/contrib/selenium/patcher.rb
|
152
|
+
- lib/datadog/ci/contrib/semantic_logger/configuration/settings.rb
|
153
|
+
- lib/datadog/ci/contrib/semantic_logger/ext.rb
|
154
|
+
- lib/datadog/ci/contrib/semantic_logger/integration.rb
|
155
|
+
- lib/datadog/ci/contrib/semantic_logger/logger.rb
|
156
|
+
- lib/datadog/ci/contrib/semantic_logger/patcher.rb
|
141
157
|
- lib/datadog/ci/contrib/settings.rb
|
142
158
|
- lib/datadog/ci/contrib/simplecov/configuration/settings.rb
|
143
159
|
- lib/datadog/ci/contrib/simplecov/ext.rb
|
@@ -178,6 +194,8 @@ files:
|
|
178
194
|
- lib/datadog/ci/git/tree_uploader.rb
|
179
195
|
- lib/datadog/ci/git/upload_packfile.rb
|
180
196
|
- lib/datadog/ci/git/user.rb
|
197
|
+
- lib/datadog/ci/logs/component.rb
|
198
|
+
- lib/datadog/ci/logs/transport.rb
|
181
199
|
- lib/datadog/ci/readonly_test_module.rb
|
182
200
|
- lib/datadog/ci/readonly_test_session.rb
|
183
201
|
- lib/datadog/ci/remote/component.rb
|
@@ -194,7 +212,6 @@ files:
|
|
194
212
|
- lib/datadog/ci/test_optimisation/coverage/ddcov.rb
|
195
213
|
- lib/datadog/ci/test_optimisation/coverage/event.rb
|
196
214
|
- lib/datadog/ci/test_optimisation/coverage/transport.rb
|
197
|
-
- lib/datadog/ci/test_optimisation/coverage/writer.rb
|
198
215
|
- lib/datadog/ci/test_optimisation/skippable.rb
|
199
216
|
- lib/datadog/ci/test_optimisation/skippable_percentage/base.rb
|
200
217
|
- lib/datadog/ci/test_optimisation/skippable_percentage/calculator.rb
|
@@ -1,116 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "datadog/core/workers/async"
|
4
|
-
require "datadog/core/workers/queue"
|
5
|
-
require "datadog/core/workers/polling"
|
6
|
-
|
7
|
-
require "datadog/core/buffer/cruby"
|
8
|
-
require "datadog/core/buffer/thread_safe"
|
9
|
-
|
10
|
-
require "datadog/core/environment/ext"
|
11
|
-
|
12
|
-
module Datadog
|
13
|
-
module CI
|
14
|
-
module TestOptimisation
|
15
|
-
module Coverage
|
16
|
-
class Writer
|
17
|
-
include Core::Workers::Queue
|
18
|
-
include Core::Workers::Polling
|
19
|
-
|
20
|
-
attr_reader :transport
|
21
|
-
|
22
|
-
DEFAULT_BUFFER_MAX_SIZE = 10_000
|
23
|
-
DEFAULT_SHUTDOWN_TIMEOUT = 60
|
24
|
-
|
25
|
-
DEFAULT_INTERVAL = 3
|
26
|
-
|
27
|
-
def initialize(transport:, options: {})
|
28
|
-
@transport = transport
|
29
|
-
|
30
|
-
# Workers::Polling settings
|
31
|
-
self.enabled = options.fetch(:enabled, true)
|
32
|
-
|
33
|
-
# Workers::Async::Thread settings
|
34
|
-
self.fork_policy = Core::Workers::Async::Thread::FORK_POLICY_RESTART
|
35
|
-
|
36
|
-
# Workers::IntervalLoop settings
|
37
|
-
self.loop_base_interval = options[:interval] || DEFAULT_INTERVAL
|
38
|
-
self.loop_back_off_ratio = options[:back_off_ratio] if options.key?(:back_off_ratio)
|
39
|
-
self.loop_back_off_max = options[:back_off_max] if options.key?(:back_off_max)
|
40
|
-
|
41
|
-
@buffer_size = options.fetch(:buffer_size, DEFAULT_BUFFER_MAX_SIZE)
|
42
|
-
|
43
|
-
self.buffer = buffer_klass.new(@buffer_size)
|
44
|
-
|
45
|
-
@shutdown_timeout = options.fetch(:shutdown_timeout, DEFAULT_SHUTDOWN_TIMEOUT)
|
46
|
-
|
47
|
-
@stopped = false
|
48
|
-
end
|
49
|
-
|
50
|
-
def write(event)
|
51
|
-
return if @stopped
|
52
|
-
|
53
|
-
# Start worker thread. If the process has forked, it will trigger #after_fork to
|
54
|
-
# reconfigure the worker accordingly.
|
55
|
-
perform
|
56
|
-
|
57
|
-
enqueue(event)
|
58
|
-
end
|
59
|
-
|
60
|
-
def perform(*events)
|
61
|
-
responses = transport.send_events(events)
|
62
|
-
|
63
|
-
if responses.find(&:server_error?)
|
64
|
-
loop_back_off!
|
65
|
-
Datadog.logger.warn { "Encountered server error while sending coverage events" }
|
66
|
-
end
|
67
|
-
|
68
|
-
nil
|
69
|
-
rescue => e
|
70
|
-
Datadog.logger.warn { "Error while sending coverage events: #{e}" }
|
71
|
-
loop_back_off!
|
72
|
-
end
|
73
|
-
|
74
|
-
def stop(force_stop = false, timeout = @shutdown_timeout)
|
75
|
-
@stopped = true
|
76
|
-
|
77
|
-
buffer.close if running?
|
78
|
-
|
79
|
-
super
|
80
|
-
end
|
81
|
-
|
82
|
-
def enqueue(event)
|
83
|
-
buffer.push(event)
|
84
|
-
end
|
85
|
-
|
86
|
-
def dequeue
|
87
|
-
buffer.pop
|
88
|
-
end
|
89
|
-
|
90
|
-
def work_pending?
|
91
|
-
!buffer.empty?
|
92
|
-
end
|
93
|
-
|
94
|
-
def async?
|
95
|
-
true
|
96
|
-
end
|
97
|
-
|
98
|
-
def after_fork
|
99
|
-
# In multiprocess environments, forks will share the same buffer until its written to.
|
100
|
-
# A.K.A. copy-on-write. We don't want forks to write events generated from another process.
|
101
|
-
# Instead, we reset it after the fork. (Make sure any enqueue operations happen after this.)
|
102
|
-
self.buffer = buffer_klass.new(@buffer_size)
|
103
|
-
end
|
104
|
-
|
105
|
-
def buffer_klass
|
106
|
-
if Core::Environment::Ext::RUBY_ENGINE == "ruby"
|
107
|
-
Core::Buffer::CRuby
|
108
|
-
else
|
109
|
-
Core::Buffer::ThreadSafe
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|