From a7684982503ace53def47f96c53f71e0ddacfbb8 Mon Sep 17 00:00:00 2001 From: Jon Chambers Date: Wed, 21 Jun 2023 12:26:35 -0400 Subject: [PATCH] Record general message delivery latency --- .../controllers/MessageController.java | 19 +++++-------------- .../textsecuregcm/metrics/MessageMetrics.java | 12 ++++++++++++ .../websocket/WebSocketConnection.java | 2 ++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java index 3a4362a94..f73c1a446 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java @@ -100,8 +100,6 @@ import org.whispersystems.textsecuregcm.storage.ReportMessageManager; import org.whispersystems.textsecuregcm.util.DestinationDeviceValidator; import org.whispersystems.textsecuregcm.util.Pair; import org.whispersystems.textsecuregcm.util.Util; -import org.whispersystems.textsecuregcm.util.ua.UnrecognizedUserAgentException; -import org.whispersystems.textsecuregcm.util.ua.UserAgentUtil; import org.whispersystems.textsecuregcm.websocket.WebSocketConnection; import org.whispersystems.websocket.Stories; import reactor.core.scheduler.Scheduler; @@ -536,21 +534,14 @@ public class MessageController { final OutgoingMessageEntityList messages = new OutgoingMessageEntityList(envelopes .map(OutgoingMessageEntity::fromEnvelope) - .peek( - outgoingMessageEntity -> MessageMetrics.measureAccountOutgoingMessageUuidMismatches(auth.getAccount(), - outgoingMessageEntity)) + .peek(outgoingMessageEntity -> { + MessageMetrics.measureAccountOutgoingMessageUuidMismatches(auth.getAccount(), outgoingMessageEntity); + MessageMetrics.measureOutgoingMessageLatency(outgoingMessageEntity.serverTimestamp(), "rest", userAgent); + }) .collect(Collectors.toList()), messagesAndHasMore.second()); - String platform; - - try { - platform = UserAgentUtil.parseUserAgentString(userAgent).getPlatform().name().toLowerCase(); - } catch (final UnrecognizedUserAgentException ignored) { - platform = "unrecognized"; - } - - Metrics.summary(OUTGOING_MESSAGE_LIST_SIZE_BYTES_DISTRIBUTION_NAME, "platform", platform) + Metrics.summary(OUTGOING_MESSAGE_LIST_SIZE_BYTES_DISTRIBUTION_NAME, Tags.of(UserAgentTagUtil.getPlatformTag(userAgent))) .record(estimateMessageListSizeBytes(messages)); return messages; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MessageMetrics.java b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MessageMetrics.java index 87cc92d7d..38695b92d 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MessageMetrics.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MessageMetrics.java @@ -8,7 +8,11 @@ package org.whispersystems.textsecuregcm.metrics; import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name; import io.micrometer.core.instrument.Metrics; +import java.time.Duration; +import java.time.Instant; import java.util.UUID; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.entities.MessageProtos; @@ -22,6 +26,8 @@ public final class MessageMetrics { private static final String MISMATCHED_ACCOUNT_ENVELOPE_UUID_COUNTER_NAME = name(MessageMetrics.class, "mismatchedAccountEnvelopeUuid"); + private static final String DELIVERY_LATENCY_TIMER_NAME = name(MessageMetrics.class, "deliveryLatency"); + public static void measureAccountOutgoingMessageUuidMismatches(final Account account, final OutgoingMessageEntity outgoingMessage) { measureAccountDestinationUuidMismatches(account, outgoingMessage.destinationUuid()); @@ -48,4 +54,10 @@ public final class MessageMetrics { } } + public static void measureOutgoingMessageLatency(final long serverTimestamp, final String channel, final String userAgent) { + Metrics.timer(DELIVERY_LATENCY_TIMER_NAME, Tags.of( + UserAgentTagUtil.getPlatformTag(userAgent), + Tag.of("channel", channel))) + .record(Duration.between(Instant.ofEpochMilli(serverTimestamp), Instant.now())); + } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java b/service/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java index 575b3e420..e5a677709 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java @@ -207,6 +207,8 @@ public class WebSocketConnection implements MessageAvailabilityListener, Displac .whenComplete((ignored, throwable) -> { if (throwable != null) { sendFailuresMeter.mark(); + } else { + MessageMetrics.measureOutgoingMessageLatency(message.getServerTimestamp(), "websocket", client.getUserAgent()); } }).thenCompose(response -> { final CompletableFuture result;