Skip to content

feat(telemetry): add fga-client.request.count metric#286

Merged
emilic merged 4 commits intomainfrom
feat/http-req-count
Mar 24, 2026
Merged

feat(telemetry): add fga-client.request.count metric#286
emilic merged 4 commits intomainfrom
feat/http-req-count

Conversation

@emilic
Copy link
Copy Markdown
Contributor

@emilic emilic commented Mar 16, 2026

…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

  • I have clicked on "allow edits by maintainers".
  • I have added documentation for new/changed functionality in this PR or in a PR to openfga.dev [Provide a link to any relevant PRs in the references section above]
  • The correct base branch is being used, if not main
  • I have added tests to validate that the change in functionality is working as expected

Summary by CodeRabbit

  • New Features

    • Added a request count metric that tracks the total number of HTTP requests made by the SDK. The metric is configurable and respects your telemetry settings, integrating seamlessly with existing telemetry infrastructure.
  • Tests

    • Added comprehensive test coverage for the new request count metric.

…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
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d9f16519-97fd-418f-962e-f32d6337e607

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The PR adds the fga-client.request.count metric to the Go SDK for tracking HTTP requests. It introduces metric definitions, configuration options, attribute preparation, and integration throughout the telemetry system, with comprehensive test coverage.

Changes

Cohort / File(s) Summary
Core Integration
api_executor.go
Calls metrics.RequestCount(1, attrs) after building telemetry attributes to record request count metric on each HTTP request.
Metric Definition
telemetry/counters.go
Introduces constant METRIC_COUNTER_REQUEST_COUNT and exported variable RequestCount defining the request count metric with name and description.
Configuration
telemetry/configuration.go
Adds METRIC_COUNTER_REQUEST_COUNT field to MetricsConfiguration struct, initialized in DefaultTelemetryConfiguration with attribute settings for the new metric.
Attribute Handling
telemetry/attributes.go
Extends Metrics.PrepareAttributes switch with case for METRIC_COUNTER_REQUEST_COUNT, mirroring existing pattern for configuration-gated metric attributes.
Telemetry Interface
telemetry/metrics.go
Adds RequestCount method to MetricsInterface and implements it in Metrics type, retrieving counter, preparing attributes, and incrementing when no errors occur.
Public API
telemetry/telemetry.go
Introduces RequestCountMetricParameters struct and RequestCountMetric function to expose request count metric functionality at package level.
Test Coverage
telemetry/counters_test.go, telemetry/metrics_test.go, telemetry/configuration_test.go, telemetry/telemetry_test.go
Adds tests validating metric definition, configuration defaults, interface behavior, and public API integration.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • SoulPancake
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR fully implements issue #282 requirements: adds fga-client.request.count metric [#282], ensures it increments per HTTP request [#282], and achieves cross-SDK parity with .NET [#282].
Out of Scope Changes check ✅ Passed All changes are within scope: new metric configuration, counter definition, metrics interface implementation, and comprehensive tests—all directly support adding the request count metric.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and specifically describes the main change: adding a new fga-client.request.count metric for telemetry. It is concise, clear, and directly relates to the primary objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/http-req-count

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 85.71429% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.85%. Comparing base (d8c395e) to head (9e3112d).

Files with missing lines Patch % Lines
telemetry/attributes.go 0.00% 4 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@emilic emilic marked this pull request as ready for review March 16, 2026 16:55
@emilic emilic requested a review from a team as a code owner March 16, 2026 16:55
Copilot AI review requested due to automatic review settings March 16, 2026 16:55
@dosubot
Copy link
Copy Markdown

dosubot bot commented Mar 16, 2026

Documentation Updates

1 document(s) were updated by changes in this PR:

OpenTelemetry Metrics Integration
View 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

How did I do? Any feedback?  Join Discord

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
telemetry/attributes.go (1)

65-70: Add direct tests for the new PrepareAttributes request-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

📥 Commits

Reviewing files that changed from the base of the PR and between 7e50860 and 1205199.

📒 Files selected for processing (10)
  • api_executor.go
  • telemetry/attributes.go
  • telemetry/configuration.go
  • telemetry/configuration_test.go
  • telemetry/counters.go
  • telemetry/counters_test.go
  • telemetry/metrics.go
  • telemetry/metrics_test.go
  • telemetry/telemetry.go
  • telemetry/telemetry_test.go

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 RequestCount counter definition and default configuration wiring for attributes.
  • Implements MetricsInterface.RequestCount + factory helper, and records the counter in apiExecutor.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.

@emilic emilic enabled auto-merge March 23, 2026 17:07
Copy link
Copy Markdown
Member

@SoulPancake SoulPancake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @emilic
Looks solid overall
Can you also add a changelog entry for this?

@SoulPancake SoulPancake changed the title feat(telemetry): add fga-client.request.count metric for tracking HTT… feat(telemetry): add fga-client.request.count metric Mar 24, 2026
@emilic
Copy link
Copy Markdown
Contributor Author

emilic commented Mar 24, 2026

Hi @emilic Looks solid overall Can you also add a changelog entry for this?

@SoulPancake - added changelog

@emilic emilic added this pull request to the merge queue Mar 24, 2026
Merged via the queue into main with commit 9c8c53a Mar 24, 2026
18 checks passed
@emilic emilic deleted the feat/http-req-count branch March 24, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add fga-client.request.count metric for tracking HTTP requests

4 participants