diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ChallengeController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ChallengeController.java index e0dedfdcd..7a7907ce0 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ChallengeController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ChallengeController.java @@ -15,21 +15,31 @@ import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.entities.AnswerChallengeRequest; import org.whispersystems.textsecuregcm.entities.AnswerPushChallengeRequest; import org.whispersystems.textsecuregcm.entities.AnswerRecaptchaChallengeRequest; import org.whispersystems.textsecuregcm.limits.RateLimitChallengeManager; +import org.whispersystems.textsecuregcm.metrics.UserAgentTagUtil; import org.whispersystems.textsecuregcm.push.NotPushRegisteredException; import org.whispersystems.textsecuregcm.util.ForwardedIpUtil; +import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name; + @Path("/v1/challenge") public class ChallengeController { private final RateLimitChallengeManager rateLimitChallengeManager; + private static final String CHALLENGE_RESPONSE_COUNTER_NAME = name(ChallengeController.class, "challengeResponse"); + private static final String CHALLENGE_TYPE_TAG = "type"; + public ChallengeController(final RateLimitChallengeManager rateLimitChallengeManager) { this.rateLimitChallengeManager = rateLimitChallengeManager; } @@ -40,16 +50,20 @@ public class ChallengeController { @Consumes(MediaType.APPLICATION_JSON) public Response handleChallengeResponse(@Auth final AuthenticatedAccount auth, @Valid final AnswerChallengeRequest answerRequest, - @HeaderParam("X-Forwarded-For") String forwardedFor) throws RetryLaterException { + @HeaderParam("X-Forwarded-For") final String forwardedFor, + @HeaderParam(HttpHeaders.USER_AGENT) final String userAgent) throws RetryLaterException { + + Tags tags = Tags.of(UserAgentTagUtil.getPlatformTag(userAgent)); try { - if (answerRequest instanceof AnswerPushChallengeRequest) { - final AnswerPushChallengeRequest pushChallengeRequest = (AnswerPushChallengeRequest) answerRequest; + if (answerRequest instanceof final AnswerPushChallengeRequest pushChallengeRequest) { + tags = tags.and(CHALLENGE_TYPE_TAG, "push"); rateLimitChallengeManager.answerPushChallenge(auth.getAccount(), pushChallengeRequest.getChallenge()); } else if (answerRequest instanceof AnswerRecaptchaChallengeRequest) { - try { + tags = tags.and(CHALLENGE_TYPE_TAG, "recaptcha"); + try { final AnswerRecaptchaChallengeRequest recaptchaChallengeRequest = (AnswerRecaptchaChallengeRequest) answerRequest; final String mostRecentProxy = ForwardedIpUtil.getMostRecentProxy(forwardedFor).orElseThrow(); @@ -59,9 +73,13 @@ public class ChallengeController { } catch (final NoSuchElementException e) { return Response.status(400).build(); } + } else { + tags = tags.and(CHALLENGE_TYPE_TAG, "unrecognized"); } } catch (final RateLimitExceededException e) { throw new RetryLaterException(e); + } finally { + Metrics.counter(CHALLENGE_RESPONSE_COUNTER_NAME, tags).increment(); } return Response.status(200).build();