datadog-ci 1.8.1 → 1.9.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 +10 -2
- data/README.md +6 -8
- data/exe/ddcirb +3 -1
- data/lib/datadog/ci/auto_instrument.rb +8 -0
- data/lib/datadog/ci/cli/cli.rb +5 -1
- data/lib/datadog/ci/cli/command/exec.rb +29 -0
- data/lib/datadog/ci/configuration/settings.rb +3 -21
- data/lib/datadog/ci/contrib/ciqueue/integration.rb +34 -0
- data/lib/datadog/ci/contrib/ciqueue/patcher.rb +23 -0
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +10 -5
- data/lib/datadog/ci/contrib/cucumber/integration.rb +5 -14
- data/lib/datadog/ci/contrib/cucumber/patcher.rb +2 -6
- data/lib/datadog/ci/contrib/instrumentation.rb +173 -0
- data/lib/datadog/ci/contrib/integration.rb +101 -117
- data/lib/datadog/ci/contrib/knapsack/extension.rb +27 -0
- data/lib/datadog/ci/contrib/knapsack/integration.rb +36 -0
- data/lib/datadog/ci/contrib/knapsack/patcher.rb +29 -0
- data/lib/datadog/ci/contrib/knapsack/runner.rb +66 -0
- data/lib/datadog/ci/contrib/minitest/integration.rb +6 -14
- data/lib/datadog/ci/contrib/minitest/patcher.rb +1 -5
- data/lib/datadog/ci/contrib/minitest/runner.rb +6 -1
- data/lib/datadog/ci/contrib/minitest/test.rb +6 -1
- data/lib/datadog/ci/contrib/patcher.rb +62 -0
- data/lib/datadog/ci/contrib/rspec/example.rb +6 -1
- data/lib/datadog/ci/contrib/rspec/integration.rb +10 -13
- data/lib/datadog/ci/contrib/rspec/patcher.rb +2 -33
- data/lib/datadog/ci/contrib/rspec/runner.rb +6 -1
- data/lib/datadog/ci/contrib/selenium/capybara_driver.rb +1 -1
- data/lib/datadog/ci/contrib/selenium/driver.rb +1 -1
- data/lib/datadog/ci/contrib/selenium/integration.rb +6 -10
- data/lib/datadog/ci/contrib/selenium/navigation.rb +6 -2
- data/lib/datadog/ci/contrib/selenium/patcher.rb +2 -6
- data/lib/datadog/ci/contrib/selenium/rum.rb +0 -2
- data/lib/datadog/ci/contrib/simplecov/integration.rb +6 -10
- data/lib/datadog/ci/contrib/simplecov/patcher.rb +2 -6
- data/lib/datadog/ci/test_retries/strategy/retry_new.rb +1 -1
- data/lib/datadog/ci/test_visibility/component.rb +2 -2
- data/lib/datadog/ci/test_visibility/telemetry.rb +2 -1
- data/lib/datadog/ci/version.rb +2 -2
- data/lib/datadog/ci.rb +9 -1
- metadata +13 -7
- data/lib/datadog/ci/contrib/contrib.rb +0 -31
- data/lib/datadog/ci/contrib/rspec/knapsack_pro/extension.rb +0 -29
- data/lib/datadog/ci/contrib/rspec/knapsack_pro/patcher.rb +0 -26
- data/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7641cbd9b01a787badb9bab7d3aa74933c99b750b46609c9a625ed3f7daaa11c
|
4
|
+
data.tar.gz: 5489c728c4b6c91ff68b515796533801b02dfb623f506da23849e60e343063a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d2f41e5eb8f58c3eecb72200658add1799109c7778fad032c6d58ec2fd462a37df7e1a47edfb6cf7390e037c4e30ada85dc95c71983c30629de38b2bf62fd35
|
7
|
+
data.tar.gz: 408151cc04150bcc8ec2a0933c0f6d38cd1362b5842e8b145960ba276431681893988cfd0c49ce47f519ae9e7451549b45503a6ea79f123cfd4cc3750cb2a8ea
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.9.0] - 2024-11-26
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
* Auto instrumentation ([#259][])
|
8
|
+
|
3
9
|
## [1.8.1] - 2024-10-18
|
4
10
|
|
5
11
|
|
@@ -356,7 +362,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
356
362
|
|
357
363
|
- Ruby versions < 2.7 no longer supported ([#8][])
|
358
364
|
|
359
|
-
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.
|
365
|
+
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.9.0...main
|
366
|
+
[1.9.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.8.1...v1.9.0
|
360
367
|
[1.8.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.8.0...v1.8.1
|
361
368
|
[1.8.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.7.0...v1.8.0
|
362
369
|
[1.7.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.6.0...v1.7.0
|
@@ -513,4 +520,5 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
513
520
|
[#243]: https://github.com/DataDog/datadog-ci-rb/issues/243
|
514
521
|
[#244]: https://github.com/DataDog/datadog-ci-rb/issues/244
|
515
522
|
[#248]: https://github.com/DataDog/datadog-ci-rb/issues/248
|
516
|
-
[#250]: https://github.com/DataDog/datadog-ci-rb/issues/250
|
523
|
+
[#250]: https://github.com/DataDog/datadog-ci-rb/issues/250
|
524
|
+
[#259]: https://github.com/DataDog/datadog-ci-rb/issues/259
|
data/README.md
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
# Datadog Test
|
1
|
+
# Datadog Test Optimization for Ruby
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/datadog-ci)
|
4
4
|
[](https://datadoghq.dev/datadog-ci-rb/)
|
5
|
-
[](https://app.codecov.io/gh/DataDog/datadog-ci-rb/branch/main)
|
6
|
-
[](https://dl.circleci.com/status-badge/redirect/gh/DataDog/datadog-ci-rb/tree/main)
|
7
5
|
|
8
6
|
Datadog's Ruby Library for instrumenting your tests.
|
9
7
|
Learn more on our [official website](https://docs.datadoghq.com/tests/) and check out our [documentation for this library](https://docs.datadoghq.com/tests/setup/ruby/?tab=cloudciprovideragentless).
|
@@ -11,12 +9,12 @@ Learn more on our [official website](https://docs.datadoghq.com/tests/) and chec
|
|
11
9
|
## Features
|
12
10
|
|
13
11
|
- [Test Visibility](https://docs.datadoghq.com/tests/) - collect metrics and results for your tests
|
14
|
-
- [
|
15
|
-
- [
|
16
|
-
- [
|
12
|
+
- [Test impact analysis](https://docs.datadoghq.com/tests/test_impact_analysis/) - save time by selectively running only tests affected by code changes
|
13
|
+
- [Flaky test management](https://docs.datadoghq.com/tests/flaky_test_management/) - track, alert, search your flaky tests in Datadog UI
|
14
|
+
- [Auto test retries](https://docs.datadoghq.com/tests/flaky_test_management/auto_test_retries/?tab=ruby) - retrying failing tests up to N times to avoid failing your build due to flaky tests
|
15
|
+
- [Early flake detection](https://docs.datadoghq.com/tests/flaky_test_management/early_flake_detection/?tab=ruby) - Datadog’s test flakiness solution that identifies flakes early by running newly added tests multiple times
|
17
16
|
- [Search and manage CI tests](https://docs.datadoghq.com/tests/search/)
|
18
17
|
- [Enhance developer workflows](https://docs.datadoghq.com/tests/developer_workflows)
|
19
|
-
- [Flaky test management](https://docs.datadoghq.com/tests/guides/flaky_test_management/)
|
20
18
|
- [Add custom measures to your tests](https://docs.datadoghq.com/tests/guides/add_custom_measures/?tab=ruby)
|
21
19
|
- [Browser tests integration with Datadog RUM](https://docs.datadoghq.com/tests/browser_tests)
|
22
20
|
|
@@ -37,7 +35,7 @@ If you used [test visibility for Ruby](https://docs.datadoghq.com/tests/setup/ru
|
|
37
35
|
## Setup
|
38
36
|
|
39
37
|
- [Test visibility setup](https://docs.datadoghq.com/tests/setup/ruby/?tab=cloudciprovideragentless)
|
40
|
-
- [
|
38
|
+
- [Test impact analysis setup](https://docs.datadoghq.com/tests/test_impact_analysis/setup/ruby/?tab=cloudciprovideragentless) (test visibility setup is required before setting up test impact analysis)
|
41
39
|
|
42
40
|
## Contributing
|
43
41
|
|
data/exe/ddcirb
CHANGED
data/lib/datadog/ci/cli/cli.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
require "datadog"
|
2
2
|
require "datadog/ci"
|
3
3
|
|
4
|
+
require_relative "command/exec"
|
4
5
|
require_relative "command/skippable_tests_percentage"
|
5
6
|
require_relative "command/skippable_tests_percentage_estimate"
|
6
7
|
|
7
8
|
module Datadog
|
8
9
|
module CI
|
9
10
|
module CLI
|
10
|
-
def self.exec(action)
|
11
|
+
def self.exec(action, args = [])
|
11
12
|
case action
|
13
|
+
when "exec"
|
14
|
+
Command::Exec.new(args).exec
|
12
15
|
when "skipped-tests", "skippable-tests"
|
13
16
|
Command::SkippableTestsPercentage.new.exec
|
14
17
|
when "skipped-tests-estimate", "skippable-tests-estimate"
|
@@ -17,6 +20,7 @@ module Datadog
|
|
17
20
|
puts("Usage: bundle exec ddcirb [command] [options]. Available commands:")
|
18
21
|
puts(" skippable-tests - calculates the exact percentage of skipped tests and prints it to stdout or file")
|
19
22
|
puts(" skippable-tests-estimate - estimates the percentage of skipped tests and prints it to stdout or file")
|
23
|
+
puts(" exec YOUR_TEST_COMMAND - automatically instruments your test command with Datadog and executes it")
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
require_relative "../../test_optimisation/skippable_percentage/estimator"
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module CI
|
6
|
+
module CLI
|
7
|
+
module Command
|
8
|
+
class Exec < Base
|
9
|
+
def initialize(args)
|
10
|
+
super()
|
11
|
+
|
12
|
+
@args = args
|
13
|
+
end
|
14
|
+
|
15
|
+
def exec
|
16
|
+
rubyopts = [
|
17
|
+
"-rdatadog/ci/auto_instrument"
|
18
|
+
]
|
19
|
+
|
20
|
+
existing_rubyopt = ENV["RUBYOPT"]
|
21
|
+
ENV["RUBYOPT"] = existing_rubyopt ? "#{existing_rubyopt} #{rubyopts.join(" ")}" : rubyopts.join(" ")
|
22
|
+
|
23
|
+
Kernel.exec(*@args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../contrib/instrumentation"
|
3
4
|
require_relative "../ext/settings"
|
4
5
|
require_relative "../utils/bundle"
|
5
6
|
|
@@ -8,8 +9,6 @@ module Datadog
|
|
8
9
|
module Configuration
|
9
10
|
# Adds CI behavior to ddtrace settings
|
10
11
|
module Settings
|
11
|
-
InvalidIntegrationError = Class.new(StandardError)
|
12
|
-
|
13
12
|
def self.extended(base)
|
14
13
|
base = base.singleton_class unless base.is_a?(Class)
|
15
14
|
add_settings!(base)
|
@@ -126,23 +125,11 @@ module Datadog
|
|
126
125
|
define_method(:instrument) do |integration_name, options = {}, &block|
|
127
126
|
return unless enabled
|
128
127
|
|
129
|
-
|
130
|
-
integration.configure(options, &block)
|
131
|
-
|
132
|
-
return unless integration.enabled
|
133
|
-
|
134
|
-
patch_results = integration.patch
|
135
|
-
next if patch_results == true
|
136
|
-
|
137
|
-
error_message = <<-ERROR
|
138
|
-
Available?: #{patch_results[:available]}, Loaded?: #{patch_results[:loaded]},
|
139
|
-
Compatible?: #{patch_results[:compatible]}, Patchable?: #{patch_results[:patchable]}"
|
140
|
-
ERROR
|
141
|
-
Datadog.logger.warn("Unable to patch #{integration_name} (#{error_message})")
|
128
|
+
Contrib::Instrumentation.instrument(integration_name, options, &block)
|
142
129
|
end
|
143
130
|
|
144
131
|
define_method(:[]) do |integration_name|
|
145
|
-
fetch_integration(integration_name).configuration
|
132
|
+
Contrib::Instrumentation.fetch_integration(integration_name).configuration
|
146
133
|
end
|
147
134
|
|
148
135
|
option :trace_flush
|
@@ -151,11 +138,6 @@ module Datadog
|
|
151
138
|
o.type :hash
|
152
139
|
o.default({})
|
153
140
|
end
|
154
|
-
|
155
|
-
define_method(:fetch_integration) do |name|
|
156
|
-
Datadog::CI::Contrib::Integration.registry[name] ||
|
157
|
-
raise(InvalidIntegrationError, "'#{name}' is not a valid integration.")
|
158
|
-
end
|
159
141
|
end
|
160
142
|
end
|
161
143
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../integration"
|
4
|
+
require_relative "patcher"
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module CI
|
8
|
+
module Contrib
|
9
|
+
module Ciqueue
|
10
|
+
# ci-queue test runner instrumentation
|
11
|
+
# https://github.com/Shopify/ci-queue
|
12
|
+
class Integration < Contrib::Integration
|
13
|
+
MINIMUM_VERSION = Gem::Version.new("0.9.0")
|
14
|
+
|
15
|
+
def version
|
16
|
+
Gem.loaded_specs["ci-queue"]&.version
|
17
|
+
end
|
18
|
+
|
19
|
+
def loaded?
|
20
|
+
!defined?(::RSpec::Queue::Runner).nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def compatible?
|
24
|
+
super && version >= MINIMUM_VERSION
|
25
|
+
end
|
26
|
+
|
27
|
+
def patcher
|
28
|
+
Patcher
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../patcher"
|
4
|
+
require_relative "../rspec/runner"
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module CI
|
8
|
+
module Contrib
|
9
|
+
module Ciqueue
|
10
|
+
# Patcher enables patching of 'rspec' module.
|
11
|
+
module Patcher
|
12
|
+
include Datadog::CI::Contrib::Patcher
|
13
|
+
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def patch
|
17
|
+
::RSpec::Queue::Runner.include(Contrib::RSpec::Runner)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative "../../ext/test"
|
4
4
|
require_relative "../../git/local_repository"
|
5
5
|
require_relative "../../utils/test_run"
|
6
|
+
require_relative "../instrumentation"
|
6
7
|
require_relative "ext"
|
7
8
|
|
8
9
|
module Datadog
|
@@ -38,9 +39,9 @@ module Datadog
|
|
38
39
|
test_visibility_component.start_test_session(
|
39
40
|
tags: {
|
40
41
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
41
|
-
CI::Ext::Test::TAG_FRAMEWORK_VERSION =>
|
42
|
+
CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s
|
42
43
|
},
|
43
|
-
service:
|
44
|
+
service: datadog_configuration[:service_name]
|
44
45
|
)
|
45
46
|
test_visibility_component.start_test_module(Ext::FRAMEWORK)
|
46
47
|
end
|
@@ -61,7 +62,7 @@ module Datadog
|
|
61
62
|
# @type var tags: Hash[String, String]
|
62
63
|
tags = {
|
63
64
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
64
|
-
CI::Ext::Test::TAG_FRAMEWORK_VERSION =>
|
65
|
+
CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s,
|
65
66
|
CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(event.test_case.location.file),
|
66
67
|
CI::Ext::Test::TAG_SOURCE_START => event.test_case.location.line.to_s
|
67
68
|
}
|
@@ -81,7 +82,7 @@ module Datadog
|
|
81
82
|
event.test_case.name,
|
82
83
|
test_suite_name,
|
83
84
|
tags: tags,
|
84
|
-
service:
|
85
|
+
service: datadog_configuration[:service_name]
|
85
86
|
)
|
86
87
|
if event.test_case.match_tags?("@#{CI::Ext::Test::ITR_UNSKIPPABLE_OPTION}")
|
87
88
|
test_span&.itr_unskippable!
|
@@ -199,7 +200,11 @@ module Datadog
|
|
199
200
|
end
|
200
201
|
end
|
201
202
|
|
202
|
-
def
|
203
|
+
def datadog_integration
|
204
|
+
CI::Contrib::Instrumentation.fetch_integration(:cucumber)
|
205
|
+
end
|
206
|
+
|
207
|
+
def datadog_configuration
|
203
208
|
Datadog.configuration.ci[:cucumber]
|
204
209
|
end
|
205
210
|
|
@@ -9,30 +9,21 @@ module Datadog
|
|
9
9
|
module Contrib
|
10
10
|
module Cucumber
|
11
11
|
# Description of Cucumber integration
|
12
|
-
class Integration
|
13
|
-
include Datadog::CI::Contrib::Integration
|
14
|
-
|
12
|
+
class Integration < Contrib::Integration
|
15
13
|
MINIMUM_VERSION = Gem::Version.new("3.0.0")
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
def self.version
|
15
|
+
def version
|
20
16
|
Gem.loaded_specs["cucumber"]&.version
|
21
17
|
end
|
22
18
|
|
23
|
-
def
|
24
|
-
!defined?(::Cucumber).nil? && !defined?(::Cucumber::Runtime).nil?
|
19
|
+
def loaded?
|
20
|
+
!defined?(::Cucumber).nil? && !defined?(::Cucumber::Runtime).nil? && !defined?(::Cucumber::Configuration).nil?
|
25
21
|
end
|
26
22
|
|
27
|
-
def
|
23
|
+
def compatible?
|
28
24
|
super && version >= MINIMUM_VERSION
|
29
25
|
end
|
30
26
|
|
31
|
-
# test environments should not auto instrument test libraries
|
32
|
-
def auto_instrument?
|
33
|
-
false
|
34
|
-
end
|
35
|
-
|
36
27
|
def new_configuration
|
37
28
|
Configuration::Settings.new
|
38
29
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative "../patcher"
|
4
4
|
|
5
5
|
require_relative "instrumentation"
|
6
6
|
|
@@ -10,14 +10,10 @@ module Datadog
|
|
10
10
|
module Cucumber
|
11
11
|
# Patches 'cucumber' gem.
|
12
12
|
module Patcher
|
13
|
-
include Datadog::
|
13
|
+
include Datadog::CI::Contrib::Patcher
|
14
14
|
|
15
15
|
module_function
|
16
16
|
|
17
|
-
def target_version
|
18
|
-
Integration.version
|
19
|
-
end
|
20
|
-
|
21
17
|
def patch
|
22
18
|
::Cucumber::Runtime.include(Instrumentation)
|
23
19
|
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "datadog/core/utils/only_once"
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module CI
|
7
|
+
module Contrib
|
8
|
+
module Instrumentation
|
9
|
+
class InvalidIntegrationError < StandardError; end
|
10
|
+
|
11
|
+
@registry = {}
|
12
|
+
@auto_instrumented = false
|
13
|
+
|
14
|
+
def self.registry
|
15
|
+
@registry
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.register_integration(integration_class)
|
19
|
+
@registry[integration_name(integration_class)] = integration_class.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.auto_instrumented?
|
23
|
+
@auto_instrumented
|
24
|
+
end
|
25
|
+
|
26
|
+
# Auto instrumentation of all integrations.
|
27
|
+
#
|
28
|
+
# Registers a :script_compiled tracepoint to watch for new Ruby files being loaded.
|
29
|
+
# On every file load it checks if any of the integrations are patchable now.
|
30
|
+
# Only the integrations that are available in the environment are checked.
|
31
|
+
def self.auto_instrument
|
32
|
+
Datadog.logger.debug("Auto instrumenting all integrations...")
|
33
|
+
@auto_instrumented = true
|
34
|
+
|
35
|
+
auto_instrumented_integrations = fetch_auto_instrumented_integrations
|
36
|
+
if auto_instrumented_integrations.empty?
|
37
|
+
Datadog.logger.warn(
|
38
|
+
"Auto instrumentation was requested, but no available integrations were found. " \
|
39
|
+
"Tests will be run without Datadog instrumentation."
|
40
|
+
)
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
# note that `Kernel.require` might be called from a different thread, so
|
45
|
+
# there is a possibility of concurrent execution of this tracepoint
|
46
|
+
mutex = Mutex.new
|
47
|
+
script_compiled_tracepoint = TracePoint.new(:script_compiled) do |tp|
|
48
|
+
all_patched = true
|
49
|
+
|
50
|
+
mutex.synchronize do
|
51
|
+
auto_instrumented_integrations.each do |integration|
|
52
|
+
next if integration.patched?
|
53
|
+
|
54
|
+
all_patched = false
|
55
|
+
next unless integration.loaded?
|
56
|
+
|
57
|
+
auto_configure_datadog
|
58
|
+
|
59
|
+
Datadog.logger.debug("#{integration.class} is loaded")
|
60
|
+
patch_integration(integration)
|
61
|
+
end
|
62
|
+
|
63
|
+
if all_patched
|
64
|
+
Datadog.logger.debug("All expected integrations are patched, disabling the script_compiled tracepoint")
|
65
|
+
|
66
|
+
tp.disable
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
script_compiled_tracepoint.enable
|
71
|
+
end
|
72
|
+
|
73
|
+
# Manual instrumentation of a specific integration.
|
74
|
+
#
|
75
|
+
# This method is called when user has `c.ci.instrument :integration_name` in their code.
|
76
|
+
def self.instrument(integration_name, options = {}, &block)
|
77
|
+
integration = fetch_integration(integration_name)
|
78
|
+
# when manually instrumented, it might be configured via code
|
79
|
+
integration.configure(options, &block)
|
80
|
+
|
81
|
+
return unless integration.enabled
|
82
|
+
|
83
|
+
patch_integration(integration, with_dependencies: true)
|
84
|
+
end
|
85
|
+
|
86
|
+
# This method instruments all additional test libraries (ex: selenium-webdriver) that need to be instrumented
|
87
|
+
# later in the test suite run.
|
88
|
+
#
|
89
|
+
# It is intended to be called when test session starts to add additional capabilities to test visibility.
|
90
|
+
#
|
91
|
+
# This method does not automatically instrument test frameworks (ex: RSpec, Cucumber, etc), it requires
|
92
|
+
# test framework to be already instrumented.
|
93
|
+
def self.instrument_on_session_start
|
94
|
+
Datadog.logger.debug("Instrumenting all late instrumented integrations...")
|
95
|
+
|
96
|
+
@registry.each do |name, integration|
|
97
|
+
next unless integration.late_instrument?
|
98
|
+
next unless integration.enabled
|
99
|
+
|
100
|
+
Datadog.logger.debug "#{name} is allowed to be late instrumented"
|
101
|
+
|
102
|
+
patch_integration(integration)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.fetch_integration(name)
|
107
|
+
@registry[name] ||
|
108
|
+
raise(InvalidIntegrationError, "'#{name}' is not a valid integration.")
|
109
|
+
end
|
110
|
+
|
111
|
+
# take the parent module name and downcase it
|
112
|
+
# for example for Datadog::CI::Contrib::RSpec::Integration it will be :rspec
|
113
|
+
def self.integration_name(subclass)
|
114
|
+
result = subclass.name&.split("::")&.[](-2)&.downcase&.to_sym
|
115
|
+
raise "Integration name could not be derived for #{subclass}" if result.nil?
|
116
|
+
result
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.patch_integration(integration, with_dependencies: false)
|
120
|
+
patch_results = integration.patch
|
121
|
+
|
122
|
+
if patch_results[:ok]
|
123
|
+
Datadog.logger.debug("#{integration.class} is patched")
|
124
|
+
|
125
|
+
return unless with_dependencies
|
126
|
+
|
127
|
+
# try to patch dependant integrations (for example knapsack that depends on rspec)
|
128
|
+
dependants = integration.dependants
|
129
|
+
.map { |name| fetch_integration(name) }
|
130
|
+
.filter { |integration| integration.patchable? }
|
131
|
+
|
132
|
+
Datadog.logger.debug("Found dependent integrations for #{integration.class}: #{dependants}")
|
133
|
+
|
134
|
+
dependants.each do |dependent_integration|
|
135
|
+
patch_integration(dependent_integration, with_dependencies: true)
|
136
|
+
end
|
137
|
+
|
138
|
+
else
|
139
|
+
Datadog.logger.debug("Attention: #{integration.class} is not patched (#{patch_results})")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.fetch_auto_instrumented_integrations
|
144
|
+
@registry.filter_map do |name, integration|
|
145
|
+
# ignore integrations that are not in the Gemfile or have incompatible versions
|
146
|
+
next unless integration.compatible?
|
147
|
+
|
148
|
+
# late instrumented integrations will be patched when the test session starts
|
149
|
+
next if integration.late_instrument?
|
150
|
+
|
151
|
+
Datadog.logger.debug("#{name} should be auto instrumented")
|
152
|
+
integration
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.auto_configure_datadog
|
157
|
+
configure_once.run do
|
158
|
+
Datadog.logger.debug("Applying Datadog configuration in CI mode...")
|
159
|
+
Datadog.configure do |c|
|
160
|
+
c.ci.enabled = true
|
161
|
+
c.tracing.enabled = true
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# This is not thread safe, it is synchronized by the caller in the tracepoint
|
167
|
+
def self.configure_once
|
168
|
+
@configure_once ||= Datadog::Core::Utils::OnlyOnce.new
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|