add metrics websocket

This commit is contained in:
Lee 2024-04-18 00:25:44 +01:00
parent cbfaa867a9
commit c5758d38e0
7 changed files with 101 additions and 8 deletions

@ -61,6 +61,12 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- Websockets -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- Redis for caching --> <!-- Redis for caching -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

@ -1,6 +1,5 @@
package xyz.mcutils.backend.common; package xyz.mcutils.backend.common;
import com.google.gson.JsonObject;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode; import org.springframework.http.HttpStatusCode;

@ -0,0 +1,22 @@
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("*");
}
}

@ -2,14 +2,16 @@ package xyz.mcutils.backend.model.cache;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.*; import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.RedisHash;
import xyz.mcutils.backend.common.CachedResponse; import xyz.mcutils.backend.common.CachedResponse;
import xyz.mcutils.backend.model.mojang.EndpointStatus; import xyz.mcutils.backend.model.mojang.EndpointStatus;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
@Setter @Getter @ToString @Setter @Getter @ToString
@RedisHash(value = "mojangEndpointStatus", timeToLive = 60L) // 1 minute (in seconds) @RedisHash(value = "mojangEndpointStatus", timeToLive = 60L) // 1 minute (in seconds)

@ -0,0 +1,15 @@
package xyz.mcutils.backend.model.metric;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Map;
@AllArgsConstructor
@Getter
public class WebsocketMetrics {
/**
* The metrics to send to the client.
*/
private final Map<String, Object> metrics;
}

@ -1,12 +1,7 @@
package xyz.mcutils.backend.model.mojang; package xyz.mcutils.backend.model.mojang;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull;
import org.springframework.data.annotation.Id;
import xyz.mcutils.backend.common.CachedResponse;
import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
import java.util.Map; import java.util.Map;

@ -0,0 +1,54 @@
package xyz.mcutils.backend.websocket;
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.model.metric.WebsocketMetrics;
import xyz.mcutils.backend.service.MetricService;
import xyz.mcutils.backend.service.metric.metrics.TotalRequestsMetric;
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 {
private final long interval = TimeUnit.SECONDS.toMillis(5);
public final List<WebSocketSession> sessions = new ArrayList<>();
public MetricsWebSocketHandler(MetricService metricService) {
Timer.scheduleRepeating(() -> {
try {
WebsocketMetrics metrics = new WebsocketMetrics(Map.of(
"totalRequests", metricService.getMetric(TotalRequestsMetric.class).getValue())
);
for (WebSocketSession session : sessions) {
session.sendMessage(new TextMessage(Main.GSON.toJson(metrics)));
}
} catch (Exception e) {
log.error("An error occurred while sending metrics to the client", e);
}
}, interval, interval);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) {
log.info("WebSocket connection established with session id: {}", session.getId());
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);
}
}