|
5 | 5 | module Datadog
|
6 | 6 | module CI
|
7 | 7 | module Contrib
|
8 |
| - module Integration |
| 8 | + class Integration |
9 | 9 | @registry = {}
|
10 | 10 |
|
11 |
| - def self.included(base) |
12 |
| - base.extend(ClassMethods) |
13 |
| - base.include(InstanceMethods) |
| 11 | + def self.inherited(subclass) |
| 12 | + @registry[integration_name(subclass)] = subclass.new |
14 | 13 | end
|
15 | 14 |
|
16 |
| - def self.register(klass, name) |
17 |
| - registry[name] = klass.new |
| 15 | + # take the parent module name and downcase it |
| 16 | + # for example for Datadog::CI::Contrib::RSpec::Integration it will be :rspec |
| 17 | + def self.integration_name(subclass) |
| 18 | + result = subclass.name&.split("::")&.[](-2)&.downcase&.to_sym |
| 19 | + raise "Integration name could not be derived for #{subclass}" if result.nil? |
| 20 | + result |
18 | 21 | end
|
19 | 22 |
|
20 | 23 | def self.registry
|
21 | 24 | @registry
|
22 | 25 | end
|
23 | 26 |
|
24 |
| - # Class-level methods for Integration |
25 |
| - module ClassMethods |
26 |
| - def register_as(name) |
27 |
| - Integration.register(self, name) |
28 |
| - end |
29 |
| - |
30 |
| - # Version of the integration target code in the environment. |
31 |
| - # |
32 |
| - # This is the gem version, when the instrumentation target is a Ruby gem. |
33 |
| - # |
34 |
| - # If the target for instrumentation has concept of versioning, override {.version}, |
35 |
| - # otherwise override {.available?} and implement a custom target presence check. |
36 |
| - # @return [Object] the target version |
37 |
| - def version |
38 |
| - nil |
39 |
| - end |
| 27 | + # Version of the integration target code in the environment. |
| 28 | + # |
| 29 | + # This is the gem version, when the instrumentation target is a Ruby gem. |
| 30 | + # |
| 31 | + # If the target for instrumentation has concept of versioning, override {.version}, |
| 32 | + # otherwise override {.available?} and implement a custom target presence check. |
| 33 | + # @return [Object] the target version |
| 34 | + def version |
| 35 | + nil |
| 36 | + end |
40 | 37 |
|
41 |
| - # Is the target available to be instrumented? (e.g. gem installed?) |
42 |
| - # |
43 |
| - # The target doesn't have to be loaded (e.g. `require`) yet, but needs to be able |
44 |
| - # to be loaded before instrumentation can commence. |
45 |
| - # |
46 |
| - # By default, {.available?} checks if {.version} returned a non-nil object. |
47 |
| - # |
48 |
| - # If the target for instrumentation has concept of versioning, override {.version}, |
49 |
| - # otherwise override {.available?} and implement a custom target presence check. |
50 |
| - # @return [Boolean] is the target available for instrumentation in this Ruby environment? |
51 |
| - def available? |
52 |
| - !version.nil? |
53 |
| - end |
| 38 | + # Is the target available to be instrumented? (e.g. gem installed?) |
| 39 | + # |
| 40 | + # The target doesn't have to be loaded (e.g. `require`) yet, but needs to be able |
| 41 | + # to be loaded before instrumentation can commence. |
| 42 | + # |
| 43 | + # By default, {.available?} checks if {.version} returned a non-nil object. |
| 44 | + # |
| 45 | + # If the target for instrumentation has concept of versioning, override {.version}, |
| 46 | + # otherwise override {.available?} and implement a custom target presence check. |
| 47 | + # @return [Boolean] is the target available for instrumentation in this Ruby environment? |
| 48 | + def available? |
| 49 | + !version.nil? |
| 50 | + end |
54 | 51 |
|
55 |
| - # Is the target loaded into the application? (e.g. gem required? Constant defined?) |
56 |
| - # |
57 |
| - # The target's objects should be ready to be referenced by the instrumented when {.loaded} |
58 |
| - # returns `true`. |
59 |
| - # |
60 |
| - # @return [Boolean] is the target ready to be referenced during instrumentation? |
61 |
| - def loaded? |
62 |
| - true |
63 |
| - end |
| 52 | + # Is the target loaded into the application? (e.g. gem required? Constant defined?) |
| 53 | + # |
| 54 | + # The target's objects should be ready to be referenced by the instrumented when {.loaded} |
| 55 | + # returns `true`. |
| 56 | + # |
| 57 | + # @return [Boolean] is the target ready to be referenced during instrumentation? |
| 58 | + def loaded? |
| 59 | + true |
| 60 | + end |
64 | 61 |
|
65 |
| - # Is this instrumentation compatible with the available target? (e.g. minimum version met?) |
66 |
| - # @return [Boolean] is the available target compatible with this instrumentation? |
67 |
| - def compatible? |
68 |
| - available? |
69 |
| - end |
| 62 | + # Is this instrumentation compatible with the available target? (e.g. minimum version met?) |
| 63 | + # @return [Boolean] is the available target compatible with this instrumentation? |
| 64 | + def compatible? |
| 65 | + available? |
| 66 | + end |
70 | 67 |
|
71 |
| - # Can the patch for this integration be applied? |
72 |
| - # |
73 |
| - # By default, this is equivalent to {#available?}, {#loaded?}, and {#compatible?} |
74 |
| - # all being truthy. |
75 |
| - def patchable? |
76 |
| - available? && loaded? && compatible? |
77 |
| - end |
| 68 | + # Can the patch for this integration be applied? |
| 69 | + # |
| 70 | + # By default, this is equivalent to {#available?}, {#loaded?}, and {#compatible?} |
| 71 | + # all being truthy. |
| 72 | + def patchable? |
| 73 | + available? && loaded? && compatible? |
78 | 74 | end
|
79 | 75 |
|
80 |
| - module InstanceMethods |
81 |
| - # returns the configuration instance. |
82 |
| - def configuration |
83 |
| - @configuration ||= new_configuration |
84 |
| - end |
| 76 | + # returns the configuration instance. |
| 77 | + def configuration |
| 78 | + @configuration ||= new_configuration |
| 79 | + end |
85 | 80 |
|
86 |
| - def configure(options = {}, &block) |
87 |
| - configuration.configure(options, &block) |
88 |
| - configuration |
89 |
| - end |
| 81 | + def configure(options = {}, &block) |
| 82 | + configuration.configure(options, &block) |
| 83 | + configuration |
| 84 | + end |
90 | 85 |
|
91 |
| - # Resets all configuration options |
92 |
| - def reset_configuration! |
93 |
| - @configuration = nil |
94 |
| - end |
| 86 | + def enabled |
| 87 | + configuration.enabled |
| 88 | + end |
95 | 89 |
|
96 |
| - def enabled |
97 |
| - configuration.enabled |
98 |
| - end |
| 90 | + # The patcher module to inject instrumented objects into the instrumentation target. |
| 91 | + # |
| 92 | + # {Contrib::Patcher} includes the basic functionality of a patcher. `include`ing |
| 93 | + # {Contrib::Patcher} into a new module is the recommend way to create a custom patcher. |
| 94 | + # |
| 95 | + # @return [Contrib::Patcher] a module that `include`s {Contrib::Patcher} |
| 96 | + def patcher |
| 97 | + nil |
| 98 | + end |
99 | 99 |
|
100 |
| - # The patcher module to inject instrumented objects into the instrumentation target. |
101 |
| - # |
102 |
| - # {Contrib::Patcher} includes the basic functionality of a patcher. `include`ing |
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 |
| 100 | + # @!visibility private |
| 101 | + def patch |
| 102 | + # @type var patcher_klass: untyped |
| 103 | + patcher_klass = patcher |
| 104 | + if !patchable? || patcher_klass.nil? |
| 105 | + return { |
| 106 | + available: available?, |
| 107 | + loaded: loaded?, |
| 108 | + compatible: compatible?, |
| 109 | + patchable: patchable? |
| 110 | + } |
108 | 111 | end
|
109 | 112 |
|
110 |
| - # @!visibility private |
111 |
| - def patch |
112 |
| - # @type var patcher_klass: untyped |
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 |
| 113 | + patcher_klass.patch |
| 114 | + true |
| 115 | + end |
126 | 116 |
|
127 |
| - # Can the patch for this integration be applied automatically? |
128 |
| - # @return [Boolean] can the tracer activate this instrumentation without explicit user input? |
129 |
| - def auto_instrument? |
130 |
| - true |
131 |
| - end |
| 117 | + # Can the patch for this integration be applied automatically? |
| 118 | + # @return [Boolean] can the tracer activate this instrumentation without explicit user input? |
| 119 | + def auto_instrument? |
| 120 | + true |
| 121 | + end |
132 | 122 |
|
133 |
| - protected |
134 |
| - |
135 |
| - # Returns a new configuration object for this integration. |
136 |
| - # |
137 |
| - # This method normally needs to be overridden for each integration |
138 |
| - # as their settings, defaults and environment variables are |
139 |
| - # specific for each integration. |
140 |
| - # |
141 |
| - # @return [Datadog::CI::Contrib::Settings] a new, integration-specific settings object |
142 |
| - def new_configuration |
143 |
| - Datadog::CI::Contrib::Settings.new |
144 |
| - end |
| 123 | + # Returns a new configuration object for this integration. |
| 124 | + # |
| 125 | + # This method normally needs to be overridden for each integration |
| 126 | + # as their settings, defaults and environment variables are |
| 127 | + # specific for each integration. |
| 128 | + # |
| 129 | + # @return [Datadog::CI::Contrib::Settings] a new, integration-specific settings object |
| 130 | + def new_configuration |
| 131 | + Datadog::CI::Contrib::Settings.new |
145 | 132 | end
|
146 | 133 | end
|
147 | 134 | end
|
|
0 commit comments