mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-17 12:34:46 +00:00
[AB-xxx] try for instrumenting
This commit is contained in:
@@ -207,4 +207,9 @@ public class ListenerExecutorConfig {
|
||||
return executorService.setupExecutorFor("voiceChatLeftListener");
|
||||
}
|
||||
|
||||
@Bean(name = "genericExecutor")
|
||||
public TaskExecutor genericExecutor() {
|
||||
return executorService.setupExecutorFor("genericExecutor");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import dev.sheldan.abstracto.core.templating.model.AttachedFile;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
@@ -58,6 +60,9 @@ public class InteractionServiceBean implements InteractionService {
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
public static final CounterMetric EPHEMERAL_MESSAGES_SEND = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
@@ -259,6 +264,8 @@ public class InteractionServiceBean implements InteractionService {
|
||||
}
|
||||
|
||||
public CompletableFuture<InteractionHook> replyMessageToSend(MessageToSend messageToSend, IReplyCallback callback) {
|
||||
Span newSpan = tracer.nextSpan().name("send-message-to-interaction");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
ReplyCallbackAction action = null;
|
||||
if(messageToSend.getUseComponentsV2()) {
|
||||
action = callback.replyComponents(messageToSend.getComponents()).useComponentsV2();
|
||||
@@ -333,10 +340,12 @@ public class InteractionServiceBean implements InteractionService {
|
||||
}
|
||||
}
|
||||
|
||||
if(action == null) {
|
||||
throw new AbstractoRunTimeException("The callback did not result in any message.");
|
||||
if (action == null) {
|
||||
throw new AbstractoRunTimeException("The callback did not result in any message.");
|
||||
}
|
||||
return action.submit();
|
||||
}
|
||||
}
|
||||
return action.submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.gson.Gson;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionResult;
|
||||
import dev.sheldan.abstracto.core.interaction.button.ButtonPostInteractionExecution;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
|
||||
import dev.sheldan.abstracto.core.interaction.button.ButtonPayload;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
@@ -63,7 +64,7 @@ public class SyncButtonClickedListenerBean extends ListenerAdapter {
|
||||
@Override
|
||||
public void onButtonInteraction(@Nonnull ButtonInteractionEvent event) {
|
||||
if(listenerList == null) return;
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), buttonClickedExecutor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), MetricUtils.wrapExecutor(buttonClickedExecutor)).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in async button event.", throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import dev.sheldan.abstracto.core.interaction.context.message.listener.MessageCo
|
||||
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.listener.interaction.MessageContextInteractionModel;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
@@ -65,7 +66,7 @@ public class MessageContextCommandListenerBean extends ListenerAdapter {
|
||||
@Override
|
||||
public void onMessageContextInteraction(MessageContextInteractionEvent event) {
|
||||
if(listenerList == null) return;
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), messageContextCommandExecutor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), MetricUtils.wrapExecutor(messageContextCommandExecutor)).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in async message context event.", throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -3,9 +3,9 @@ package dev.sheldan.abstracto.core.interaction.menu;
|
||||
import com.google.gson.Gson;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionResult;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListener;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListenerModel;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
@@ -60,7 +60,7 @@ public class StringSelectMenuListenerBean extends ListenerAdapter {
|
||||
public void onStringSelectInteraction(@Nonnull StringSelectInteractionEvent event) {
|
||||
if(listenerList == null) return;
|
||||
event.deferEdit().queue();
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), buttonClickedExecutor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), MetricUtils.wrapExecutor(buttonClickedExecutor)).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in async button event.", throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionResult;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.ModalPayload;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.ModalPostInteractionExecution;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
@@ -62,7 +63,7 @@ public class ModalInteractionListenerBean extends ListenerAdapter {
|
||||
@Override
|
||||
public void onModalInteraction(@Nonnull ModalInteractionEvent event) {
|
||||
if(listenerList == null) return;
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), modalInteractionExecutor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), MetricUtils.wrapExecutor(modalInteractionExecutor)).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in modal interaction event.", throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -31,6 +31,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
@@ -100,6 +105,12 @@ public class SlashCommandListenerBean extends ListenerAdapter {
|
||||
@Autowired
|
||||
private SchedulerService schedulerService;
|
||||
|
||||
@Autowired
|
||||
private ObservationRegistry observationRegistry;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||
|
||||
@@ -124,6 +135,8 @@ public class SlashCommandListenerBean extends ListenerAdapter {
|
||||
|
||||
@Override
|
||||
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
|
||||
Observation observation = Observation.createNotStarted("slash-command-received", this.observationRegistry);
|
||||
observation.observe(() -> {
|
||||
try {
|
||||
if(commands == null || commands.isEmpty()) return;
|
||||
if(ContextUtils.hasGuild(event.getInteraction())) {
|
||||
@@ -131,43 +144,59 @@ public class SlashCommandListenerBean extends ListenerAdapter {
|
||||
} else {
|
||||
log.debug("Executing slash command by user {}", event.getUser().getIdLong());
|
||||
}
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), slashCommandExecutor).exceptionally(throwable -> {
|
||||
Span span = tracer.currentSpan();
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
|
||||
self.executeListenerLogic(event).whenComplete((unused, throwable) -> {
|
||||
span.end();
|
||||
});
|
||||
}
|
||||
|
||||
}, slashCommandExecutor).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in async slash command event.", throwable);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Failed to process slash command interaction event.", exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void executeListenerLogic(SlashCommandInteractionEvent event) {
|
||||
public CompletableFuture<Void> executeListenerLogic(SlashCommandInteractionEvent event) {
|
||||
Optional<Command> potentialCommand = findCommand(event);
|
||||
potentialCommand.ifPresent(command -> {
|
||||
metricService.incrementCounter(SLASH_COMMANDS_PROCESSED_COUNTER);
|
||||
try {
|
||||
commandService.isCommandExecutable(command, event).thenAccept(conditionResult -> {
|
||||
self.executeCommand(event, command, conditionResult);
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Error while executing command {}", command.getConfiguration().getName(), throwable);
|
||||
CommandResult commandResult = CommandResult.fromError(throwable.getMessage(), throwable);
|
||||
if(potentialCommand.isPresent()) {
|
||||
Command command = potentialCommand.get();
|
||||
metricService.incrementCounter(SLASH_COMMANDS_PROCESSED_COUNTER);
|
||||
try {
|
||||
Span span = tracer.currentSpan();
|
||||
span.tag("command-name", command.getConfiguration().getName());
|
||||
return commandService.isCommandExecutable(command, event).thenCompose(conditionResult -> {
|
||||
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
|
||||
return self.executeCommand(event, command, conditionResult);
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Error while executing command {}", command.getConfiguration().getName(), throwable);
|
||||
CommandResult commandResult = CommandResult.fromError(throwable.getMessage(), throwable);
|
||||
self.executePostCommandListener(command, event, commandResult);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Error while checking if command {} is executable.", command.getConfiguration().getName(), exception);
|
||||
CommandResult commandResult = CommandResult.fromError(exception.getMessage(), exception);
|
||||
self.executePostCommandListener(command, event, commandResult);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Error while checking if command {} is executable.", command.getConfiguration().getName(), exception);
|
||||
CommandResult commandResult = CommandResult.fromError(exception.getMessage(), exception);
|
||||
self.executePostCommandListener(command, event, commandResult);
|
||||
}
|
||||
});
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandAutoCompleteInteraction(@Nonnull CommandAutoCompleteInteractionEvent event) {
|
||||
try {
|
||||
if(commands == null || commands.isEmpty()) return;
|
||||
CompletableFuture.runAsync(() -> self.executeAutCompleteListenerLogic(event), slashCommandAutoCompleteExecutor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeAutCompleteListenerLogic(event), MetricUtils.wrapExecutor(slashCommandAutoCompleteExecutor)).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in async auto complete interaction event.", throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -6,6 +6,9 @@ import dev.sheldan.abstracto.core.interactive.setup.callback.MessageInteractionC
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -20,6 +23,9 @@ public class InteractiveMessageReceivedListener implements AsyncMessageReceivedL
|
||||
// TODO timeout
|
||||
private Map<Long, Map<Long, Map<Long, MessageInteractionCallback>>> callbacks = new HashMap<>();
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
private static final Lock runTimeLock = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
@@ -40,7 +46,8 @@ public class InteractiveMessageReceivedListener implements AsyncMessageReceivedL
|
||||
|
||||
public boolean executeCallback(MessageReceivedModel model) {
|
||||
runTimeLock.lock();
|
||||
try {
|
||||
Span newSpan = tracer.nextSpan().name("interactive-message-tracker");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())){
|
||||
if(callbacks.containsKey(model.getServerId())) {
|
||||
Map<Long, Map<Long, MessageInteractionCallback>> channelMap = callbacks.get(model.getServerId());
|
||||
if(channelMap.containsKey(model.getMessage().getChannel().getIdLong())) {
|
||||
@@ -56,6 +63,7 @@ public class InteractiveMessageReceivedListener implements AsyncMessageReceivedL
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
newSpan.end();
|
||||
runTimeLock.unlock();
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.MessageCache;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
@@ -28,18 +26,6 @@ public class AsyncMessageReceivedListenerBean extends ListenerAdapter {
|
||||
@Autowired(required = false)
|
||||
private List<AsyncMessageReceivedListener> listenerList;
|
||||
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private ExceptionService exceptionService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("messageReceivedExecutor")
|
||||
private TaskExecutor messageReceivedExecutor;
|
||||
@@ -47,14 +33,21 @@ public class AsyncMessageReceivedListenerBean extends ListenerAdapter {
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
private ObservationRegistry observationRegistry;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onMessageReceived(@Nonnull MessageReceivedEvent event) {
|
||||
if(listenerList == null) return;
|
||||
if(!event.isFromGuild()) return;
|
||||
messageCache.putMessageInCache(event.getMessage());
|
||||
MessageReceivedModel model = getModel(event);
|
||||
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, messageReceivedExecutor));
|
||||
Observation observation = Observation.createNotStarted("async-message-received", this.observationRegistry);
|
||||
observation.lowCardinalityKeyValue("some-tag", "some-value");
|
||||
observation.observe(() -> {
|
||||
messageCache.putMessageInCache(event.getMessage());
|
||||
MessageReceivedModel model = getModel(event);
|
||||
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, messageReceivedExecutor));
|
||||
});
|
||||
}
|
||||
|
||||
private MessageReceivedModel getModel(MessageReceivedEvent event) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.CacheEntityService;
|
||||
@@ -54,7 +55,7 @@ public class AsyncPrivateMessageReceivedListenerBean extends ListenerAdapter {
|
||||
cacheEntityService.buildCachedMessageFromMessage(event.getMessage()).thenAccept(cachedMessage ->
|
||||
privateMessageReceivedListeners.forEach(messageReceivedListener -> CompletableFuture.runAsync(() ->
|
||||
self.executeIndividualPrivateMessageReceivedListener(cachedMessage, messageReceivedListener, event)
|
||||
, privateMessageReceivedExecutor)
|
||||
, MetricUtils.wrapExecutor(privateMessageReceivedExecutor))
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Async private message receiver listener {} failed.", messageReceivedListener, throwable);
|
||||
return null;
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package dev.sheldan.abstracto.core.listener.sync.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.MessageCache;
|
||||
import dev.sheldan.abstracto.core.utils.BeanUtils;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.annotation.Observed;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
@@ -25,6 +24,7 @@ import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@Observed
|
||||
public class MessageReceivedListenerBean extends ListenerAdapter {
|
||||
|
||||
@Autowired
|
||||
@@ -33,24 +33,15 @@ public class MessageReceivedListenerBean extends ListenerAdapter {
|
||||
@Autowired(required = false)
|
||||
private List<MessageReceivedListener> listenerList;
|
||||
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private ExceptionService exceptionService;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
@Autowired
|
||||
private ObservationRegistry observationRegistry;
|
||||
|
||||
public static final String MESSAGE_METRIC = "message";
|
||||
public static final String ACTION = "action";
|
||||
private static final CounterMetric MESSAGE_RECEIVED_COUNTER = CounterMetric
|
||||
@@ -63,12 +54,14 @@ public class MessageReceivedListenerBean extends ListenerAdapter {
|
||||
@Transactional
|
||||
public void onMessageReceived(@Nonnull MessageReceivedEvent event) {
|
||||
if(!event.isFromGuild()) return;
|
||||
metricService.incrementCounter(MESSAGE_RECEIVED_COUNTER);
|
||||
messageCache.putMessageInCache(event.getMessage());
|
||||
if(listenerList == null) return;
|
||||
MessageReceivedModel model = getModel(event);
|
||||
listenerList.forEach(messageReceivedListener -> listenerService.executeFeatureAwareListener(messageReceivedListener, model));
|
||||
|
||||
Observation observation = Observation.createNotStarted("message-received", this.observationRegistry);
|
||||
observation.observe(() -> {
|
||||
metricService.incrementCounter(MESSAGE_RECEIVED_COUNTER);
|
||||
messageCache.putMessageInCache(event.getMessage());
|
||||
if (listenerList == null) return;
|
||||
MessageReceivedModel model = getModel(event);
|
||||
listenerList.forEach(messageReceivedListener -> listenerService.executeFeatureAwareListener(messageReceivedListener, model));
|
||||
});
|
||||
}
|
||||
|
||||
private MessageReceivedModel getModel(MessageReceivedEvent event) {
|
||||
|
||||
@@ -3,6 +3,10 @@ package dev.sheldan.abstracto.core.service;
|
||||
import dev.sheldan.abstracto.core.logging.OkHttpLogger;
|
||||
import dev.sheldan.abstracto.core.metric.OkHttpMetrics;
|
||||
import dev.sheldan.abstracto.core.models.SystemInfo;
|
||||
import io.micrometer.context.ContextExecutorService;
|
||||
import io.micrometer.context.ContextSnapshotFactory;
|
||||
import io.micrometer.core.instrument.binder.okhttp3.OkHttpObservationInterceptor;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
@@ -11,9 +15,13 @@ import net.dv8tion.jda.api.utils.ChunkingFilter;
|
||||
import net.dv8tion.jda.api.utils.MemberCachePolicy;
|
||||
import net.dv8tion.jda.api.utils.cache.CacheFlag;
|
||||
import net.dv8tion.jda.internal.utils.IOUtil;
|
||||
import okhttp3.Dispatcher;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.internal.Util;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
@@ -24,6 +32,9 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@@ -46,6 +57,18 @@ public class BotServiceBean implements BotService {
|
||||
@Value("${abstracto.memberCachePolicy:ALL}")
|
||||
private String memberCachePolicy;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("genericExecutor")
|
||||
private TaskExecutor genericExecutor;
|
||||
|
||||
@Autowired
|
||||
private ObservationRegistry observationRegistry;
|
||||
|
||||
private OkHttpObservationInterceptor.Builder defaultInterceptorBuilder() {
|
||||
return OkHttpObservationInterceptor.builder(observationRegistry, "okhttp.requests")
|
||||
.uriMapper(req -> req.url().encodedPath());
|
||||
}
|
||||
|
||||
private static final Map<String, MemberCachePolicy> POSSIBLE_MEMBER_CACHE_POLICIES = new HashMap<>();
|
||||
|
||||
static {
|
||||
@@ -84,6 +107,10 @@ public class BotServiceBean implements BotService {
|
||||
OkHttpClient.Builder defaultBuilder = IOUtil.newHttpClientBuilder();
|
||||
defaultBuilder.addInterceptor(okHttpMetrics);
|
||||
defaultBuilder.addInterceptor(okHttpLogger);
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
|
||||
defaultBuilder.dispatcher(new Dispatcher(ContextExecutorService.wrap(executor, ContextSnapshotFactory.builder().build()::captureAll)));
|
||||
defaultBuilder.addInterceptor(defaultInterceptorBuilder().build());
|
||||
builder.setHttpClientBuilder(defaultBuilder);
|
||||
|
||||
this.instance = builder.build();
|
||||
|
||||
@@ -14,6 +14,8 @@ import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
@@ -35,6 +37,7 @@ import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -77,6 +80,9 @@ public class ChannelServiceBean implements ChannelService {
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
public static final CounterMetric CHANNEL_CREATE_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
@@ -209,6 +215,9 @@ public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> sendMessageToSendToChannel(MessageToSend messageToSend, MessageChannel textChannel) {
|
||||
Span newSpan = tracer.nextSpan().name("send-message");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
newSpan.tag("channel.id", textChannel.getIdLong());
|
||||
messageToSend.setEphemeral(false);
|
||||
if(textChannel instanceof GuildMessageChannel guildMessageChannel) {
|
||||
long maxFileSize = guildMessageChannel.getGuild().getMaxFileSize();
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.listener.*;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
@@ -84,7 +85,7 @@ public class ListenerServiceBean implements ListenerService {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
CompletableFuture.runAsync(() -> self.executeFeatureListenerInTransaction(listener, model), executor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeFeatureListenerInTransaction(listener, model), MetricUtils.wrapExecutor(executor)).exceptionally(throwable -> {
|
||||
log.error("Feature aware async Listener {} failed with async exception:", listener.getClass().getName(), throwable);
|
||||
return null;
|
||||
});
|
||||
@@ -111,7 +112,7 @@ public class ListenerServiceBean implements ListenerService {
|
||||
@Override
|
||||
public <T extends ListenerModel, R extends ListenerExecutionResult> void executeListener(AbstractoListener<T, R> listener, T model, TaskExecutor executor) {
|
||||
try {
|
||||
CompletableFuture.runAsync(() -> self.executeListenerInTransaction(listener, model), executor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeListenerInTransaction(listener, model), MetricUtils.wrapExecutor(executor)).exceptionally(throwable -> {
|
||||
log.error("Async Listener {} failed with async exception:", listener.getClass().getName(), throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.model.database.ACommand;
|
||||
import dev.sheldan.abstracto.core.command.service.management.CommandInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.command.service.management.CommandManagementService;
|
||||
import dev.sheldan.abstracto.core.listener.AsyncStartupListener;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelType;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
@@ -21,6 +22,8 @@ import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.apache.commons.collections4.SetUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -65,6 +68,10 @@ public class StartupServiceBean implements Startup {
|
||||
@Autowired
|
||||
private ProfanityService profanityService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("genericExecutor")
|
||||
private TaskExecutor genericExecutor;
|
||||
|
||||
@Override
|
||||
public void startBot() throws LoginException {
|
||||
service.login();
|
||||
@@ -95,7 +102,7 @@ public class StartupServiceBean implements Startup {
|
||||
} catch (Exception e) {
|
||||
log.error("Startup listener {} failed.", asyncStartupListener, e);
|
||||
}
|
||||
}).thenAccept(unused -> log.info("Startup listener {} finished.", asyncStartupListener))
|
||||
}, MetricUtils.wrapExecutor(genericExecutor)).thenAccept(unused -> log.info("Startup listener {} finished.", asyncStartupListener))
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Startup listener {} failed.", asyncStartupListener, throwable);
|
||||
return null;
|
||||
|
||||
@@ -2,9 +2,10 @@ package dev.sheldan.abstracto.core.templating.loading;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.ServerContext;
|
||||
import dev.sheldan.abstracto.core.templating.model.EffectiveTemplate;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.management.EffectiveTemplateManagementService;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -26,6 +27,9 @@ public class DatabaseTemplateLoader implements TemplateLoader {
|
||||
@Autowired
|
||||
private ServerContext serverContext;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
/**
|
||||
* Loads the content of the template object
|
||||
* @param s The key of the template to load
|
||||
@@ -34,6 +38,9 @@ public class DatabaseTemplateLoader implements TemplateLoader {
|
||||
@Override
|
||||
public Object findTemplateSource(String s) throws IOException {
|
||||
Optional<EffectiveTemplate> templateByKey;
|
||||
Span newSpan = tracer.nextSpan().name("load-template");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
newSpan.tag("template.key", s);
|
||||
if(s.contains("/")) {
|
||||
String[] parts = s.split("/");
|
||||
templateByKey = effectiveTemplateManagementService.getTemplateByKeyAndServer(parts[1], Long.parseLong(parts[0]));
|
||||
@@ -41,6 +48,9 @@ public class DatabaseTemplateLoader implements TemplateLoader {
|
||||
templateByKey = effectiveTemplateManagementService.getTemplateByKey(s);
|
||||
}
|
||||
return templateByKey.orElse(null);
|
||||
} finally {
|
||||
newSpan.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,6 +32,8 @@ import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -97,6 +99,10 @@ public class TemplateServiceBean implements TemplateService {
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
|
||||
/**
|
||||
* Formats the passed count with the embed used for formatting pages.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user