13
13
import static java .util .logging .Level .FINE ;
14
14
import static java .util .logging .Level .SEVERE ;
15
15
import static net .bytebuddy .matcher .ElementMatchers .any ;
16
+ import static net .bytebuddy .matcher .ElementMatchers .none ;
16
17
17
18
import io .opentelemetry .context .Context ;
18
19
import io .opentelemetry .context .ContextStorage ;
30
31
import io .opentelemetry .javaagent .bootstrap .internal .ConfiguredResourceAttributesHolder ;
31
32
import io .opentelemetry .javaagent .extension .AgentListener ;
32
33
import io .opentelemetry .javaagent .extension .ignore .IgnoredTypesConfigurer ;
34
+ import io .opentelemetry .javaagent .extension .instrumentation .internal .EarlyInstrumentationModule ;
33
35
import io .opentelemetry .javaagent .tooling .asyncannotationsupport .WeakRefAsyncOperationEndStrategies ;
34
36
import io .opentelemetry .javaagent .tooling .bootstrap .BootstrapPackagesBuilderImpl ;
35
37
import io .opentelemetry .javaagent .tooling .bootstrap .BootstrapPackagesConfigurer ;
36
38
import io .opentelemetry .javaagent .tooling .config .ConfigPropertiesBridge ;
37
39
import io .opentelemetry .javaagent .tooling .config .EarlyInitAgentConfig ;
40
+ import io .opentelemetry .javaagent .tooling .field .FieldBackedImplementationConfiguration ;
41
+ import io .opentelemetry .javaagent .tooling .field .VirtualFieldImplementationInstaller ;
42
+ import io .opentelemetry .javaagent .tooling .field .VirtualFieldImplementationInstallerFactory ;
38
43
import io .opentelemetry .javaagent .tooling .ignore .IgnoredClassLoadersMatcher ;
39
44
import io .opentelemetry .javaagent .tooling .ignore .IgnoredTypesBuilderImpl ;
40
45
import io .opentelemetry .javaagent .tooling .ignore .IgnoredTypesMatcher ;
49
54
import java .util .HashMap ;
50
55
import java .util .List ;
51
56
import java .util .Map ;
57
+ import java .util .Objects ;
52
58
import java .util .logging .LogManager ;
53
59
import java .util .logging .Logger ;
54
60
import java .util .stream .Stream ;
@@ -84,6 +90,8 @@ public class AgentInstaller {
84
90
85
91
private static final Map <String , List <Runnable >> CLASS_LOAD_CALLBACKS = new HashMap <>();
86
92
93
+ private static volatile boolean instrumentationInstalled ;
94
+
87
95
public static void installBytebuddyAgent (
88
96
Instrumentation inst , ClassLoader extensionClassLoader , EarlyInitAgentConfig earlyConfig ) {
89
97
addByteBuddyRawSetting ();
@@ -98,7 +106,7 @@ public static void installBytebuddyAgent(
98
106
if (earlyConfig .getBoolean (JAVAAGENT_ENABLED_CONFIG , true )) {
99
107
setupUnsafe (inst );
100
108
List <AgentListener > agentListeners = loadOrdered (AgentListener .class , extensionClassLoader );
101
- installBytebuddyAgent (inst , extensionClassLoader , agentListeners );
109
+ installBytebuddyAgent (inst , extensionClassLoader , agentListeners , earlyConfig );
102
110
} else {
103
111
logger .fine ("Tracing is disabled, not installing instrumentations." );
104
112
}
@@ -107,31 +115,13 @@ public static void installBytebuddyAgent(
107
115
private static void installBytebuddyAgent (
108
116
Instrumentation inst ,
109
117
ClassLoader extensionClassLoader ,
110
- Iterable <AgentListener > agentListeners ) {
118
+ Iterable <AgentListener > agentListeners ,
119
+ EarlyInitAgentConfig earlyConfig ) {
111
120
112
121
WeakRefAsyncOperationEndStrategies .initialize ();
113
-
114
122
EmbeddedInstrumentationProperties .setPropertiesLoader (extensionClassLoader );
115
-
116
123
setDefineClassHandler ();
117
-
118
- // If noop OpenTelemetry is enabled, autoConfiguredSdk will be null and AgentListeners are not
119
- // called
120
- AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
121
- installOpenTelemetrySdk (extensionClassLoader );
122
-
123
- ConfigProperties sdkConfig = AgentListener .resolveConfigProperties (autoConfiguredSdk );
124
- AgentInstrumentationConfig .internalInitializeConfig (new ConfigPropertiesBridge (sdkConfig ));
125
- copyNecessaryConfigToSystemProperties (sdkConfig );
126
-
127
- setBootstrapPackages (sdkConfig , extensionClassLoader );
128
- ConfiguredResourceAttributesHolder .initialize (
129
- SdkAutoconfigureAccess .getResourceAttributes (autoConfiguredSdk ));
130
-
131
- for (BeforeAgentListener agentListener :
132
- loadOrdered (BeforeAgentListener .class , extensionClassLoader )) {
133
- agentListener .beforeAgent (autoConfiguredSdk );
134
- }
124
+ FieldBackedImplementationConfiguration .configure (earlyConfig );
135
125
136
126
AgentBuilder agentBuilder =
137
127
new AgentBuilder .Default (
@@ -153,9 +143,6 @@ private static void installBytebuddyAgent(
153
143
if (JavaModule .isSupported ()) {
154
144
agentBuilder = agentBuilder .with (new ExposeAgentBootstrapListener (inst ));
155
145
}
156
-
157
- agentBuilder = configureIgnoredTypes (sdkConfig , extensionClassLoader , agentBuilder );
158
-
159
146
if (logger .isLoggable (FINE )) {
160
147
agentBuilder =
161
148
agentBuilder
@@ -165,6 +152,28 @@ private static void installBytebuddyAgent(
165
152
.with (new TransformLoggingListener ());
166
153
}
167
154
155
+ installEarlyInstrumentation (agentBuilder , inst );
156
+
157
+ // If noop OpenTelemetry is enabled, autoConfiguredSdk will be null and AgentListeners are not
158
+ // called
159
+ AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
160
+ installOpenTelemetrySdk (extensionClassLoader );
161
+
162
+ ConfigProperties sdkConfig = AgentListener .resolveConfigProperties (autoConfiguredSdk );
163
+ AgentInstrumentationConfig .internalInitializeConfig (new ConfigPropertiesBridge (sdkConfig ));
164
+ copyNecessaryConfigToSystemProperties (sdkConfig );
165
+
166
+ setBootstrapPackages (sdkConfig , extensionClassLoader );
167
+ ConfiguredResourceAttributesHolder .initialize (
168
+ SdkAutoconfigureAccess .getResourceAttributes (autoConfiguredSdk ));
169
+
170
+ for (BeforeAgentListener agentListener :
171
+ loadOrdered (BeforeAgentListener .class , extensionClassLoader )) {
172
+ agentListener .beforeAgent (autoConfiguredSdk );
173
+ }
174
+
175
+ agentBuilder = configureIgnoredTypes (sdkConfig , extensionClassLoader , agentBuilder );
176
+
168
177
int numberOfLoadedExtensions = 0 ;
169
178
for (AgentExtension agentExtension : loadOrdered (AgentExtension .class , extensionClassLoader )) {
170
179
if (logger .isLoggable (FINE )) {
@@ -191,13 +200,44 @@ private static void installBytebuddyAgent(
191
200
192
201
agentBuilder = AgentBuilderUtil .optimize (agentBuilder );
193
202
ResettableClassFileTransformer resettableClassFileTransformer = agentBuilder .installOn (inst );
203
+ instrumentationInstalled = true ;
194
204
ClassFileTransformerHolder .setClassFileTransformer (resettableClassFileTransformer );
195
205
196
206
addHttpServerResponseCustomizers (extensionClassLoader );
197
207
198
208
runAfterAgentListeners (agentListeners , autoConfiguredSdk , sdkConfig );
199
209
}
200
210
211
+ private static void installEarlyInstrumentation (
212
+ AgentBuilder agentBuilder , Instrumentation instrumentation ) {
213
+ // We are only going to install the virtual fields here. Installing virtual field changes class
214
+ // structure and can not be applied to already loaded classes.
215
+ agentBuilder = agentBuilder .with (AgentBuilder .RedefinitionStrategy .DISABLED );
216
+
217
+ AgentBuilder .Identified .Extendable extendableAgentBuilder =
218
+ agentBuilder
219
+ .ignore (
220
+ target -> instrumentationInstalled , // turn off after instrumentation is installed
221
+ Objects ::nonNull )
222
+ .type (none ())
223
+ .transform (
224
+ (builder , typeDescription , classLoader , module , protectionDomain ) -> builder );
225
+
226
+ VirtualFieldImplementationInstallerFactory virtualFieldInstallerFactory =
227
+ new VirtualFieldImplementationInstallerFactory ();
228
+ for (EarlyInstrumentationModule earlyInstrumentationModule :
229
+ loadOrdered (EarlyInstrumentationModule .class , Utils .getExtensionsClassLoader ())) {
230
+
231
+ VirtualFieldImplementationInstaller contextProvider =
232
+ virtualFieldInstallerFactory .create (
233
+ earlyInstrumentationModule .getInstrumentationModule ());
234
+ extendableAgentBuilder = contextProvider .injectFields (extendableAgentBuilder );
235
+ }
236
+
237
+ agentBuilder = AgentBuilderUtil .optimize (extendableAgentBuilder );
238
+ agentBuilder .installOn (instrumentation );
239
+ }
240
+
201
241
private static void copyNecessaryConfigToSystemProperties (ConfigProperties config ) {
202
242
for (String property : asList ("otel.instrumentation.experimental.span-suppression-strategy" )) {
203
243
String value = config .getString (property );
0 commit comments