Skip to content

Commit

Permalink
Feature/fix scope updates (#17)
Browse files Browse the repository at this point in the history
* extend ClassInstrumentationConfiguration (wip)

* extend ClassInstrumentationConfiguration and adjust tests

* add test

* improve tests

* apply requested changes

* optimize method call order

* apply spotless
  • Loading branch information
EddeCCC authored Sep 17, 2024
1 parent b0f1722 commit 944e68e
Show file tree
Hide file tree
Showing 39 changed files with 759 additions and 587 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import org.slf4j.LoggerFactory;
import rocks.inspectit.gepard.agent.configuration.ConfigurationManager;
import rocks.inspectit.gepard.agent.instrumentation.InstrumentationManager;
import rocks.inspectit.gepard.agent.internal.instrumentation.InstrumentationState;
import rocks.inspectit.gepard.agent.notification.NotificationManager;
import rocks.inspectit.gepard.agent.resolver.ConfigurationHolder;
import rocks.inspectit.gepard.agent.resolver.ConfigurationResolver;
import rocks.inspectit.gepard.agent.state.ConfigurationResolver;
import rocks.inspectit.gepard.agent.state.InspectitConfigurationHolder;
import rocks.inspectit.gepard.agent.state.InstrumentationState;
import rocks.inspectit.gepard.agent.transformation.TransformationManager;

@SuppressWarnings("unused")
Expand All @@ -20,7 +20,7 @@ public class InspectitAgentExtension implements AgentExtension {
private static final Logger log = LoggerFactory.getLogger(InspectitAgentExtension.class);

/**
* Entrypoint for the inspectIT gepard extension
* Entrypoint for the inspectIT gepard extension.
*
* @param agentBuilder the configuration builder for the instrumentation agent provided by
* OpenTelemetry
Expand All @@ -35,21 +35,21 @@ public AgentBuilder extend(AgentBuilder agentBuilder, ConfigProperties config) {
NotificationManager notificationManager = NotificationManager.create();
notificationManager.sendStartNotification();

// Create resolver to apply our configuration to classes, types etc.
ConfigurationHolder configurationHolder = ConfigurationHolder.create();
// Prepare instrumentation state tracking
InspectitConfigurationHolder configurationHolder = InspectitConfigurationHolder.create();
ConfigurationResolver configurationResolver = ConfigurationResolver.create(configurationHolder);
InstrumentationState instrumentationState = InstrumentationState.create(configurationResolver);

// Modify the OTel AgentBuilder with our transformer
InstrumentationState instrumentationState = InstrumentationState.create();
TransformationManager transformationManager =
TransformationManager.create(configurationResolver, instrumentationState);
TransformationManager.create(instrumentationState);
agentBuilder = transformationManager.modify(agentBuilder);

// Set up instrumentation
InstrumentationManager instrumentationManager = InstrumentationManager.create();
instrumentationManager.createConfigurationReceiver();
instrumentationManager.startClassDiscovery();
instrumentationManager.startBatchInstrumentation(configurationResolver, instrumentationState);
instrumentationManager.startBatchInstrumentation(instrumentationState);

// Start loading the inspectit configuration
ConfigurationManager configurationManager = ConfigurationManager.create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public void loadConfiguration() {
* configuration server url was set up.
*/
private void startHttpPolling(String serverUrl, ConfigurationPersistence persistence) {
log.info("Starting configuration polling from configuration server with url: {}", serverUrl);
InspectitScheduler scheduler = InspectitScheduler.getInstance();
HttpConfigurationPoller poller = new HttpConfigurationPoller(serverUrl, persistence);
Duration pollingInterval = PropertiesResolver.getPollingInterval();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
import rocks.inspectit.gepard.agent.instrumentation.cache.input.ConfigurationReceiver;
import rocks.inspectit.gepard.agent.instrumentation.cache.process.BatchInstrumenter;
import rocks.inspectit.gepard.agent.internal.configuration.observer.ConfigurationReceivedEvent;
import rocks.inspectit.gepard.agent.internal.instrumentation.InstrumentationState;
import rocks.inspectit.gepard.agent.internal.schedule.InspectitScheduler;
import rocks.inspectit.gepard.agent.resolver.ConfigurationResolver;
import rocks.inspectit.gepard.agent.state.InstrumentationState;

/** Responsible component for setting up and executing instrumentation. */
public class InstrumentationManager {
Expand Down Expand Up @@ -55,12 +54,10 @@ public void startClassDiscovery() {
* Starts the scheduled instrumentation of pending class batched via {@link BatchInstrumenter}.
* Currently, the instrumentation interval is fixed to 500 ms.
*/
public void startBatchInstrumentation(
ConfigurationResolver configurationResolver, InstrumentationState instrumentationState) {
public void startBatchInstrumentation(InstrumentationState instrumentationState) {
InspectitScheduler scheduler = InspectitScheduler.getInstance();
BatchInstrumenter batchInstrumenter =
new BatchInstrumenter(
pendingClassesCache, instrumentation, configurationResolver, instrumentationState);
new BatchInstrumenter(pendingClassesCache, instrumentation, instrumentationState);
Duration batchInterval = Duration.ofMillis(500);
scheduler.startRunnable(batchInstrumenter, batchInterval);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rocks.inspectit.gepard.agent.instrumentation.cache.PendingClassesCache;
import rocks.inspectit.gepard.agent.internal.instrumentation.InstrumentationState;
import rocks.inspectit.gepard.agent.internal.schedule.NamedRunnable;
import rocks.inspectit.gepard.agent.resolver.ConfigurationResolver;
import rocks.inspectit.gepard.agent.state.InstrumentationState;

/**
* Responsible for retransforming classes in batches. The batch size is fixed to 1000. This is
Expand All @@ -25,18 +24,14 @@ public class BatchInstrumenter implements NamedRunnable {

private final Instrumentation instrumentation;

private final ConfigurationResolver configurationResolver;

private final InstrumentationState instrumentationState;

public BatchInstrumenter(
PendingClassesCache pendingClassesCache,
Instrumentation instrumentation,
ConfigurationResolver configurationResolver,
InstrumentationState instrumentationState) {
this.pendingClassesCache = pendingClassesCache;
this.instrumentation = instrumentation;
this.configurationResolver = configurationResolver;
this.instrumentationState = instrumentationState;
}

Expand Down Expand Up @@ -70,10 +65,9 @@ Set<Class<?>> getNextBatch(int batchSize) {
checkedClassesCount++;

try {
boolean shouldInstrument = configurationResolver.shouldInstrument(clazz);
boolean isInstrumented = instrumentationState.isInstrumented(clazz);
boolean shouldRetransform = instrumentationState.shouldRetransform(clazz);

if (shouldInstrument != isInstrumented) classesToRetransform.add(clazz);
if (shouldRetransform) classesToRetransform.add(clazz);
} catch (Exception e) {
log.error("Could not check instrumentation status for {}", clazz.getName(), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,22 @@
*/
public class Scope {

private boolean enabled;

private String fqn;

private List<String> methods;

private boolean enabled;

public Scope() {}

public Scope(String fqn, boolean enabled) {
public Scope(boolean enabled, String fqn, List<String> methods) {
this.fqn = fqn;
this.methods = methods;
this.enabled = enabled;
}

public Scope(String fqn, List<String> methods, boolean enabled) {
this.fqn = fqn;
this.methods = methods;
this.enabled = enabled;
public boolean isEnabled() {
return enabled;
}

public String getFqn() {
Expand All @@ -34,8 +33,4 @@ public String getFqn() {
public List<String> getMethods() {
return methods;
}

public boolean isEnabled() {
return enabled;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ public boolean isEqualTo(Class<?> clazz) {
return typeName.equals(clazz.getName()) && classLoader.equals(clazz.getClassLoader());
}

/**
* @return the fully qualified name of the type
*/
public String getName() {
return typeName;
}

@Override
public boolean equals(Object other) {
if (other instanceof InstrumentedType otherType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,42 @@
package rocks.inspectit.gepard.agent.internal.instrumentation.model;

import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;

/**
* Stores the instrumentation configuration for a specific class. Currently, a class can only be
* instrumented or not. Later, we could add a list of active rules for example.
*/
public class ClassInstrumentationConfiguration {
public record ClassInstrumentationConfiguration(
Set<InstrumentationScope> activeScopes,
ElementMatcher.Junction<MethodDescription> methodMatcher) {

/** The configuration representing that no instrumentation of the class if performed. */
public static final ClassInstrumentationConfiguration NO_INSTRUMENTATION =
new ClassInstrumentationConfiguration(Collections.emptySet(), ElementMatchers.none());

/** Currently, only true */
private final boolean isInstrumented;
/**
* Checks, if this configuration induces bytecode changes to the target class.
*
* @return true, if this configuration expects instrumentation
*/
public boolean isActive() {
return !activeScopes.isEmpty();
}

public ClassInstrumentationConfiguration(boolean isInstrumented) {
this.isInstrumented = isInstrumented;
@Override
public boolean equals(Object o) {
if (o instanceof ClassInstrumentationConfiguration otherConfig)
return activeScopes.equals(otherConfig.activeScopes);
return false;
}

public boolean isInstrumented() {
return isInstrumented;
@Override
public int hashCode() {
return Objects.hash(activeScopes);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package rocks.inspectit.gepard.agent.internal.instrumentation.model;

import java.util.List;
import java.util.Objects;
import rocks.inspectit.gepard.agent.internal.configuration.model.instrumentation.Scope;

/**
* @param fqn the fully qualified name of a class
* @param methods the methods of the class to instrument
*/
public record InstrumentationScope(String fqn, List<String> methods) {

/**
* Creates an {@link InstrumentationScope} out of a {@link Scope}
*
* @param scope the scope
* @return the instrumentation scope
*/
public static InstrumentationScope create(Scope scope) {
return new InstrumentationScope(scope.getFqn(), scope.getMethods());
}

@Override
public boolean equals(Object o) {
if (o instanceof InstrumentationScope otherScope)
return fqn.equals(otherScope.fqn) && methods.equals(otherScope.methods);
return false;
}

@Override
public int hashCode() {
return Objects.hash(fqn, methods);
}
}
Loading

0 comments on commit 944e68e

Please sign in to comment.