diff --git a/src/main/java/xyz/mcutils/backend/config/WebSocketConfig.java b/src/main/java/xyz/mcutils/backend/config/WebSocketConfig.java deleted file mode 100644 index ee4c3c1..0000000 --- a/src/main/java/xyz/mcutils/backend/config/WebSocketConfig.java +++ /dev/null @@ -1,22 +0,0 @@ -package xyz.mcutils.backend.config; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.socket.config.annotation.EnableWebSocket; -import org.springframework.web.socket.config.annotation.WebSocketConfigurer; -import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; -import xyz.mcutils.backend.service.MetricService; -import xyz.mcutils.backend.websocket.MetricsWebSocketHandler; - -@Configuration -@EnableWebSocket -public class WebSocketConfig implements WebSocketConfigurer { - - @Autowired - private MetricService metricService; - - @Override - public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(new MetricsWebSocketHandler(metricService), "/websocket/metrics").setAllowedOrigins("*"); - } -} diff --git a/src/main/java/xyz/mcutils/backend/service/ServerService.java b/src/main/java/xyz/mcutils/backend/service/ServerService.java index 270938b..a18b861 100644 --- a/src/main/java/xyz/mcutils/backend/service/ServerService.java +++ b/src/main/java/xyz/mcutils/backend/service/ServerService.java @@ -3,9 +3,9 @@ package xyz.mcutils.backend.service; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import xyz.mcutils.backend.common.AppConfig; import xyz.mcutils.backend.common.DNSUtils; import xyz.mcutils.backend.common.EnumUtils; -import xyz.mcutils.backend.common.AppConfig; import xyz.mcutils.backend.exception.impl.BadRequestException; import xyz.mcutils.backend.exception.impl.ResourceNotFoundException; import xyz.mcutils.backend.model.cache.CachedMinecraftServer; diff --git a/src/main/java/xyz/mcutils/backend/service/metric/metrics/ConnectedSocketsMetric.java b/src/main/java/xyz/mcutils/backend/service/metric/metrics/ConnectedSocketsMetric.java index 59ed4e0..3d67f6f 100644 --- a/src/main/java/xyz/mcutils/backend/service/metric/metrics/ConnectedSocketsMetric.java +++ b/src/main/java/xyz/mcutils/backend/service/metric/metrics/ConnectedSocketsMetric.java @@ -1,7 +1,7 @@ package xyz.mcutils.backend.service.metric.metrics; import xyz.mcutils.backend.service.metric.impl.IntegerMetric; -import xyz.mcutils.backend.websocket.MetricsWebSocketHandler; +import xyz.mcutils.backend.websocket.WebSocketManager; public class ConnectedSocketsMetric extends IntegerMetric { @@ -16,6 +16,6 @@ public class ConnectedSocketsMetric extends IntegerMetric { @Override public void collect() { - setValue(MetricsWebSocketHandler.SESSIONS.size()); + setValue(WebSocketManager.getTotalConnections()); } } diff --git a/src/main/java/xyz/mcutils/backend/service/pinger/impl/BedrockMinecraftServerPinger.java b/src/main/java/xyz/mcutils/backend/service/pinger/impl/BedrockMinecraftServerPinger.java index 38641fe..545fc72 100644 --- a/src/main/java/xyz/mcutils/backend/service/pinger/impl/BedrockMinecraftServerPinger.java +++ b/src/main/java/xyz/mcutils/backend/service/pinger/impl/BedrockMinecraftServerPinger.java @@ -10,7 +10,10 @@ import xyz.mcutils.backend.model.server.BedrockMinecraftServer; import xyz.mcutils.backend.service.pinger.MinecraftServerPinger; import java.io.IOException; -import java.net.*; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; /** * The {@link MinecraftServerPinger} for pinging diff --git a/src/main/java/xyz/mcutils/backend/service/pinger/impl/JavaMinecraftServerPinger.java b/src/main/java/xyz/mcutils/backend/service/pinger/impl/JavaMinecraftServerPinger.java index f456e13..5ef49c3 100644 --- a/src/main/java/xyz/mcutils/backend/service/pinger/impl/JavaMinecraftServerPinger.java +++ b/src/main/java/xyz/mcutils/backend/service/pinger/impl/JavaMinecraftServerPinger.java @@ -3,7 +3,6 @@ package xyz.mcutils.backend.service.pinger.impl; import lombok.extern.log4j.Log4j2; import xyz.mcutils.backend.Main; import xyz.mcutils.backend.common.JavaMinecraftVersion; -import xyz.mcutils.backend.common.ServerUtils; import xyz.mcutils.backend.common.packet.impl.java.JavaPacketHandshakingInSetProtocol; import xyz.mcutils.backend.common.packet.impl.java.JavaPacketStatusInStart; import xyz.mcutils.backend.exception.impl.BadRequestException; diff --git a/src/main/java/xyz/mcutils/backend/websocket/WebSocket.java b/src/main/java/xyz/mcutils/backend/websocket/WebSocket.java new file mode 100644 index 0000000..5fd6374 --- /dev/null +++ b/src/main/java/xyz/mcutils/backend/websocket/WebSocket.java @@ -0,0 +1,54 @@ +package xyz.mcutils.backend.websocket; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.jetbrains.annotations.NotNull; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@RequiredArgsConstructor @Getter @Log4j2(topic = "WebSocket") +public abstract class WebSocket extends TextWebSocketHandler { + + /** + * The sessions that are connected to the WebSocket. + */ + private final List sessions = new ArrayList<>(); + + /** + * The path of the WebSocket. + *

+ * Example: /websocket/metrics + *

+ */ + public final String path; + + /** + * Sends a message to the client. + * + * @param session the session to send the message to + * @param message the message to send + * @throws IOException if an error occurs while sending the message + */ + public void sendMessage(WebSocketSession session, String message) throws IOException { + session.sendMessage(new TextMessage(message)); + } + + @Override + public void afterConnectionEstablished(@NotNull WebSocketSession session) throws Exception { + this.sessions.add(session); + log.info("Connection established: {}", session.getId()); + } + + @Override + public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus status) throws Exception { + this.sessions.remove(session); + log.info("Connection closed: {}", session.getId()); + } +} diff --git a/src/main/java/xyz/mcutils/backend/websocket/WebSocketManager.java b/src/main/java/xyz/mcutils/backend/websocket/WebSocketManager.java new file mode 100644 index 0000000..c678c5a --- /dev/null +++ b/src/main/java/xyz/mcutils/backend/websocket/WebSocketManager.java @@ -0,0 +1,51 @@ +package xyz.mcutils.backend.websocket; + +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; +import xyz.mcutils.backend.service.MetricService; +import xyz.mcutils.backend.websocket.impl.MetricsWebSocket; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +@EnableWebSocket +public class WebSocketManager implements WebSocketConfigurer { + private static final List WEB_SOCKETS = new ArrayList<>(); + + private final MetricService metricService; + + @Autowired + public WebSocketManager(MetricService metricService) { + this.metricService = metricService; + } + + @Override + public void registerWebSocketHandlers(@NotNull WebSocketHandlerRegistry registry) { + registerWebSocket(registry, new MetricsWebSocket(metricService)); + } + + /** + * Registers a WebSocket. + * + * @param registry the registry to register the WebSocket on + * @param webSocket the WebSocket to register + */ + private void registerWebSocket(WebSocketHandlerRegistry registry, WebSocket webSocket) { + registry.addHandler(webSocket, webSocket.getPath()).setAllowedOrigins("*"); + WEB_SOCKETS.add(webSocket); + } + + /** + * Gets the total amount of connections. + * + * @return the total amount of connections + */ + public static int getTotalConnections() { + return WEB_SOCKETS.stream().mapToInt(webSocket -> webSocket.getSessions().size()).sum(); + } +} diff --git a/src/main/java/xyz/mcutils/backend/websocket/MetricsWebSocketHandler.java b/src/main/java/xyz/mcutils/backend/websocket/impl/MetricsWebSocket.java similarity index 61% rename from src/main/java/xyz/mcutils/backend/websocket/MetricsWebSocketHandler.java rename to src/main/java/xyz/mcutils/backend/websocket/impl/MetricsWebSocket.java index aa4b6c2..b4929af 100644 --- a/src/main/java/xyz/mcutils/backend/websocket/MetricsWebSocketHandler.java +++ b/src/main/java/xyz/mcutils/backend/websocket/impl/MetricsWebSocket.java @@ -1,34 +1,30 @@ -package xyz.mcutils.backend.websocket; +package xyz.mcutils.backend.websocket.impl; import lombok.extern.log4j.Log4j2; -import org.jetbrains.annotations.NotNull; -import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; -import org.springframework.web.socket.handler.TextWebSocketHandler; import xyz.mcutils.backend.Main; import xyz.mcutils.backend.common.Timer; import xyz.mcutils.backend.service.MetricService; import xyz.mcutils.backend.service.metric.metrics.TotalRequestsMetric; import xyz.mcutils.backend.service.metric.metrics.UniquePlayerLookupsMetric; import xyz.mcutils.backend.service.metric.metrics.UniqueServerLookupsMetric; +import xyz.mcutils.backend.websocket.WebSocket; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @Log4j2(topic = "WebSocket/Metrics") -public class MetricsWebSocketHandler extends TextWebSocketHandler { +public class MetricsWebSocket extends WebSocket { private final long interval = TimeUnit.SECONDS.toMillis(5); - public static final List SESSIONS = new ArrayList<>(); - private final MetricService metricService; - public MetricsWebSocketHandler(MetricService metricService) { + public MetricsWebSocket(MetricService metricService) { + super("/websocket/metrics"); this.metricService = metricService; + Timer.scheduleRepeating(() -> { - for (WebSocketSession session : SESSIONS) { + for (WebSocketSession session : this.getSessions()) { sendMetrics(session); } }, interval, interval); @@ -50,19 +46,4 @@ public class MetricsWebSocketHandler extends TextWebSocketHandler { log.error("An error occurred while sending metrics to the client", e); } } - - @Override - public void afterConnectionEstablished(WebSocketSession session) { - log.info("WebSocket connection established with session id: {}", session.getId()); - - sendMetrics(session); - SESSIONS.add(session); - } - - @Override - public void afterConnectionClosed(WebSocketSession session, @NotNull CloseStatus status) { - log.info("WebSocket connection closed with session id: {}", session.getId()); - - SESSIONS.remove(session); - } } \ No newline at end of file