diff --git a/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java b/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java index 166f3514..e36589b5 100644 --- a/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java +++ b/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java @@ -8,7 +8,6 @@ import java.net.URI; import java.net.http.HttpRequest; import java.time.Instant; -import java.util.HashMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; @@ -88,7 +87,6 @@ public CompletableFuture getAccessToken() throws FgaInvalidParameterExce snapshot.set(new AccessToken(token, Instant.now().plusSeconds(response.getExpiresInSeconds()))); inFlight.set(null); promise.complete(token); - telemetry.metrics().credentialsRequest(1L, new HashMap<>()); } }); } catch (Exception e) { @@ -112,10 +110,14 @@ private CompletableFuture exchangeToken() ApiClient.formRequestBuilder("POST", "", this.authRequest.buildFormRequestBody(), config); HttpRequest request = requestBuilder.build(); - return new HttpRequestAttempt<>( - request, "exchangeToken", CredentialsFlowResponse.class, apiClient, config, telemetry) - .attemptHttpRequest() - .thenApply(ApiResponse::getData); + HttpRequestAttempt attempt = new HttpRequestAttempt<>( + request, "exchangeToken", CredentialsFlowResponse.class, apiClient, config, telemetry); + + return attempt.attemptHttpRequest().thenApply(response -> { + // Record the token request with the attributes of its HTTP request, e.g. the host and status code + telemetry.metrics().credentialsRequest(1L, attempt.getTelemetryAttributes()); + return response.getData(); + }); } private static String buildApiTokenIssuer(String issuer) throws FgaInvalidParameterException { diff --git a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java index bfc54aa7..fa766990 100644 --- a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java +++ b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java @@ -5,6 +5,8 @@ import static org.hamcrest.core.StringContains.containsString; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.mockingDetails; import static org.mockito.Mockito.when; import com.github.tomakehurst.wiremock.junit5.*; @@ -15,19 +17,26 @@ import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.constants.FgaConstants; import dev.openfga.sdk.errors.FgaInvalidParameterException; +import dev.openfga.sdk.telemetry.Attribute; +import dev.openfga.sdk.telemetry.Attributes; +import dev.openfga.sdk.telemetry.Metrics; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.MockedConstruction; +import org.mockito.invocation.Invocation; @WireMockTest class OAuth2ClientTest { @@ -368,6 +377,32 @@ public void apiTokenIssuers_invalidURI(String invalidApiTokenIssuer) { assertInstanceOf(IllegalArgumentException.class, exception.getCause()); } + @Test + public void credentialsRequestMetricHasTheTokenRequestAttributes() throws Exception { + try (MockedConstruction metrics = mockConstruction(Metrics.class)) { + // Given + OAuth2Client auth0 = newAuth0Client("https://issuer.fga.example"); + mockHttpClient + .onPost("https://issuer.fga.example/oauth/token") + .doReturn(200, String.format("{\"access_token\":\"%s\"}", ACCESS_TOKEN)); + + // When + auth0.getAccessToken().get(); + + // Then + List credentialsRequests = metrics.constructed().stream() + .flatMap(m -> mockingDetails(m).getInvocations().stream()) + .filter(invocation -> invocation.getMethod().getName().equals("credentialsRequest")) + .collect(Collectors.toList()); + assertEquals(1, credentialsRequests.size()); + + Map attributes = credentialsRequests.get(0).getArgument(1); + assertEquals("issuer.fga.example", attributes.get(Attributes.HTTP_HOST)); + assertEquals("200", attributes.get(Attributes.HTTP_RESPONSE_STATUS_CODE)); + assertEquals("POST", attributes.get(Attributes.HTTP_REQUEST_METHOD)); + } + } + private OAuth2Client newAuth0Client(String apiTokenIssuer) throws FgaInvalidParameterException { return newClientCredentialsClient( apiTokenIssuer,