Skip to content

feat: adds http metrics to OTEL - #4294

Merged
akshaydeo merged 2 commits into
devfrom
06-11-feat_adds_http_metrics_to_otel
Jun 11, 2026
Merged

feat: adds http metrics to OTEL#4294
akshaydeo merged 2 commits into
devfrom
06-11-feat_adds_http_metrics_to_otel

Conversation

@roroghost17

@roroghost17 roroghost17 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds http_request_size_bytes and http_response_size_bytes histogram metrics to the OTel plugin, giving operators visibility into HTTP payload sizes alongside the existing request count and duration metrics.

Changes

  • Added RecordHTTPMetrics method to OtelPlugin that records request count, duration, and request/response body sizes in a single call. Non-positive sizes (e.g. -1 when Content-Length is unknown in fasthttp) are skipped to avoid polluting histograms with sentinel values.
  • Added an OTel HTTP metrics middleware in PrepareCommonMiddlewares that captures request size before the handler runs, then resolves the OTel plugin instance after the response is complete. The plugin is resolved per-request rather than captured at startup to avoid recording against stale meter providers after a config reload.
  • Documented the two new metrics (http_request_size_bytes, http_response_size_bytes) in the OTel observability reference docs.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

Start Bifrost with an OTel plugin configured and a metrics exporter pointing at an OTLP-compatible backend (e.g. Prometheus via the OTLP receiver or an OTel Collector).

Send a few HTTP requests and verify the following metrics appear with path, method, and status labels:

# Example: query Prometheus
curl -s http://localhost:9090/api/v1/query?query=http_request_size_bytes_bucket | jq .
curl -s http://localhost:9090/api/v1/query?query=http_response_size_bytes_bucket | jq .

Confirm that requests without a Content-Length header (size reported as -1 by fasthttp) do not produce a data point in http_request_size_bytes.

go test ./plugins/otel/... ./transports/bifrost-http/...

Screenshots/Recordings

N/A

Breaking changes

  • No

Related issues

N/A

Security considerations

No new auth, secrets, or PII surface. Request and response sizes are recorded as numeric values only; no body content is captured.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

Summary by CodeRabbit

  • New Features

    • HTTP request and response body size histograms are now collected and exported via OpenTelemetry with explicit bucket boundaries; sizes are recorded only when Content-Length is present.
    • Per-request metrics now include counts, durations, and conditional payload-size measurements to improve request observability.
  • Documentation

    • Observability docs updated to describe the new size histograms and their recording conditions.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f5e08e8e-654a-4ac3-9fb6-16c6bc28b8fc

📥 Commits

Reviewing files that changed from the base of the PR and between 3d6a2dd and 069a2a9.

📒 Files selected for processing (4)
  • docs/features/observability/otel.mdx
  • plugins/otel/main.go
  • plugins/otel/metrics.go
  • transports/bifrost-http/server/server.go

📝 Walkthrough

Walkthrough

Adds explicit HTTP body-size histogram buckets and two new histograms, implements OtelPlugin.RecordHTTPMetrics to record request count, duration, and optional sizes, wires a server middleware to capture per-request timing and sizes and call the new method, and updates docs to list the new metrics.

Changes

HTTP Metrics Recording Integration

Layer / File(s) Summary
HTTP body size histogram buckets
plugins/otel/metrics.go
Defines httpBodySizeBuckets and applies these explicit boundaries to http_request_size_bytes and http_response_size_bytes.
HTTP metrics recording method
plugins/otel/main.go
OtelPlugin.RecordHTTPMetrics records HTTP request count and duration and conditionally records request/response sizes for each configured metrics exporter target.
HTTP server metrics middleware
transports/bifrost-http/server/server.go
Adds middleware in PrepareCommonMiddlewares that captures request start time, request/response Content-Length and status, then resolves the Otel plugin and calls RecordHTTPMetrics with path, method, status, duration, and sizes.
Metrics documentation
docs/features/observability/otel.mdx
Adds http_request_size_bytes and http_response_size_bytes to the "Pushed Metrics" table and notes sizes are only emitted when Content-Length is present.

Sequence Diagram

sequenceDiagram
  participant HTTPRequest
  participant ServerMiddleware
  participant OtelPlugin
  participant MetricsExporter
  HTTPRequest->>ServerMiddleware: incoming request
  activate ServerMiddleware
  ServerMiddleware->>ServerMiddleware: capture start time, content-length
  ServerMiddleware->>ServerMiddleware: execute handler, capture response status and size
  ServerMiddleware->>OtelPlugin: RecordHTTPMetrics(path, method, status, duration, requestSize, responseSize)
  activate OtelPlugin
  OtelPlugin->>OtelPlugin: build HTTP attributes
  OtelPlugin->>MetricsExporter: record metrics for active targets
  deactivate OtelPlugin
  ServerMiddleware->>HTTPRequest: return response
  deactivate ServerMiddleware
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • danpiths
  • akshaydeo

Poem

🐇 I hopped along the HTTP trail,
Counting bytes where headers prevail,
Durations tallied, sizes too,
Content-Length tells what is true,
Metrics bloom — a tiny observability tale.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change—adding HTTP metrics to the OpenTelemetry plugin—and is concise and specific.
Description check ✅ Passed The description covers all key required sections: summary, changes, type of change (marked), affected areas (marked), testing instructions, and security considerations. All critical information is present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 06-11-feat_adds_http_metrics_to_otel

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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

roroghost17 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

@CLAassistant

CLAassistant commented Jun 11, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@roroghost17
roroghost17 marked this pull request as ready for review June 11, 2026 14:06

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/features/observability/otel.mdx`:
- Around line 944-945: The table entries for `http_request_size_bytes` and
`http_response_size_bytes` don't mention that sizes are only recorded when
Content-Length is known (fasthttp reports -1 otherwise); update the
documentation to clarify this by modifying the descriptions for those two
metrics to something like "HTTP request body size (when Content-Length is
present)" and/or add a short callout below the table stating "Note: Size metrics
are only recorded when the Content-Length header is present; requests without
Content-Length (e.g., chunked transfer) will not produce data points in these
histograms."
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 84286416-735c-4234-a23f-e350782f496e

📥 Commits

Reviewing files that changed from the base of the PR and between 066504c and e69befb.

📒 Files selected for processing (3)
  • docs/features/observability/otel.mdx
  • plugins/otel/main.go
  • transports/bifrost-http/server/server.go

Comment thread docs/features/observability/otel.mdx
@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

Safe to merge for the OTel metrics feature; the bundled migration is functionally correct but performs a full-table UPDATE without batching.

The OTel plugin and server middleware changes are straightforward and correct — size guards, histogram boundaries, and per-request plugin resolution all look right. The one concern is in the bundled migration: the final UPDATE governance_customers SET budget_id = NULL WHERE budget_id IS NOT NULL is an unbatched full-table write inside a single transaction. For deployments with many governance customers this could hold a write lock longer than expected, which may delay concurrent governance API calls during the upgrade. The migration logic itself is sound; it's the single-statement approach rather than batching that warrants a second look before deploying to large instances.

framework/configstore/migrations.go — the final bulk UPDATE in migrationNullLegacyCustomerBudgetID

Important Files Changed

Filename Overview
plugins/otel/metrics.go Adds explicit httpBodySizeBuckets (100B–1GB exponential) to httpRequestSizeBytes and httpResponseSizeBytes histograms; initialization path is clean and consistent with other histograms
plugins/otel/main.go New RecordHTTPMetrics method correctly guards against non-positive sizes and iterates over all targets' metrics exporters; no-op when metrics are disabled
transports/bifrost-http/server/server.go OTel middleware is appended unconditionally (runs lib.FindPluginAs on every request even when no OTel plugin is configured), unlike the Prometheus branch; core logic for capturing request/response sizes is otherwise correct
framework/configstore/migrations.go New migration nulls the legacy governance_customers.budget_id column; final bulk UPDATE runs without row-batching inside the migrator transaction, which could hold a write lock on larger deployments
docs/features/observability/otel.mdx Two new metrics rows added to the metrics table with accurate recording-condition note

Reviews (4): Last reviewed commit: "feat: adds http metrics to OTEL" | Re-trigger Greptile

Comment thread transports/bifrost-http/server/server.go

akshaydeo commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Merge activity

@akshaydeo
akshaydeo changed the base branch from 06-11-fix_fixes_customer_fk_column_issue to graphite-base/4294 June 11, 2026 19:17
@roroghost17
roroghost17 force-pushed the 06-11-feat_adds_http_metrics_to_otel branch from 3d6a2dd to 069a2a9 Compare June 11, 2026 19:21
@akshaydeo
akshaydeo changed the base branch from graphite-base/4294 to dev June 11, 2026 19:27
@akshaydeo
akshaydeo merged commit 975c2cd into dev Jun 11, 2026
8 of 11 checks passed
@akshaydeo
akshaydeo deleted the 06-11-feat_adds_http_metrics_to_otel branch June 11, 2026 19:27
akshaydeo pushed a commit that referenced this pull request Jun 12, 2026
## Summary

Adds `http_request_size_bytes` and `http_response_size_bytes` histogram metrics to the OTel plugin, giving operators visibility into HTTP payload sizes alongside the existing request count and duration metrics.

## Changes

- Added `RecordHTTPMetrics` method to `OtelPlugin` that records request count, duration, and request/response body sizes in a single call. Non-positive sizes (e.g. `-1` when `Content-Length` is unknown in fasthttp) are skipped to avoid polluting histograms with sentinel values.
- Added an OTel HTTP metrics middleware in `PrepareCommonMiddlewares` that captures request size before the handler runs, then resolves the OTel plugin instance after the response is complete. The plugin is resolved per-request rather than captured at startup to avoid recording against stale meter providers after a config reload.
- Documented the two new metrics (`http_request_size_bytes`, `http_response_size_bytes`) in the OTel observability reference docs.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

Start Bifrost with an OTel plugin configured and a metrics exporter pointing at an OTLP-compatible backend (e.g. Prometheus via the OTLP receiver or an OTel Collector).

Send a few HTTP requests and verify the following metrics appear with `path`, `method`, and `status` labels:

```sh
# Example: query Prometheus
curl -s http://localhost:9090/api/v1/query?query=http_request_size_bytes_bucket | jq .
curl -s http://localhost:9090/api/v1/query?query=http_response_size_bytes_bucket | jq .
```

Confirm that requests without a `Content-Length` header (size reported as `-1` by fasthttp) do **not** produce a data point in `http_request_size_bytes`.

```sh
go test ./plugins/otel/... ./transports/bifrost-http/...
```

## Screenshots/Recordings

N/A

## Breaking changes

- [x] No

## Related issues

N/A

## Security considerations

No new auth, secrets, or PII surface. Request and response sizes are recorded as numeric values only; no body content is captured.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * HTTP request and response body size histograms are now collected and exported via OpenTelemetry with explicit bucket boundaries; sizes are recorded only when Content-Length is present.
  * Per-request metrics now include counts, durations, and conditional payload-size measurements to improve request observability.

* **Documentation**
  * Observability docs updated to describe the new size histograms and their recording conditions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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.

3 participants