From b84d32c8c03b0c6a8240cf792fafdc89e38042c7 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Thu, 26 Mar 2026 21:32:42 +0530 Subject: [PATCH 1/3] feat: add per call http metric --- CHANGELOG.md | 3 ++ .../sdk/api/client/HttpRequestAttempt.java | 1 + .../dev/openfga/sdk/telemetry/Counters.java | 9 ++++++ .../dev/openfga/sdk/telemetry/Metrics.java | 14 ++++++++ .../TelemetryConfigurationTest.java | 30 +++++++++++++++++ .../openfga/sdk/telemetry/CountersTest.java | 14 ++++++++ .../openfga/sdk/telemetry/MetricsTest.java | 32 +++++++++++++++++++ 7 files changed, 103 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4ea6b45..9c5e59af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [Unreleased](https://github.com/openfga/java-sdk/compare/v0.9.7...HEAD) +### Added +- Add `fga-client.request.count` counter metric to track the total number of HTTP requests made to the FGA server. This metric is **disabled by default** and must be explicitly enabled via `TelemetryConfiguration`. + ## v0.9.7 ### [0.9.7](https://github.com/openfga/java-sdk/compare/v0.9.6...v0.9.7) (2026-03-17) diff --git a/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java b/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java index 88f33f52..88744917 100644 --- a/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java +++ b/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java @@ -219,6 +219,7 @@ private CompletableFuture> processHttpResponse( Double requestDuration = (double) (System.currentTimeMillis() - requestStarted); telemetry.metrics().requestDuration(requestDuration, this.getTelemetryAttributes()); + telemetry.metrics().requestCount(1L, this.getTelemetryAttributes()); return deserializeResponse(response) .thenApply(modeledResponse -> new ApiResponse<>( diff --git a/src/main/java/dev/openfga/sdk/telemetry/Counters.java b/src/main/java/dev/openfga/sdk/telemetry/Counters.java index c755fb61..73275e1a 100644 --- a/src/main/java/dev/openfga/sdk/telemetry/Counters.java +++ b/src/main/java/dev/openfga/sdk/telemetry/Counters.java @@ -11,5 +11,14 @@ public class Counters { "fga-client.credentials.request", "The total number of times new access tokens have been requested using ClientCredentials."); + /** + * The REQUEST_COUNT counter represents the total number of HTTP requests made by the SDK. + * This counter is emitted once per underlying HTTP request. + * Note: This counter is disabled by default and must be explicitly enabled in TelemetryConfiguration. + */ + public static final Counter REQUEST_COUNT = new Counter( + "fga-client.request.count", + "The total number of HTTP requests made to the FGA server."); + private Counters() {} // Instantiation prevented. } diff --git a/src/main/java/dev/openfga/sdk/telemetry/Metrics.java b/src/main/java/dev/openfga/sdk/telemetry/Metrics.java index 88483262..817a331d 100644 --- a/src/main/java/dev/openfga/sdk/telemetry/Metrics.java +++ b/src/main/java/dev/openfga/sdk/telemetry/Metrics.java @@ -106,6 +106,20 @@ public LongCounter credentialsRequest(Long value, Map attribu return getCounter(Counters.CREDENTIALS_REQUEST, value, attributes); } + /** + * Returns a LongCounter counter for tracking the total number of HTTP requests made to the FGA server. + * This counter is emitted once per underlying HTTP request. + * Note: This counter is disabled by default and must be explicitly enabled in TelemetryConfiguration. + * + * @param value The value to be added to the counter. + * @param attributes A map of attributes associated with the metric. + * + * @return The LongCounter metric instance for request count, or null if not configured. + */ + public LongCounter requestCount(Long value, Map attributes) { + return getCounter(Counters.REQUEST_COUNT, value, attributes); + } + /** * Returns a DoubleHistogram histogram for measuring the total roundtrip time it took to process a request, including the time it took to send the request and receive the response. * diff --git a/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java b/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java index 5347c539..39596f05 100644 --- a/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java +++ b/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java @@ -50,6 +50,9 @@ void testDefaultMetrics() { assertTrue( metrics.containsKey(Histograms.REQUEST_DURATION), "The metrics map should contain the REQUEST_DURATION histogram."); + assertFalse( + metrics.containsKey(Counters.REQUEST_COUNT), + "The metrics map should NOT contain the REQUEST_COUNT counter by default."); Map> defaultAttributes = metrics.get(Counters.CREDENTIALS_REQUEST); assertNotNull(defaultAttributes, "The default attributes map should not be null."); @@ -132,6 +135,33 @@ void testDefaultMetrics() { "The default attribute map should not contain the FGA_CLIENT_REQUEST_BATCH_CHECK_SIZE attribute."); } + @Test + void testRequestCountIsDisabledByDefault() { + // Arrange + TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(); + + // Act + Map>> metrics = telemetryConfiguration.metrics(); + + // Assert + assertFalse( + metrics.containsKey(Counters.REQUEST_COUNT), + "REQUEST_COUNT should not be enabled by default."); + } + + @Test + void testRequestCountCanBeExplicitlyEnabled() { + // Arrange + Map>> metrics = new HashMap<>(); + metrics.put(Counters.REQUEST_COUNT, TelemetryConfiguration.defaultAttributes()); + TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(metrics); + + // Assert + assertTrue( + telemetryConfiguration.metrics().containsKey(Counters.REQUEST_COUNT), + "REQUEST_COUNT should be present when explicitly configured."); + } + @Test void testOverridingDefaultMetrics() { // Arrange diff --git a/src/test/java/dev/openfga/sdk/telemetry/CountersTest.java b/src/test/java/dev/openfga/sdk/telemetry/CountersTest.java index 4b69f1b3..b81b44c8 100644 --- a/src/test/java/dev/openfga/sdk/telemetry/CountersTest.java +++ b/src/test/java/dev/openfga/sdk/telemetry/CountersTest.java @@ -19,4 +19,18 @@ void shouldCreateCredentialsRequestCounter() { assertThat(counter.getName()).isEqualTo(expectedName); assertThat(counter.getDescription()).isEqualTo(expectedDescription); } + + @Test + void shouldCreateRequestCountCounter() { + // given + String expectedName = "fga-client.request.count"; + String expectedDescription = "The total number of HTTP requests made to the FGA server."; + + // when + Counter counter = Counters.REQUEST_COUNT; + + // then + assertThat(counter.getName()).isEqualTo(expectedName); + assertThat(counter.getDescription()).isEqualTo(expectedDescription); + } } diff --git a/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java b/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java index 8c47b995..c433fcfb 100644 --- a/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java +++ b/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java @@ -114,6 +114,35 @@ void shouldQueryDuration() { assertThat(doubleHistogram).isNotNull(); } + @Test + void shouldReturnNullForRequestCountWhenNotConfigured() { + // given - default configuration does not include REQUEST_COUNT + Metrics metrics = new Metrics(new Configuration()); + + // when + LongCounter counter = metrics.requestCount(1L, Map.of()); + + // then + assertThat(counter).isNull(); + } + + @Test + void shouldReturnRequestCountWhenExplicitlyEnabled() { + // given + Map> attrs = Map.of(); + Map>> configuredMetrics = + Map.of(Counters.REQUEST_COUNT, attrs); + TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(configuredMetrics); + Configuration config = new Configuration().telemetryConfiguration(telemetryConfiguration); + Metrics metrics = new Metrics(config); + + // when + LongCounter counter = metrics.requestCount(1L, Map.of()); + + // then + assertThat(counter).isNotNull(); + } + @Test void shouldNotSentMetricsIfNotConfigured() { // given @@ -173,6 +202,9 @@ void shouldDefaultMetricsEnabled() { .isNotNull(); assertThat(metrics.getHistogram(Histograms.REQUEST_DURATION, 10.0, Map.of())) .isNotNull(); + // REQUEST_COUNT is disabled by default + assertThat(metrics.getCounter(Counters.REQUEST_COUNT, 1L, Map.of())) + .isNull(); } @Test From 3ce00d54c577f0c77860c979a5f1dfda7fa29213 Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Thu, 26 Mar 2026 21:41:24 +0530 Subject: [PATCH 2/3] fix: lint --- src/main/java/dev/openfga/sdk/telemetry/Counters.java | 5 ++--- .../sdk/api/configuration/TelemetryConfigurationTest.java | 4 +--- src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java | 6 ++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/dev/openfga/sdk/telemetry/Counters.java b/src/main/java/dev/openfga/sdk/telemetry/Counters.java index 73275e1a..4089e496 100644 --- a/src/main/java/dev/openfga/sdk/telemetry/Counters.java +++ b/src/main/java/dev/openfga/sdk/telemetry/Counters.java @@ -16,9 +16,8 @@ public class Counters { * This counter is emitted once per underlying HTTP request. * Note: This counter is disabled by default and must be explicitly enabled in TelemetryConfiguration. */ - public static final Counter REQUEST_COUNT = new Counter( - "fga-client.request.count", - "The total number of HTTP requests made to the FGA server."); + public static final Counter REQUEST_COUNT = + new Counter("fga-client.request.count", "The total number of HTTP requests made to the FGA server."); private Counters() {} // Instantiation prevented. } diff --git a/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java b/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java index 39596f05..bd475ceb 100644 --- a/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java +++ b/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java @@ -144,9 +144,7 @@ void testRequestCountIsDisabledByDefault() { Map>> metrics = telemetryConfiguration.metrics(); // Assert - assertFalse( - metrics.containsKey(Counters.REQUEST_COUNT), - "REQUEST_COUNT should not be enabled by default."); + assertFalse(metrics.containsKey(Counters.REQUEST_COUNT), "REQUEST_COUNT should not be enabled by default."); } @Test diff --git a/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java b/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java index c433fcfb..ffe313ca 100644 --- a/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java +++ b/src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java @@ -130,8 +130,7 @@ void shouldReturnNullForRequestCountWhenNotConfigured() { void shouldReturnRequestCountWhenExplicitlyEnabled() { // given Map> attrs = Map.of(); - Map>> configuredMetrics = - Map.of(Counters.REQUEST_COUNT, attrs); + Map>> configuredMetrics = Map.of(Counters.REQUEST_COUNT, attrs); TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(configuredMetrics); Configuration config = new Configuration().telemetryConfiguration(telemetryConfiguration); Metrics metrics = new Metrics(config); @@ -203,8 +202,7 @@ void shouldDefaultMetricsEnabled() { assertThat(metrics.getHistogram(Histograms.REQUEST_DURATION, 10.0, Map.of())) .isNotNull(); // REQUEST_COUNT is disabled by default - assertThat(metrics.getCounter(Counters.REQUEST_COUNT, 1L, Map.of())) - .isNull(); + assertThat(metrics.getCounter(Counters.REQUEST_COUNT, 1L, Map.of())).isNull(); } @Test From c615e98f4877e6c45dacbe83ebb7d35d32b7c1b2 Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Fri, 27 Mar 2026 11:38:33 +0530 Subject: [PATCH 3/3] feat: remove duplicate assertion --- .../configuration/TelemetryConfigurationTest.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java b/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java index bd475ceb..e85baee7 100644 --- a/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java +++ b/src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java @@ -135,18 +135,6 @@ void testDefaultMetrics() { "The default attribute map should not contain the FGA_CLIENT_REQUEST_BATCH_CHECK_SIZE attribute."); } - @Test - void testRequestCountIsDisabledByDefault() { - // Arrange - TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(); - - // Act - Map>> metrics = telemetryConfiguration.metrics(); - - // Assert - assertFalse(metrics.containsKey(Counters.REQUEST_COUNT), "REQUEST_COUNT should not be enabled by default."); - } - @Test void testRequestCountCanBeExplicitlyEnabled() { // Arrange