Skip to content

Commit

Permalink
Optimize within matching
Browse files Browse the repository at this point in the history
ByteBuddy's StringMatcher uses String.matches which performs about 10x slower
than caching a Pattern inside a custom PatternMatcher

Uglify the test / reference pattern examples to more closely match the required patterns

Flag incorrect InstrumentationLoader test
  • Loading branch information
Marko Elezovic committed Jun 11, 2022
1 parent 1c370d0 commit 6846183
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 20 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
**Kanela** is a Java Agent written in Java 8+ and powered by [ByteBuddy] with some additionally [ASM] features to provide a simple way to instrument applications running on the JVM and allow introduce Kamon features such as context propagation and metrics.


[ByteBuddy]:http://bytebuddy.net/#/
[ASM]:http://asm.ow2.org/
[ByteBuddy]:https://bytebuddy.net/#/
[ASM]:https://asm.ow2.io/
24 changes: 12 additions & 12 deletions agent-test/src/main/resources/application.conf
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
kanela {
modules {
example-module {
name = "Example Module"
stoppable = false
instrumentations = [
"app.kanela.instrumentation.MonitorInstrumentation",
]
within = [ "app.kanela.cases.+" ]
}
modules {
example-module {
name = "Example Module"
stoppable = false
instrumentations = [
"app.kanela.instrumentation.MonitorInstrumentation",
]
within = [ "app\\.kanela\\.cases\\..+" ]
}
debug-mode = false
class-dumper.enabled = false
}
}
debug-mode = false
class-dumper.enabled = false
}
4 changes: 2 additions & 2 deletions agent-test/src/test/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ kanela {
instrumentations = [ ] // written by spec

within = [
"app.kanela..*",
"java.net.*"
"app\\.kanela\\..*",
"java\\.net\\..*",
]

bootstrap-injection {
Expand Down
16 changes: 14 additions & 2 deletions agent/src/main/java/kanela/agent/builder/KanelaAgentBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import kanela.agent.cache.PoolStrategyCache;
import kanela.agent.resubmitter.PeriodicResubmitter;
import kanela.agent.util.ListBuilder;
import kanela.agent.util.PatternMatcher;
import kanela.agent.util.conf.KanelaConfiguration;
import kanela.agent.util.log.Logger;
import lombok.Value;
Expand All @@ -36,6 +37,7 @@
import net.bytebuddy.dynamic.scaffold.MethodGraph;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.NameMatcher;

import java.lang.instrument.Instrumentation;
import java.util.ArrayList;
Expand Down Expand Up @@ -141,10 +143,20 @@ private AgentBuilder.Listener additionalListeners() {
}

private ElementMatcher.Junction<NamedElement> ignoreMatches() {
return not(nameMatches(moduleDescription.getWithinPackage()));
final String withinPackage = moduleDescription.getWithinPackage();
if (withinPackage.isEmpty()) {
return any();
} else {
return not(new NameMatcher<>(new PatternMatcher(withinPackage)));
}
}

private ElementMatcher.Junction<NamedElement> moduleExcludes() {
return nameMatches(moduleDescription.getExcludePackage());
final String moduleExcludes = moduleDescription.getExcludePackage();
if (moduleExcludes.isEmpty()) {
return none();
} else {
return new NameMatcher<>(new PatternMatcher(moduleExcludes));
}
}
}
18 changes: 18 additions & 0 deletions agent/src/main/java/kanela/agent/util/PatternMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package kanela.agent.util;

import net.bytebuddy.matcher.ElementMatcher;

import java.util.regex.Pattern;

public class PatternMatcher extends ElementMatcher.Junction.AbstractBase<String> {
private final Pattern regex;

public PatternMatcher(final String regex) {
this.regex = Pattern.compile(regex);
}

@Override
public boolean matches(final String target) {
return regex.matcher(target).matches();
}
}
4 changes: 2 additions & 2 deletions agent/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ kanela {
# disable-class-format-changes = "true|false" (optional)
# # List of fully qualified name of the implementation of kanela.agent.api.instrumentation.InstrumentationBuilderr.
# instrumentations = []
# # Excludes all types that matches the list of patterns. e.g. org.apache. *
# # Excludes all types that match the list of patterns. e.g. org\.apache\..*
# exclude = []
# # Only instruments types that are within the list of patterns. e.g. javax.*
# # Only instruments types that are within the list of patterns. e.g. javax\..*
# within = []
# # The exception handler strategy on instrumentation error: LOG|SUPPRESS
# exception-handler-strategy = "SUPPRESS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ class InstrumentationLoaderSpec extends FlatSpec with Matchers with BeforeAndAft

when(agentModuleDescriptionMock.getInstrumentations).thenReturn(JList.empty[String]())
when(agentModuleDescriptionMock.getWithinPackage).thenReturn("")
when(agentModuleDescriptionMock.getExcludePackage).thenReturn("")
when(agentModuleDescriptionMock.getName).thenReturn("x-module")

InstrumentationLoader.load(instrumentationMock, Thread.currentThread().getContextClassLoader, agentConfiguration)

verify(agentConfiguration, times(1)).getAgentModules
}

// TODO FIXME: This test is useless since it explodes before getting to InstrumentationLoader.load
// It should be refactored to expect a specific exception and not a generic RuntimeException
// (currently blowing up due to errorneous spy+mock combo)
"with an unknown instrumentation" should "blow up" in {
val instrumentationMock = mock(classOf[Instrumentation])
val agentModuleDescriptionMock = mock(classOf[ModuleConfiguration])
Expand Down Expand Up @@ -81,6 +85,7 @@ class InstrumentationLoaderSpec extends FlatSpec with Matchers with BeforeAndAft

when(agentModuleDescriptionMock.getInstrumentations).thenReturn(JList.of[String]("kanela.agent.instrumentation.KamonFakeInstrumentationBuilder"))
when(agentModuleDescriptionMock.getWithinPackage).thenReturn("")
when(agentModuleDescriptionMock.getExcludePackage).thenReturn("")
when(agentModuleDescriptionMock.getName).thenReturn("x-module")

InstrumentationLoader.load(instrumentationMock, Thread.currentThread().getContextClassLoader, agentConfiguration)
Expand Down

0 comments on commit 6846183

Please sign in to comment.