io.perfana.client.PerfanaExecutorEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of perfana-java-client Show documentation
Show all versions of perfana-java-client Show documentation
Perfana java client for integrating performance test tools
package io.perfana.client;
import io.perfana.client.api.PerfanaCaller;
import io.perfana.client.api.PerfanaClientLogger;
import io.perfana.client.api.PerfanaConnectionSettings;
import io.perfana.client.api.PerfanaTestContext;
import io.perfana.client.exception.PerfanaClientRuntimeException;
import io.perfana.event.PerfanaEventBroadcaster;
import io.perfana.event.PerfanaEventProperties;
import io.perfana.event.ScheduleEvent;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class PerfanaExecutorEngine {
private PerfanaClientLogger logger;
private ScheduledExecutorService executorKeepAlive;
private ScheduledExecutorService executorCustomEvents;
public PerfanaExecutorEngine(PerfanaClientLogger logger) {
if (logger == null) {
throw new PerfanaClientRuntimeException("Logger is null");
}
this.logger = logger;
}
public void startKeepAliveThread(PerfanaCaller perfana, PerfanaTestContext context, PerfanaConnectionSettings settings, PerfanaEventBroadcaster broadcaster, PerfanaEventProperties eventProperties) {
if (executorKeepAlive != null) {
throw new RuntimeException("Cannot start keep alive thread multiple times!");
}
logger.info(String.format("Calling Perfana (%s) keep alive every %s.", settings.getPerfanaUrl(), settings.getKeepAliveDuration()));
executorKeepAlive = createKeepAliveScheduler();
KeepAliveRunner keepAliveRunner = new KeepAliveRunner(perfana, context, broadcaster, eventProperties);
executorKeepAlive.scheduleAtFixedRate(keepAliveRunner, 0, settings.getKeepAliveDuration().getSeconds(), TimeUnit.SECONDS);
}
private void addToExecutor(ScheduledExecutorService executorService, PerfanaTestContext context, ScheduleEvent event, PerfanaEventProperties eventProperties, PerfanaCaller perfana, PerfanaEventBroadcaster broadcaster) {
executorService.schedule(new EventRunner(context, eventProperties, event, broadcaster, perfana), event.getDuration().getSeconds(), TimeUnit.SECONDS);
}
void shutdownThreadsNow() {
logger.info("Shutdown Perfana Executor threads");
if (executorKeepAlive != null) {
executorKeepAlive.shutdownNow();
}
if (executorCustomEvents != null) {
List runnables = executorCustomEvents.shutdownNow();
if (runnables.size() > 0) {
logger.warn("There are " + runnables.size() + " custom Perfana events that are not (fully) executed!");
}
}
executorKeepAlive = null;
executorCustomEvents = null;
}
public void startCustomEventScheduler(PerfanaCaller perfana, PerfanaTestContext context, List scheduleEvents, PerfanaEventBroadcaster broadcaster, PerfanaEventProperties eventProperties) {
if (!(scheduleEvents == null || scheduleEvents.isEmpty())) {
logger.info(createEventScheduleMessage(scheduleEvents));
executorCustomEvents = createCustomEventScheduler();
scheduleEvents.forEach(event -> addToExecutor(executorCustomEvents, context, event, eventProperties, perfana, broadcaster));
}
else {
logger.info("No custom Perfana schedule events found.");
}
}
private String createEventScheduleMessage(List scheduleEvents) {
StringBuilder message = new StringBuilder();
message.append("=== custom Perfana events schedule ===");
scheduleEvents.forEach(event -> message
.append("\n==> ")
.append(String.format("ScheduleEvent %-16s [fire-at=%-8s settings=%s]", event.getName(), event.getDuration(), event.getSettings())));
return message.toString();
}
private ScheduledExecutorService createKeepAliveScheduler() {
return Executors.newSingleThreadScheduledExecutor(r -> {
String threadName = "Perfana-Keep-Alive-Thread";
logger.info("Creating new thead: " + threadName);
return new Thread(r, threadName);
});
}
private ScheduledExecutorService createCustomEventScheduler() {
return Executors.newScheduledThreadPool(2, new ThreadFactory() {
private final AtomicInteger perfanaThreadCount = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
String threadName = "Perfana-Custom-Event-Thread-" + perfanaThreadCount.incrementAndGet();
logger.info("Creating new thead: " + threadName);
return new Thread(r, threadName);
}
});
}
public static class KeepAliveRunner implements Runnable {
private final PerfanaCaller perfana;
private final PerfanaTestContext context;
private final PerfanaEventBroadcaster broadcaster;
private final PerfanaEventProperties eventProperties;
KeepAliveRunner(PerfanaCaller perfana, PerfanaTestContext context, PerfanaEventBroadcaster broadcaster, PerfanaEventProperties eventProperties) {
this.perfana = perfana;
this.context = context;
this.broadcaster = broadcaster;
this.eventProperties = eventProperties;
}
@Override
public void run() {
perfana.callPerfanaTestEndpoint(context, false);
broadcaster.broadCastKeepAlive(context, eventProperties);
}
@Override
public String toString() {
return "KeepAliveRunner for " + context.getTestRunId();
}
}
public static class EventRunner implements Runnable {
private final ScheduleEvent event;
private final PerfanaTestContext context;
private final PerfanaEventProperties eventProperties;
private final PerfanaEventBroadcaster eventBroadcaster;
private final PerfanaCaller perfana;
public EventRunner(PerfanaTestContext context, PerfanaEventProperties eventProperties, ScheduleEvent event, PerfanaEventBroadcaster eventBroadcaster, PerfanaCaller perfana) {
this.event = event;
this.context = context;
this.eventProperties = eventProperties;
this.eventBroadcaster = eventBroadcaster;
this.perfana = perfana;
}
@Override
public void run() {
perfana.callPerfanaEvent(context, event.getName());
eventBroadcaster.broadcastCustomEvent(context, eventProperties, event);
}
@Override
public String toString() {
return String.format("EventRunner for event %s for testId %s", event, context.getTestRunId());
}
}
}