Skip to content

Commit cc3a5f2

Browse files
authored
feat: report a per call http metric (#310)
* feat: add per call http metric * fix: lint * feat: remove duplicate assertion
1 parent 9d2fde1 commit cc3a5f2

7 files changed

Lines changed: 86 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## [Unreleased](https://github.com/openfga/java-sdk/compare/v0.9.7...HEAD)
44

5+
### Added
6+
- 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`.
7+
58
## v0.9.7
69

710
### [0.9.7](https://github.com/openfga/java-sdk/compare/v0.9.6...v0.9.7) (2026-03-17)

src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ private CompletableFuture<ApiResponse<T>> processHttpResponse(
219219
Double requestDuration = (double) (System.currentTimeMillis() - requestStarted);
220220

221221
telemetry.metrics().requestDuration(requestDuration, this.getTelemetryAttributes());
222+
telemetry.metrics().requestCount(1L, this.getTelemetryAttributes());
222223

223224
return deserializeResponse(response)
224225
.thenApply(modeledResponse -> new ApiResponse<>(

src/main/java/dev/openfga/sdk/telemetry/Counters.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,13 @@ public class Counters {
1111
"fga-client.credentials.request",
1212
"The total number of times new access tokens have been requested using ClientCredentials.");
1313

14+
/**
15+
* The REQUEST_COUNT counter represents the total number of HTTP requests made by the SDK.
16+
* This counter is emitted once per underlying HTTP request.
17+
* Note: This counter is disabled by default and must be explicitly enabled in TelemetryConfiguration.
18+
*/
19+
public static final Counter REQUEST_COUNT =
20+
new Counter("fga-client.request.count", "The total number of HTTP requests made to the FGA server.");
21+
1422
private Counters() {} // Instantiation prevented.
1523
}

src/main/java/dev/openfga/sdk/telemetry/Metrics.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@ public LongCounter credentialsRequest(Long value, Map<Attribute, String> attribu
106106
return getCounter(Counters.CREDENTIALS_REQUEST, value, attributes);
107107
}
108108

109+
/**
110+
* Returns a LongCounter counter for tracking the total number of HTTP requests made to the FGA server.
111+
* This counter is emitted once per underlying HTTP request.
112+
* Note: This counter is disabled by default and must be explicitly enabled in TelemetryConfiguration.
113+
*
114+
* @param value The value to be added to the counter.
115+
* @param attributes A map of attributes associated with the metric.
116+
*
117+
* @return The LongCounter metric instance for request count, or null if not configured.
118+
*/
119+
public LongCounter requestCount(Long value, Map<Attribute, String> attributes) {
120+
return getCounter(Counters.REQUEST_COUNT, value, attributes);
121+
}
122+
109123
/**
110124
* 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.
111125
*

src/test/java/dev/openfga/sdk/api/configuration/TelemetryConfigurationTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ void testDefaultMetrics() {
5050
assertTrue(
5151
metrics.containsKey(Histograms.REQUEST_DURATION),
5252
"The metrics map should contain the REQUEST_DURATION histogram.");
53+
assertFalse(
54+
metrics.containsKey(Counters.REQUEST_COUNT),
55+
"The metrics map should NOT contain the REQUEST_COUNT counter by default.");
5356

5457
Map<Attribute, Optional<Object>> defaultAttributes = metrics.get(Counters.CREDENTIALS_REQUEST);
5558
assertNotNull(defaultAttributes, "The default attributes map should not be null.");
@@ -132,6 +135,19 @@ void testDefaultMetrics() {
132135
"The default attribute map should not contain the FGA_CLIENT_REQUEST_BATCH_CHECK_SIZE attribute.");
133136
}
134137

138+
@Test
139+
void testRequestCountCanBeExplicitlyEnabled() {
140+
// Arrange
141+
Map<Metric, Map<Attribute, Optional<Object>>> metrics = new HashMap<>();
142+
metrics.put(Counters.REQUEST_COUNT, TelemetryConfiguration.defaultAttributes());
143+
TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(metrics);
144+
145+
// Assert
146+
assertTrue(
147+
telemetryConfiguration.metrics().containsKey(Counters.REQUEST_COUNT),
148+
"REQUEST_COUNT should be present when explicitly configured.");
149+
}
150+
135151
@Test
136152
void testOverridingDefaultMetrics() {
137153
// Arrange

src/test/java/dev/openfga/sdk/telemetry/CountersTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,18 @@ void shouldCreateCredentialsRequestCounter() {
1919
assertThat(counter.getName()).isEqualTo(expectedName);
2020
assertThat(counter.getDescription()).isEqualTo(expectedDescription);
2121
}
22+
23+
@Test
24+
void shouldCreateRequestCountCounter() {
25+
// given
26+
String expectedName = "fga-client.request.count";
27+
String expectedDescription = "The total number of HTTP requests made to the FGA server.";
28+
29+
// when
30+
Counter counter = Counters.REQUEST_COUNT;
31+
32+
// then
33+
assertThat(counter.getName()).isEqualTo(expectedName);
34+
assertThat(counter.getDescription()).isEqualTo(expectedDescription);
35+
}
2236
}

src/test/java/dev/openfga/sdk/telemetry/MetricsTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,34 @@ void shouldQueryDuration() {
114114
assertThat(doubleHistogram).isNotNull();
115115
}
116116

117+
@Test
118+
void shouldReturnNullForRequestCountWhenNotConfigured() {
119+
// given - default configuration does not include REQUEST_COUNT
120+
Metrics metrics = new Metrics(new Configuration());
121+
122+
// when
123+
LongCounter counter = metrics.requestCount(1L, Map.of());
124+
125+
// then
126+
assertThat(counter).isNull();
127+
}
128+
129+
@Test
130+
void shouldReturnRequestCountWhenExplicitlyEnabled() {
131+
// given
132+
Map<Attribute, Optional<Object>> attrs = Map.of();
133+
Map<Metric, Map<Attribute, Optional<Object>>> configuredMetrics = Map.of(Counters.REQUEST_COUNT, attrs);
134+
TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(configuredMetrics);
135+
Configuration config = new Configuration().telemetryConfiguration(telemetryConfiguration);
136+
Metrics metrics = new Metrics(config);
137+
138+
// when
139+
LongCounter counter = metrics.requestCount(1L, Map.of());
140+
141+
// then
142+
assertThat(counter).isNotNull();
143+
}
144+
117145
@Test
118146
void shouldNotSentMetricsIfNotConfigured() {
119147
// given
@@ -173,6 +201,8 @@ void shouldDefaultMetricsEnabled() {
173201
.isNotNull();
174202
assertThat(metrics.getHistogram(Histograms.REQUEST_DURATION, 10.0, Map.of()))
175203
.isNotNull();
204+
// REQUEST_COUNT is disabled by default
205+
assertThat(metrics.getCounter(Counters.REQUEST_COUNT, 1L, Map.of())).isNull();
176206
}
177207

178208
@Test

0 commit comments

Comments
 (0)