datadog-ci 1.8.1 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -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 +64 -25
- data/lib/datadog/ci/contrib/rspec/example_group.rb +18 -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.rb +8 -7
- data/lib/datadog/ci/test_optimisation/component.rb +9 -4
- 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
@@ -1,147 +1,131 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "settings"
|
4
|
+
require_relative "instrumentation"
|
4
5
|
|
5
6
|
module Datadog
|
6
7
|
module CI
|
7
8
|
module Contrib
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def self.included(base)
|
12
|
-
base.extend(ClassMethods)
|
13
|
-
base.include(InstanceMethods)
|
9
|
+
class Integration
|
10
|
+
def self.inherited(subclass)
|
11
|
+
Instrumentation.register_integration(subclass)
|
14
12
|
end
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
# List of integrations names that depend on this integration.
|
15
|
+
# Specify when you might need to automatically instrument other integrations (like test runner for the
|
16
|
+
# test framework).
|
17
|
+
def dependants
|
18
|
+
[]
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
# Version of the integration target code in the environment.
|
22
|
+
#
|
23
|
+
# This is the gem version, when the instrumentation target is a Ruby gem.
|
24
|
+
#
|
25
|
+
# If the target for instrumentation has concept of versioning, override {.version},
|
26
|
+
# otherwise override {.available?} and implement a custom target presence check.
|
27
|
+
# @return [Object] the target version
|
28
|
+
def version
|
29
|
+
nil
|
22
30
|
end
|
23
31
|
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def version
|
38
|
-
nil
|
39
|
-
end
|
32
|
+
# Is the target available to be instrumented? (e.g. gem installed?)
|
33
|
+
#
|
34
|
+
# The target doesn't have to be loaded (e.g. `require`) yet, but needs to be able
|
35
|
+
# to be loaded before instrumentation can commence.
|
36
|
+
#
|
37
|
+
# By default, {.available?} checks if {.version} returned a non-nil object.
|
38
|
+
#
|
39
|
+
# If the target for instrumentation has concept of versioning, override {.version},
|
40
|
+
# otherwise override {.available?} and implement a custom target presence check.
|
41
|
+
# @return [Boolean] is the target available for instrumentation in this Ruby environment?
|
42
|
+
def available?
|
43
|
+
!version.nil?
|
44
|
+
end
|
40
45
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
# @return [Boolean] is the target available for instrumentation in this Ruby environment?
|
51
|
-
def available?
|
52
|
-
!version.nil?
|
53
|
-
end
|
46
|
+
# Is the target loaded into the application? (e.g. gem required? Constant defined?)
|
47
|
+
#
|
48
|
+
# The target's objects should be ready to be referenced by the instrumented when {.loaded}
|
49
|
+
# returns `true`.
|
50
|
+
#
|
51
|
+
# @return [Boolean] is the target ready to be referenced during instrumentation?
|
52
|
+
def loaded?
|
53
|
+
true
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# @return [Boolean] is the target ready to be referenced during instrumentation?
|
61
|
-
def loaded?
|
62
|
-
true
|
63
|
-
end
|
56
|
+
# Is this instrumentation compatible with the available target? (e.g. minimum version met?)
|
57
|
+
# @return [Boolean] is the available target compatible with this instrumentation?
|
58
|
+
def compatible?
|
59
|
+
available?
|
60
|
+
end
|
64
61
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
# Can the patch for this integration be applied?
|
63
|
+
#
|
64
|
+
# By default, this is equivalent to {#available?}, {#loaded?}, and {#compatible?}
|
65
|
+
# all being truthy.
|
66
|
+
def patchable?
|
67
|
+
available? && loaded? && compatible?
|
68
|
+
end
|
70
69
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
# all being truthy.
|
75
|
-
def patchable?
|
76
|
-
available? && loaded? && compatible?
|
77
|
-
end
|
70
|
+
# returns the configuration instance.
|
71
|
+
def configuration
|
72
|
+
@configuration ||= new_configuration
|
78
73
|
end
|
79
74
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
75
|
+
def configure(options = {}, &block)
|
76
|
+
configuration.configure(options, &block)
|
77
|
+
configuration
|
78
|
+
end
|
85
79
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
80
|
+
def enabled
|
81
|
+
configuration.enabled
|
82
|
+
end
|
90
83
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
84
|
+
# The patcher module to inject instrumented objects into the instrumentation target.
|
85
|
+
#
|
86
|
+
# {Contrib::Patcher} includes the basic functionality of a patcher. `include`ing
|
87
|
+
# {Contrib::Patcher} into a new module is the recommend way to create a custom patcher.
|
88
|
+
#
|
89
|
+
# @return [Contrib::Patcher] a module that `include`s {Contrib::Patcher}
|
90
|
+
def patcher
|
91
|
+
nil
|
92
|
+
end
|
95
93
|
|
96
|
-
|
97
|
-
|
94
|
+
# @!visibility private
|
95
|
+
def patch
|
96
|
+
if !patchable? || patcher.nil?
|
97
|
+
return {
|
98
|
+
ok: false,
|
99
|
+
available: available?,
|
100
|
+
loaded: loaded?,
|
101
|
+
compatible: compatible?,
|
102
|
+
patchable: patchable?
|
103
|
+
}
|
98
104
|
end
|
99
105
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
# {Contrib::Patcher} into a new module is the recommend way to create a custom patcher.
|
104
|
-
#
|
105
|
-
# @return [Contrib::Patcher] a module that `include`s {Contrib::Patcher}
|
106
|
-
def patcher
|
107
|
-
nil
|
108
|
-
end
|
106
|
+
patcher.patch
|
107
|
+
{ok: true}
|
108
|
+
end
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
patcher_klass = patcher
|
114
|
-
if !self.class.patchable? || patcher_klass.nil?
|
115
|
-
return {
|
116
|
-
available: self.class.available?,
|
117
|
-
loaded: self.class.loaded?,
|
118
|
-
compatible: self.class.compatible?,
|
119
|
-
patchable: self.class.patchable?
|
120
|
-
}
|
121
|
-
end
|
122
|
-
|
123
|
-
patcher_klass.patch
|
124
|
-
true
|
125
|
-
end
|
110
|
+
def patched?
|
111
|
+
patcher&.patched?
|
112
|
+
end
|
126
113
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
114
|
+
# Can the patch for this integration be applied automatically?
|
115
|
+
# @return [Boolean] can the tracer activate this instrumentation without explicit user input?
|
116
|
+
def late_instrument?
|
117
|
+
false
|
118
|
+
end
|
132
119
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
def new_configuration
|
143
|
-
Datadog::CI::Contrib::Settings.new
|
144
|
-
end
|
120
|
+
# Returns a new configuration object for this integration.
|
121
|
+
#
|
122
|
+
# This method normally needs to be overridden for each integration
|
123
|
+
# as their settings, defaults and environment variables are
|
124
|
+
# specific for each integration.
|
125
|
+
#
|
126
|
+
# @return [Datadog::CI::Contrib::Settings] a new, integration-specific settings object
|
127
|
+
def new_configuration
|
128
|
+
Datadog::CI::Contrib::Settings.new
|
145
129
|
end
|
146
130
|
end
|
147
131
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "knapsack_pro/extensions/rspec_extension"
|
4
|
+
|
5
|
+
require_relative "runner"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module Knapsack
|
11
|
+
module Extension
|
12
|
+
def self.included(base)
|
13
|
+
base.singleton_class.prepend(ClassMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def setup!
|
18
|
+
super
|
19
|
+
|
20
|
+
::RSpec::Core::Runner.include(Datadog::CI::Contrib::Knapsack::Runner)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
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 Knapsack
|
10
|
+
# Knapsack Pro test runner instrumentation
|
11
|
+
# https://github.com/KnapsackPro/knapsack_pro-ruby
|
12
|
+
class Integration < Contrib::Integration
|
13
|
+
MINIMUM_VERSION = Gem::Version.new("7.0.0")
|
14
|
+
|
15
|
+
def version
|
16
|
+
Gem.loaded_specs["knapsack_pro"]&.version
|
17
|
+
end
|
18
|
+
|
19
|
+
def loaded?
|
20
|
+
!defined?(::KnapsackPro).nil? &&
|
21
|
+
!defined?(::KnapsackPro::Extensions::RSpecExtension).nil? &&
|
22
|
+
!defined?(::KnapsackPro::Extensions::RSpecExtension::Runner).nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def compatible?
|
26
|
+
super && version >= MINIMUM_VERSION
|
27
|
+
end
|
28
|
+
|
29
|
+
def patcher
|
30
|
+
Patcher
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../patcher"
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module CI
|
7
|
+
module Contrib
|
8
|
+
module Knapsack
|
9
|
+
module Patcher
|
10
|
+
include Datadog::CI::Contrib::Patcher
|
11
|
+
|
12
|
+
module_function
|
13
|
+
|
14
|
+
def patch
|
15
|
+
if ::RSpec::Core::Runner.ancestors.include?(::KnapsackPro::Extensions::RSpecExtension::Runner)
|
16
|
+
# knapsack already patched rspec runner
|
17
|
+
require_relative "runner"
|
18
|
+
::RSpec::Core::Runner.include(Datadog::CI::Contrib::Knapsack::Runner)
|
19
|
+
else
|
20
|
+
# knapsack didn't patch rspec runner yet
|
21
|
+
require_relative "extension"
|
22
|
+
::KnapsackPro::Extensions::RSpecExtension.include(Datadog::CI::Contrib::Knapsack::Extension)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../ext/test"
|
4
|
+
require_relative "../rspec/ext"
|
5
|
+
require_relative "../instrumentation"
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module CI
|
9
|
+
module Contrib
|
10
|
+
module Knapsack
|
11
|
+
module Runner
|
12
|
+
def self.included(base)
|
13
|
+
base.prepend(InstanceMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
module InstanceMethods
|
17
|
+
# TODO: this is coupled to RSpec integration being present, not sure if it's bad or not at this point
|
18
|
+
def knapsack__run_specs(*args)
|
19
|
+
return super if ::RSpec.configuration.dry_run? && !datadog_configuration[:dry_run_enabled]
|
20
|
+
return super unless datadog_configuration[:enabled]
|
21
|
+
|
22
|
+
test_session = test_visibility_component.start_test_session(
|
23
|
+
tags: {
|
24
|
+
CI::Ext::Test::TAG_FRAMEWORK => CI::Contrib::RSpec::Ext::FRAMEWORK,
|
25
|
+
CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s
|
26
|
+
},
|
27
|
+
service: datadog_configuration[:service_name]
|
28
|
+
)
|
29
|
+
|
30
|
+
test_module = test_visibility_component.start_test_module(CI::Contrib::RSpec::Ext::FRAMEWORK)
|
31
|
+
|
32
|
+
result = super
|
33
|
+
return result unless test_module && test_session
|
34
|
+
|
35
|
+
if result != 0
|
36
|
+
test_module.failed!
|
37
|
+
test_session.failed!
|
38
|
+
else
|
39
|
+
test_module.passed!
|
40
|
+
test_session.passed!
|
41
|
+
end
|
42
|
+
test_module.finish
|
43
|
+
test_session.finish
|
44
|
+
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def datadog_integration
|
51
|
+
CI::Contrib::Instrumentation.fetch_integration(:rspec)
|
52
|
+
end
|
53
|
+
|
54
|
+
def datadog_configuration
|
55
|
+
Datadog.configuration.ci[:rspec]
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_visibility_component
|
59
|
+
Datadog.send(:components).test_visibility
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -9,30 +9,22 @@ module Datadog
|
|
9
9
|
module Contrib
|
10
10
|
module Minitest
|
11
11
|
# Description of Minitest integration
|
12
|
-
class Integration
|
13
|
-
include Datadog::CI::Contrib::Integration
|
14
|
-
|
12
|
+
class Integration < Contrib::Integration
|
15
13
|
MINIMUM_VERSION = Gem::Version.new("5.0.0")
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
def self.version
|
15
|
+
def version
|
20
16
|
Gem.loaded_specs["minitest"]&.version
|
21
17
|
end
|
22
18
|
|
23
|
-
def
|
24
|
-
!defined?(::Minitest).nil?
|
19
|
+
def loaded?
|
20
|
+
!defined?(::Minitest).nil? && !defined?(::Minitest::Runnable).nil? && !defined?(::Minitest::Test).nil? &&
|
21
|
+
!defined?(::Minitest::CompositeReporter).nil?
|
25
22
|
end
|
26
23
|
|
27
|
-
def
|
24
|
+
def compatible?
|
28
25
|
super && version >= MINIMUM_VERSION
|
29
26
|
end
|
30
27
|
|
31
|
-
# test environments should not auto instrument test libraries
|
32
|
-
def auto_instrument?
|
33
|
-
false
|
34
|
-
end
|
35
|
-
|
36
28
|
def new_configuration
|
37
29
|
Configuration::Settings.new
|
38
30
|
end
|
@@ -11,14 +11,10 @@ module Datadog
|
|
11
11
|
module Minitest
|
12
12
|
# Patcher enables patching of 'minitest' module.
|
13
13
|
module Patcher
|
14
|
-
include Datadog::
|
14
|
+
include Datadog::CI::Contrib::Patcher
|
15
15
|
|
16
16
|
module_function
|
17
17
|
|
18
|
-
def target_version
|
19
|
-
Integration.version
|
20
|
-
end
|
21
|
-
|
22
18
|
def patch
|
23
19
|
# test session start
|
24
20
|
::Minitest.include(Runner)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../ext/test"
|
4
|
+
require_relative "../instrumentation"
|
4
5
|
require_relative "ext"
|
5
6
|
|
6
7
|
module Datadog
|
@@ -25,7 +26,7 @@ module Datadog
|
|
25
26
|
test_visibility_component.start_test_session(
|
26
27
|
tags: {
|
27
28
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
28
|
-
CI::Ext::Test::TAG_FRAMEWORK_VERSION =>
|
29
|
+
CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s
|
29
30
|
},
|
30
31
|
service: datadog_configuration[:service_name],
|
31
32
|
total_tests_count: (DD_ESTIMATED_TESTS_PER_SUITE * ::Minitest::Runnable.runnables.size).to_i
|
@@ -47,6 +48,10 @@ module Datadog
|
|
47
48
|
|
48
49
|
private
|
49
50
|
|
51
|
+
def datadog_integration
|
52
|
+
CI::Contrib::Instrumentation.fetch_integration(:minitest)
|
53
|
+
end
|
54
|
+
|
50
55
|
def datadog_configuration
|
51
56
|
Datadog.configuration.ci[:minitest]
|
52
57
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative "../../ext/test"
|
4
4
|
require_relative "../../git/local_repository"
|
5
|
+
require_relative "../instrumentation"
|
5
6
|
require_relative "ext"
|
6
7
|
require_relative "helpers"
|
7
8
|
|
@@ -36,7 +37,7 @@ module Datadog
|
|
36
37
|
test_suite_name,
|
37
38
|
tags: {
|
38
39
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
39
|
-
CI::Ext::Test::TAG_FRAMEWORK_VERSION =>
|
40
|
+
CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s,
|
40
41
|
CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(source_file),
|
41
42
|
CI::Ext::Test::TAG_SOURCE_START => line_number.to_s
|
42
43
|
},
|
@@ -79,6 +80,10 @@ module Datadog
|
|
79
80
|
span.finish
|
80
81
|
end
|
81
82
|
|
83
|
+
def datadog_integration
|
84
|
+
CI::Contrib::Instrumentation.fetch_integration(:minitest)
|
85
|
+
end
|
86
|
+
|
82
87
|
def datadog_configuration
|
83
88
|
Datadog.configuration.ci[:minitest]
|
84
89
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "datadog/core/utils/only_once"
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module CI
|
7
|
+
module Contrib
|
8
|
+
# Common behavior for patcher modules.
|
9
|
+
module Patcher
|
10
|
+
def self.included(base)
|
11
|
+
base.singleton_class.prepend(CommonMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Prepended instance methods for all patchers
|
15
|
+
module CommonMethods
|
16
|
+
attr_accessor \
|
17
|
+
:patch_error_result,
|
18
|
+
:patch_successful
|
19
|
+
|
20
|
+
def patch_name
|
21
|
+
(self.class != Class && self.class != Module) ? self.class.name : name
|
22
|
+
end
|
23
|
+
|
24
|
+
def patched?
|
25
|
+
patch_only_once.ran?
|
26
|
+
end
|
27
|
+
|
28
|
+
def patch
|
29
|
+
return unless defined?(super)
|
30
|
+
|
31
|
+
patch_only_once.run do
|
32
|
+
super.tap do
|
33
|
+
@patch_successful = true
|
34
|
+
end
|
35
|
+
rescue => e
|
36
|
+
on_patch_error(e)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Processes patching errors. This default implementation logs the error and reports relevant metrics.
|
41
|
+
# @param e [Exception]
|
42
|
+
def on_patch_error(e)
|
43
|
+
Datadog.logger.error("Failed to apply #{patch_name} patch. Cause: #{e} Location: #{Array(e.backtrace).first}")
|
44
|
+
|
45
|
+
@patch_error_result = {
|
46
|
+
type: e.class.name,
|
47
|
+
message: e.message,
|
48
|
+
line: Array(e.backtrace).first
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def patch_only_once
|
55
|
+
# NOTE: This is not thread-safe
|
56
|
+
@patch_only_once ||= Datadog::Core::Utils::OnlyOnce.new
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|