diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsHttpChannelListener.java b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsHttpChannelListener.java index c2526d534..f5bd3cc2f 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsHttpChannelListener.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsHttpChannelListener.java @@ -31,6 +31,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.storage.ClientReleaseManager; import org.whispersystems.textsecuregcm.util.logging.UriInfoUtil; +import org.whispersystems.textsecuregcm.util.ua.UnrecognizedUserAgentException; +import org.whispersystems.textsecuregcm.util.ua.UserAgent; +import org.whispersystems.textsecuregcm.util.ua.UserAgentUtil; /** * Gathers and reports HTTP request metrics at the Jetty container level, which sits above Jersey. In order to get @@ -49,7 +52,6 @@ public class MetricsHttpChannelListener implements HttpChannel.Listener, Contain private static final Logger logger = LoggerFactory.getLogger(MetricsHttpChannelListener.class); private record RequestInfo(String path, String method, int statusCode, @Nullable String userAgent) { - } private final ClientReleaseManager clientReleaseManager; @@ -136,15 +138,30 @@ public class MetricsHttpChannelListener implements HttpChannel.Listener, Contain final RequestInfo requestInfo = getRequestInfo(request); + @Nullable final UserAgent userAgent; + { + UserAgent parsedUserAgent; + + try { + parsedUserAgent = UserAgentUtil.parseUserAgentString(requestInfo.userAgent()); + } catch (final UnrecognizedUserAgentException e) { + parsedUserAgent = null; + } + + userAgent = parsedUserAgent; + } + + final Tag platformTag = UserAgentTagUtil.getPlatformTag(userAgent); + final List tags = new ArrayList<>(5); tags.add(Tag.of(PATH_TAG, requestInfo.path())); tags.add(Tag.of(METHOD_TAG, requestInfo.method())); tags.add(Tag.of(STATUS_CODE_TAG, String.valueOf(requestInfo.statusCode()))); tags.add(Tag.of(TRAFFIC_SOURCE_TAG, TrafficSource.HTTP.name().toLowerCase())); - tags.add(UserAgentTagUtil.getPlatformTag(requestInfo.userAgent())); + tags.add(platformTag); final Optional maybeClientVersionTag = - UserAgentTagUtil.getClientVersionTag(requestInfo.userAgent, clientReleaseManager); + UserAgentTagUtil.getClientVersionTag(userAgent, clientReleaseManager); maybeClientVersionTag.ifPresent(tags::add); @@ -154,7 +171,7 @@ public class MetricsHttpChannelListener implements HttpChannel.Listener, Contain meterRegistry.counter(REQUEST_BYTES_COUNTER_NAME, tags).increment(request.getContentRead()); maybeClientVersionTag.ifPresent(clientVersionTag -> meterRegistry.counter(REQUESTS_BY_VERSION_COUNTER_NAME, - Tags.of(clientVersionTag, UserAgentTagUtil.getPlatformTag(requestInfo.userAgent))) + Tags.of(clientVersionTag, platformTag)) .increment()); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListener.java b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListener.java index ca86af361..7bb7f5731 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListener.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListener.java @@ -24,6 +24,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.storage.ClientReleaseManager; import org.whispersystems.textsecuregcm.util.logging.UriInfoUtil; +import org.whispersystems.textsecuregcm.util.ua.UnrecognizedUserAgentException; +import org.whispersystems.textsecuregcm.util.ua.UserAgent; +import org.whispersystems.textsecuregcm.util.ua.UserAgentUtil; import org.whispersystems.websocket.WebSocketResourceProvider; /** @@ -84,6 +87,24 @@ public class MetricsRequestEventListener implements RequestEventListener { public void onEvent(final RequestEvent event) { if (event.getType() == RequestEvent.Type.FINISHED) { if (!event.getUriInfo().getMatchedTemplates().isEmpty()) { + @Nullable final UserAgent userAgent; + { + final List userAgentValues = event.getContainerRequest().getRequestHeader(HttpHeaders.USER_AGENT); + final String userAgentString = userAgentValues != null && !userAgentValues.isEmpty() ? userAgentValues.getFirst() : null; + + UserAgent parsedUserAgent; + + try { + parsedUserAgent = UserAgentUtil.parseUserAgentString(userAgentString); + } catch (final UnrecognizedUserAgentException e) { + parsedUserAgent = null; + } + + userAgent = parsedUserAgent; + } + + final Tag platformTag = UserAgentTagUtil.getPlatformTag(userAgent); + final List tags = new ArrayList<>(); tags.add(Tag.of(PATH_TAG, UriInfoUtil.getPathTemplate(event.getUriInfo()))); tags.add(Tag.of(METHOD_TAG, event.getContainerRequest().getMethod())); @@ -98,14 +119,7 @@ public class MetricsRequestEventListener implements RequestEventListener { .map(Optional::isPresent) .orElse(false) .toString())); - - @Nullable final String userAgent; - { - final List userAgentValues = event.getContainerRequest().getRequestHeader(HttpHeaders.USER_AGENT); - userAgent = userAgentValues != null && !userAgentValues.isEmpty() ? userAgentValues.getFirst() : null; - } - - tags.add(UserAgentTagUtil.getPlatformTag(userAgent)); + tags.add(platformTag); final Optional maybeClientVersionTag = UserAgentTagUtil.getClientVersionTag(userAgent, clientReleaseManager); @@ -132,7 +146,7 @@ public class MetricsRequestEventListener implements RequestEventListener { .ifPresent(bytes -> meterRegistry.counter(RESPONSE_BYTES_COUNTER_NAME, tags).increment(bytes)); maybeClientVersionTag.ifPresent(clientVersionTag -> meterRegistry.counter(REQUESTS_BY_VERSION_COUNTER_NAME, - Tags.of(clientVersionTag, UserAgentTagUtil.getPlatformTag(userAgent))) + Tags.of(clientVersionTag, platformTag)) .increment()); } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/UserAgentTagUtil.java b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/UserAgentTagUtil.java index c44124f92..aedc9cba7 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/UserAgentTagUtil.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/UserAgentTagUtil.java @@ -35,7 +35,7 @@ public class UserAgentTagUtil { return getPlatformTag(containerRequestContext.getHeaderString(HttpHeaders.USER_AGENT)); } - public static Tag getPlatformTag(final String userAgentString) { + public static Tag getPlatformTag(@Nullable final String userAgentString) { if (SERVER_UA.equals(userAgentString)) { return Tag.of(PLATFORM_TAG, "server"); @@ -55,16 +55,25 @@ public class UserAgentTagUtil { return Tag.of(PLATFORM_TAG, userAgent != null ? userAgent.platform().name().toLowerCase() : "unrecognized"); } - public static Optional getClientVersionTag(final String userAgentString, final ClientReleaseManager clientReleaseManager) { - try { - final UserAgent userAgent = UserAgentUtil.parseUserAgentString(userAgentString); + public static Optional getClientVersionTag(@Nullable final String userAgentString, + final ClientReleaseManager clientReleaseManager) { - if (clientReleaseManager.isVersionActive(userAgent.platform(), userAgent.version())) { - return Optional.of(Tag.of(VERSION_TAG, userAgent.version().toString())); - } - } catch (final UnrecognizedUserAgentException ignored) { + try { + return getClientVersionTag(UserAgentUtil.parseUserAgentString(userAgentString), clientReleaseManager); + } catch (final UnrecognizedUserAgentException e) { + return Optional.empty(); + } + } + + public static Optional getClientVersionTag(@Nullable final UserAgent userAgent, + final ClientReleaseManager clientReleaseManager) { + + if (userAgent == null) { + return Optional.empty(); } - return Optional.empty(); + return clientReleaseManager.isVersionActive(userAgent.platform(), userAgent.version()) + ? Optional.of(Tag.of(VERSION_TAG, userAgent.version().toString())) + : Optional.empty(); } }