feat(telemetry): add fga-client.request.count metric#286
Conversation
…P requests Record a counter metric on every HTTP attempt in recordTelemetry(), alongside the existing request.duration and query.duration metrics. This enables users to track the total number of HTTP requests made by the SDK via OpenTelemetry. Closes #282
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThe PR adds the Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client Code
participant Executor as api_executor
participant Metrics as metrics.Metrics
participant Telemetry as OpenTelemetry Backend
Client->>Executor: Execute HTTP Request
Executor->>Executor: Build telemetry attributes
Executor->>Metrics: RequestCount(1, attrs)
Metrics->>Metrics: GetCounter()
Metrics->>Metrics: PrepareAttributes(METRIC_COUNTER_REQUEST_COUNT)
Metrics->>Telemetry: counter.Add(1, attrs)
Telemetry-->>Metrics: Success
Metrics-->>Executor: Return counter
Executor->>Executor: Continue request execution
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #286 +/- ##
==========================================
+ Coverage 33.70% 33.85% +0.14%
==========================================
Files 115 115
Lines 9826 9854 +28
==========================================
+ Hits 3312 3336 +24
- Misses 6244 6248 +4
Partials 270 270 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Documentation Updates 1 document(s) were updated by changes in this PR: OpenTelemetry Metrics IntegrationView Changes@@ -10,6 +10,7 @@
|--------------------------------------|-----------|--------------------|----------------------------------------------------------------------------------------------|
| `fga-client.request.duration` | Histogram | Yes | Total request time for FGA requests (milliseconds) |
| `fga-client.query.duration` | Histogram | Yes | Time taken by the FGA server to process and evaluate the request (milliseconds) |
+| `fga-client.request.count` | Counter | Yes | Total number of HTTP requests made by the SDK |
| `fga-client.credentials.request` | Counter | Yes | Total number of new token requests initiated using the Client Credentials flow |
| `fga-client.http_request.duration` | Histogram | Yes (JS/Java), No (Go) | Time taken for a single HTTP request to complete, including retries (milliseconds) |
@@ -24,19 +25,19 @@
| Attribute Name | Type | Enabled by Default | Description | Used By Metrics |
|--------------------------------------- |---------|--------------------|-----------------------------------------------------------------------------------------------|-----------------------------------------|
-| `fga-client.response.model_id` | string | Yes | Authorization model ID used by the FGA server | request.duration, query.duration |
+| `fga-client.response.model_id` | string | Yes | Authorization model ID used by the FGA server | request.duration, query.duration, request.count |
| `fga-client.request.method` | string | Yes | FGA method/action performed (e.g., Check, ListObjects) | request.duration, query.duration |
-| `fga-client.request.store_id` | string | Yes | Store ID sent in the request | request.duration, query.duration |
-| `fga-client.request.model_id` | string | Yes | Authorization model ID sent in the request, if any | request.duration, query.duration |
-| `fga-client.request.client_id` | string | Yes | Client ID associated with the request, if any | request.duration, query.duration |
+| `fga-client.request.store_id` | string | Yes | Store ID sent in the request | request.duration, query.duration, request.count |
+| `fga-client.request.model_id` | string | Yes | Authorization model ID sent in the request, if any | request.duration, query.duration, request.count |
+| `fga-client.request.client_id` | string | Yes | Client ID associated with the request, if any | request.duration, query.duration, request.count |
| `fga-client.user` | string | No | User associated with the action (for check and list users); disabled by default | request.duration, query.duration |
-| `http.status_code` / `http.response.status_code` | int | Yes | HTTP response status code | request.duration, query.duration, http_request.duration |
-| `http.request.method` | string | (JS: No, Java: Yes)| HTTP method for the request | request.duration, query.duration, http_request.duration |
-| `http.host` | string | Yes | Host identifier of the origin | request.duration, query.duration, http_request.duration |
-| `user_agent.original` | string | Yes | User agent used in the query | request.duration, query.duration, http_request.duration |
-| `url.full` | string | (JS: No, Java: Yes)| Full URL of the request | request.duration, query.duration, http_request.duration |
-| `url.scheme` | string | (JS: No, Java: Yes)| HTTP scheme (`http`/`https`) | request.duration, query.duration, http_request.duration |
-| `http.request.resend_count` | int | Yes | Number of retries attempted | request.duration, query.duration |
+| `http.status_code` / `http.response.status_code` | int | Yes | HTTP response status code | request.duration, query.duration, request.count, http_request.duration |
+| `http.request.method` | string | (JS: No, Java: Yes)| HTTP method for the request | request.duration, query.duration, request.count, http_request.duration |
+| `http.host` | string | Yes | Host identifier of the origin | request.duration, query.duration, request.count, http_request.duration |
+| `user_agent.original` | string | Yes | User agent used in the query | request.duration, query.duration, request.count, http_request.duration |
+| `url.full` | string | (JS: No, Java: Yes)| Full URL of the request | request.duration, query.duration, request.count, http_request.duration |
+| `url.scheme` | string | (JS: No, Java: Yes)| HTTP scheme (`http`/`https`) | request.duration, query.duration, request.count, http_request.duration |
+| `http.request.resend_count` | int | Yes | Number of retries attempted | request.duration, query.duration, request.count |
| `fga-client.request.batch_check_size` | int | No | Number of checks in a batch check request | request.duration, query.duration |
| `http.client.request.duration` | int | No (JS only) | Time taken by the FGA server to process and evaluate the request (rounded to ms) | |
| `http.server.request.duration` | int | No (JS only) | Number of retries attempted | |
@@ -166,7 +167,7 @@
[See full Java configuration example](https://github.com/openfga/java-sdk/blob/main/docs/OpenTelemetry.md#metrics-configuration)
#### Go SDK
-In the Go SDK, the `fga-client.http_request.duration` metric is disabled by default to reduce overhead. To enable it, explicitly configure it in your telemetry configuration:
+In the Go SDK, the `fga-client.http_request.duration` metric is disabled by default to reduce overhead. The `fga-client.request.count` counter metric is enabled by default. To enable or configure metrics, use the telemetry configuration:
```go
import (
@@ -184,9 +185,24 @@
telemetry.ATTR_URL_SCHEME: &telemetry.AttributeConfiguration{Enabled: true},
telemetry.ATTR_USER_AGENT_ORIGINAL: &telemetry.AttributeConfiguration{Enabled: true},
}
-```
-
-Once configured, pass this configuration to your OpenFGA client to begin collecting HTTP request duration metrics.
+
+// Configure the request count metric attributes (enabled by default)
+config.Metrics.METRIC_COUNTER_REQUEST_COUNT = &telemetry.MetricConfiguration{
+ telemetry.ATTR_FGA_CLIENT_REQUEST_CLIENT_ID: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_HTTP_REQUEST_METHOD: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_FGA_CLIENT_REQUEST_MODEL_ID: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_FGA_CLIENT_REQUEST_STORE_ID: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_FGA_CLIENT_RESPONSE_MODEL_ID: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_HTTP_HOST: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_HTTP_REQUEST_RESEND_COUNT: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_HTTP_RESPONSE_STATUS_CODE: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_URL_FULL: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_URL_SCHEME: &telemetry.AttributeConfiguration{Enabled: true},
+ telemetry.ATTR_USER_AGENT_ORIGINAL: &telemetry.AttributeConfiguration{Enabled: true},
+}
+```
+
+Once configured, pass this configuration to your OpenFGA client to begin collecting metrics.
[See Go SDK telemetry documentation](https://github.com/openfga/go-sdk/blob/main/telemetry/README.md)
@@ -197,6 +213,7 @@
- `fga_client_request_duration_bucket` (request duration histogram)
- `fga_client_query_duration_bucket` (query duration histogram)
+- `fga_client_request_count_total` (request count counter)
- `fga_client_http_request_duration_bucket` (HTTP request duration histogram)
- `fga_client_credentials_request_total` (credentials request counter)
@@ -210,6 +227,9 @@
rate(fga_client_http_request_duration_sum[5m]) / rate(fga_client_http_request_duration_count[5m])
# Request rate by HTTP status code
+rate(fga_client_request_count_total[5m])
+
+# Request rate (alternative query)
rate(fga_client_request_duration_count[5m])
# 95th percentile HTTP request duration |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
telemetry/attributes.go (1)
65-70: Add direct tests for the newPrepareAttributesrequest-count branch.The new switch branch is correct, but this path should get explicit tests (including nil config and enabled config cases) to cover the newly introduced lines and prevent regression drift.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@telemetry/attributes.go` around lines 65 - 70, Add unit tests covering the PrepareAttributes function's METRIC_COUNTER_REQUEST_COUNT branch: write tests that call PrepareAttributes (or the exported wrapper used in tests) with (1) a config where METRIC_COUNTER_REQUEST_COUNT == nil and assert it returns attribute.EmptySet() (or equivalent) and no error, and (2) a config where METRIC_COUNTER_REQUEST_COUNT is set (enabled) and assert the returned allowed set equals that config value; reference the METRIC_COUNTER_REQUEST_COUNT switch branch in telemetry/attributes.go to locate the code under test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@api_executor.go`:
- Around line 363-364: Move the metrics.RequestCount(1, attrs) call out of
recordTelemetry and invoke it immediately after the HTTP response is available
(right after http.Do/resp != nil), before any status handling or body reads, so
every attempt (including 3xx/4xx/5xx and read-body failures) is counted; keep
recordTelemetry for success-specific fields but remove the RequestCount call
there and ensure the attrs variable used for RequestCount is prepared at that
earlier point so the counter is emitted for every response attempt.
In `@telemetry/metrics.go`:
- Around line 75-87: The method Metrics.RequestCount shadows the outer err by
using := when calling m.PrepareAttributes, so PrepareAttributes errors are
discarded; change the call in RequestCount to assign into the existing err (use
= not :=) or use a new variable name (e.g., preparedAttrs) and propagate that
err, then return the actual error instead of nil; apply the same fix to the
other methods (CredentialsRequest, RequestDuration, QueryDuration,
HTTPRequestDuration) that call m.PrepareAttributes so all PrepareAttributes
failures are returned properly and no err is shadowed when calling GetCounter or
PrepareAttributes.
---
Nitpick comments:
In `@telemetry/attributes.go`:
- Around line 65-70: Add unit tests covering the PrepareAttributes function's
METRIC_COUNTER_REQUEST_COUNT branch: write tests that call PrepareAttributes (or
the exported wrapper used in tests) with (1) a config where
METRIC_COUNTER_REQUEST_COUNT == nil and assert it returns attribute.EmptySet()
(or equivalent) and no error, and (2) a config where
METRIC_COUNTER_REQUEST_COUNT is set (enabled) and assert the returned allowed
set equals that config value; reference the METRIC_COUNTER_REQUEST_COUNT switch
branch in telemetry/attributes.go to locate the code under test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 73f84c7f-e936-4a2e-a9ae-87dcfb97fdff
📒 Files selected for processing (10)
api_executor.gotelemetry/attributes.gotelemetry/configuration.gotelemetry/configuration_test.gotelemetry/counters.gotelemetry/counters_test.gotelemetry/metrics.gotelemetry/metrics_test.gotelemetry/telemetry.gotelemetry/telemetry_test.go
There was a problem hiding this comment.
Pull request overview
Adds a new OpenTelemetry counter metric (fga-client.request.count) to track the number of HTTP requests made by the Go SDK, aligning metrics parity across SDKs and addressing #282.
Changes:
- Introduces the
RequestCountcounter definition and default configuration wiring for attributes. - Implements
MetricsInterface.RequestCount+ factory helper, and records the counter inapiExecutor.recordTelemetry. - Adds unit tests in the telemetry package for the new counter and metric plumbing.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
api_executor.go |
Increments the new request count metric during telemetry recording. |
telemetry/attributes.go |
Allows attribute filtering/config for the new counter. |
telemetry/configuration.go |
Adds default config block for the new counter and its enabled attributes. |
telemetry/configuration_test.go |
Verifies default configuration includes the new counter. |
telemetry/counters.go |
Defines the fga-client.request.count counter constant + metadata. |
telemetry/counters_test.go |
Tests counter name/description initialization. |
telemetry/metrics.go |
Adds RequestCount to the metrics interface and implements the counter emission. |
telemetry/metrics_test.go |
Tests RequestCount calls Add on the counter. |
telemetry/telemetry.go |
Adds RequestCountMetricParameters and RequestCountMetric factory wrapper. |
telemetry/telemetry_test.go |
Adds a basic factory-level test for RequestCountMetric. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
SoulPancake
left a comment
There was a problem hiding this comment.
Hi @emilic
Looks solid overall
Can you also add a changelog entry for this?
@SoulPancake - added changelog |
…P requests
Record a counter metric on every HTTP attempt in recordTelemetry(), alongside the existing request.duration and query.duration metrics. This enables users to track the total number of HTTP requests made by the SDK via OpenTelemetry.
Closes #282
Description
What problem is being solved?
How is it being solved?
What changes are made to solve it?
References
Review Checklist
mainSummary by CodeRabbit
New Features
Tests