Measure the rate of new WebSocket connections by authentication type

This commit is contained in:
Jon Chambers
2025-07-17 11:35:15 -04:00
committed by GitHub
parent 4ccd39fd55
commit 631b9a5290
3 changed files with 33 additions and 26 deletions

View File

@@ -18,26 +18,35 @@ public class OpenWebSocketCounter {
private static final String WEBSOCKET_CLOSED_COUNTER_NAME = name(OpenWebSocketCounter.class, "websocketClosed");
private final String newConnectionCounterName;
private final String durationTimerName;
private final Tags tags;
private final Map<ClientPlatform, AtomicInteger> openWebsocketsByClientPlatform;
private final AtomicInteger openWebsocketsFromUnknownPlatforms;
private final Map<ClientPlatform, Timer> durationTimersByClientPlatform;
private final Timer durationTimerForUnknownPlatforms;
public OpenWebSocketCounter(final String openWebSocketGaugeName,
final String newConnectionCounterName,
final String durationTimerName) {
public OpenWebSocketCounter(final String openWebSocketGaugeName, final String durationTimerName) {
this(openWebSocketGaugeName, durationTimerName, Tags.empty());
this(openWebSocketGaugeName, durationTimerName, newConnectionCounterName, Tags.empty());
}
public OpenWebSocketCounter(final String openWebSocketGaugeName, final String durationTimerName, final Tags tags) {
public OpenWebSocketCounter(final String openWebSocketGaugeName,
final String newConnectionCounterName,
final String durationTimerName,
final Tags tags) {
this.newConnectionCounterName = newConnectionCounterName;
this.durationTimerName = durationTimerName;
this.tags = tags;
openWebsocketsByClientPlatform = EnumMapUtil.toEnumMap(ClientPlatform.class,
clientPlatform -> buildGauge(openWebSocketGaugeName, clientPlatform.name().toLowerCase(), tags));
openWebsocketsFromUnknownPlatforms = buildGauge(openWebSocketGaugeName, "unknown", tags);
durationTimersByClientPlatform = EnumMapUtil.toEnumMap(ClientPlatform.class,
clientPlatform -> buildTimer(durationTimerName, clientPlatform.name().toLowerCase(), tags));
durationTimerForUnknownPlatforms = buildTimer(durationTimerName, "unknown", tags);
}
private static AtomicInteger buildGauge(final String gaugeName, final String clientPlatformName, final Tags tags) {
@@ -46,47 +55,43 @@ public class OpenWebSocketCounter {
new AtomicInteger(0));
}
private static Timer buildTimer(final String timerName, final String clientPlatformName, final Tags tags) {
return Timer.builder(timerName)
.publishPercentileHistogram(true)
.tags(tags.and(Tag.of(UserAgentTagUtil.PLATFORM_TAG, clientPlatformName)))
.register(Metrics.globalRegistry);
}
public void countOpenWebSocket(final WebSocketSessionContext context) {
final Timer.Sample sample = Timer.start();
// We have to jump through some hoops here to have something "effectively final" for the close listener, but
// assignable from a `catch` block.
final AtomicInteger openWebSocketCounter;
final Timer durationTimer;
{
AtomicInteger calculatedOpenWebSocketCounter;
Timer calculatedDurationTimer;
try {
final ClientPlatform clientPlatform =
UserAgentUtil.parseUserAgentString(context.getClient().getUserAgent()).platform();
calculatedOpenWebSocketCounter = openWebsocketsByClientPlatform.get(clientPlatform);
calculatedDurationTimer = durationTimersByClientPlatform.get(clientPlatform);
} catch (final UnrecognizedUserAgentException e) {
calculatedOpenWebSocketCounter = openWebsocketsFromUnknownPlatforms;
calculatedDurationTimer = durationTimerForUnknownPlatforms;
}
openWebSocketCounter = calculatedOpenWebSocketCounter;
durationTimer = calculatedDurationTimer;
}
openWebSocketCounter.incrementAndGet();
final Tags tagsWithClientPlatform = tags.and(UserAgentTagUtil.getPlatformTag(context.getClient().getUserAgent()));
Metrics.counter(newConnectionCounterName, tagsWithClientPlatform).increment();
context.addWebsocketClosedListener((context1, statusCode, reason) -> {
sample.stop(durationTimer);
sample.stop(Timer.builder(durationTimerName)
.publishPercentileHistogram(true)
.tags(tagsWithClientPlatform)
.register(Metrics.globalRegistry));
openWebSocketCounter.decrementAndGet();
Metrics.counter(WEBSOCKET_CLOSED_COUNTER_NAME, "status", String.valueOf(statusCode))
Metrics.counter(WEBSOCKET_CLOSED_COUNTER_NAME, tagsWithClientPlatform.and("status", String.valueOf(statusCode)))
.increment();
});
}