mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-19 16:58:04 +01:00
Measure the rate of new WebSocket connections by authentication type
This commit is contained in:
@@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import reactor.core.scheduler.Scheduler;
|
||||
public class AuthenticatedConnectListener implements WebSocketConnectListener {
|
||||
|
||||
private static final String OPEN_WEBSOCKET_GAUGE_NAME = name(WebSocketConnection.class, "openWebsockets");
|
||||
private static final String NEW_CONNECTION_COUNTER_NAME = name(AuthenticatedConnectListener.class, "newConnections");
|
||||
private static final String CONNECTED_DURATION_TIMER_NAME =
|
||||
name(AuthenticatedConnectListener.class, "connectedDuration");
|
||||
|
||||
@@ -84,10 +85,10 @@ public class AuthenticatedConnectListener implements WebSocketConnectListener {
|
||||
this.experimentEnrollmentManager = experimentEnrollmentManager;
|
||||
|
||||
openAuthenticatedWebSocketCounter =
|
||||
new OpenWebSocketCounter(OPEN_WEBSOCKET_GAUGE_NAME, CONNECTED_DURATION_TIMER_NAME, Tags.of(AUTHENTICATED_TAG_NAME, "true"));
|
||||
new OpenWebSocketCounter(OPEN_WEBSOCKET_GAUGE_NAME, NEW_CONNECTION_COUNTER_NAME, CONNECTED_DURATION_TIMER_NAME, Tags.of(AUTHENTICATED_TAG_NAME, "true"));
|
||||
|
||||
openUnauthenticatedWebSocketCounter =
|
||||
new OpenWebSocketCounter(OPEN_WEBSOCKET_GAUGE_NAME, CONNECTED_DURATION_TIMER_NAME, Tags.of(AUTHENTICATED_TAG_NAME, "false"));
|
||||
new OpenWebSocketCounter(OPEN_WEBSOCKET_GAUGE_NAME, NEW_CONNECTION_COUNTER_NAME, CONNECTED_DURATION_TIMER_NAME, Tags.of(AUTHENTICATED_TAG_NAME, "false"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -54,6 +54,7 @@ public class ProvisioningConnectListener implements WebSocketConnectListener {
|
||||
this.timeoutExecutor = timeoutExecutor;
|
||||
this.timeout = timeout;
|
||||
this.openWebSocketCounter = new OpenWebSocketCounter(MetricsUtil.name(getClass(), "openWebsockets"),
|
||||
MetricsUtil.name(getClass(), "newConnections"),
|
||||
MetricsUtil.name(getClass(), "sessionDuration"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user