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