package org.stagemonitor.tracing; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; import org.stagemonitor.core.util.ClassUtils; import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Set; import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; import static org.stagemonitor.core.instrument.OverridesMethodElementMatcher.overridesSuperMethodThat; import static org.stagemonitor.core.instrument.StagemonitorClassNameMatcher.isInsideMonitoredProject; public class MethodLevelMonitorRequestsTransformer extends AbstractMonitorRequestsTransformer { private final Set<Class<? extends Annotation>> asyncCallAnnotations = new HashSet<Class<? extends Annotation>>(); @SuppressWarnings("unchecked") public MethodLevelMonitorRequestsTransformer() { asyncCallAnnotations.add((Class<? extends Annotation>) ClassUtils.forNameOrNull("org.springframework.scheduling.annotation.Async")); asyncCallAnnotations.add((Class<? extends Annotation>) ClassUtils.forNameOrNull("javax.ejb.Asynchronous")); if (configuration.getConfig(TracingPlugin.class).isMonitorScheduledTasks()) { asyncCallAnnotations.add((Class<? extends Annotation>) ClassUtils.forNameOrNull("org.springframework.scheduling.annotation.Scheduled")); asyncCallAnnotations.add((Class<? extends Annotation>) ClassUtils.forNameOrNull("org.springframework.scheduling.annotation.Schedules")); asyncCallAnnotations.add((Class<? extends Annotation>) ClassUtils.forNameOrNull("javax.ejb.Schedule")); asyncCallAnnotations.add((Class<? extends Annotation>) ClassUtils.forNameOrNull("javax.ejb.Schedules")); } asyncCallAnnotations.remove(null); } @Override protected ElementMatcher.Junction<MethodDescription> getExtraMethodElementMatcher() { ElementMatcher.Junction<MethodDescription> matcher = isAnnotatedWith(MonitorRequests.class) // TODO maybe add a configuration to disable super method search as it is relatively costly // InstrumentationPerformanceTest without: ~20ms with: ~420ms // 0,5s is relatively much compared to other matchers but not really noticeable on startup .or(overridesSuperMethodThat(isAnnotatedWith(MonitorRequests.class)).onSuperClassesThat(isInsideMonitoredProject())); for (Class<? extends Annotation> annotation : asyncCallAnnotations) { matcher = matcher.or(isAnnotatedWith(annotation)); } return matcher; } }