Add a utility method to get OS, OS version, and libsignal version tags from UA additional specifiers

This commit is contained in:
Jon Chambers
2026-02-17 17:51:45 -05:00
committed by Jon Chambers
parent 5ffcdb1c3f
commit 24029ef00c
2 changed files with 59 additions and 5 deletions

View File

@@ -6,11 +6,15 @@
package org.whispersystems.textsecuregcm.metrics;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.core.HttpHeaders;
import java.util.Optional;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.whispersystems.textsecuregcm.WhisperServerVersion;
import org.whispersystems.textsecuregcm.storage.ClientReleaseManager;
import org.whispersystems.textsecuregcm.util.ua.UnrecognizedUserAgentException;
@@ -24,10 +28,16 @@ public class UserAgentTagUtil {
public static final String PLATFORM_TAG = "platform";
public static final String VERSION_TAG = "clientVersion";
public static final String OPERATING_SYSTEM_TAG = "operatingSystem";
public static final String OPERATING_SYSTEM_VERSION_TAG = "operatingSystemVersion";
public static final String LIBSIGNAL_VERSION_TAG = "libsignalVersion";
public static final String SERVER_UA =
String.format("Signal-Server/%s (%s)", WhisperServerVersion.getServerVersion(), UUID.randomUUID());
private static final Pattern STANDARD_ADDITIONAL_SPECIFIERS_PATTERN =
Pattern.compile("^(Windows|macOS|Linux) (\\S+) libsignal/([\\d.]+).*$", Pattern.CASE_INSENSITIVE);
private UserAgentTagUtil() {
}
@@ -76,4 +86,30 @@ public class UserAgentTagUtil {
? Optional.of(Tag.of(VERSION_TAG, userAgent.version().toString()))
: Optional.empty();
}
public static Tags getAdditionalSpecifierTags(@Nullable final String userAgentString) {
UserAgent userAgent = null;
try {
userAgent = UserAgentUtil.parseUserAgentString(userAgentString);
} catch (final UnrecognizedUserAgentException ignored) {
}
return getAdditionalSpecifierTags(userAgent);
}
public static Tags getAdditionalSpecifierTags(@Nullable final UserAgent userAgent) {
if (userAgent == null || StringUtils.isBlank(userAgent.additionalSpecifiers())) {
return Tags.empty();
}
final Matcher matcher = STANDARD_ADDITIONAL_SPECIFIERS_PATTERN.matcher(userAgent.additionalSpecifiers());
return matcher.matches()
? Tags.of(
OPERATING_SYSTEM_TAG, matcher.group(1),
OPERATING_SYSTEM_VERSION_TAG, matcher.group(2),
LIBSIGNAL_VERSION_TAG, matcher.group(3))
: Tags.empty();
}
}