Skip to content

feat(metrics): add per-IP and DeFi transaction content metrics#440

Open
verbotenj wants to merge 1 commit intomainfrom
worktree-feat-improve-metrics
Open

feat(metrics): add per-IP and DeFi transaction content metrics#440
verbotenj wants to merge 1 commit intomainfrom
worktree-feat-improve-metrics

Conversation

@verbotenj
Copy link
Copy Markdown
Contributor

@verbotenj verbotenj commented Apr 6, 2026

Closes #32


Summary by cubic

Adds per‑IP request and transaction content Prometheus metrics to the tx‑submit API with trusted‑proxy‑aware client IP detection. Legacy gauges remain; new counters track request outcomes and DeFi‑relevant signals.

  • New Features

    • Per‑IP requests counter: tx_submit_requests_total{ip,result} with accepted/rejected/error. Client IP uses X‑Real‑IP > first X‑Forwarded‑For only when the immediate peer is in api.trustedProxies/API_TRUSTED_PROXIES; otherwise falls back to RemoteAddr.
    • Content counters: tx_submit_script_type_total{type}, tx_submit_has_minting_total{has_minting}, tx_submit_has_reference_inputs_total{has_reference_inputs}. Computed via submit.ParseTxInfo before submission; recorded on accept and reject.
    • Keeps legacy gauges tx_submit_count and tx_submit_fail_count. Skips per‑IP metric on bad Content‑Type; records error on body read failures.
  • Refactors

    • Centralized metrics in internal/metrics with Register()/RegisterForTesting(); Start() now calls metrics.Register(). internal/api updated to use the package.

Written for commit 69b3106. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Enhanced transaction submission tracking with detailed metrics including client IP capture, submission status (accepted/rejected/error), script type detection, and transaction feature analysis (minting and reference input presence).
  • Tests

    • Added comprehensive test coverage for transaction metrics recording and client IP extraction logic.

@verbotenj verbotenj requested a review from a team as a code owner April 6, 2026 04:10
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

📝 Walkthrough

Walkthrough

This pull request refactors the metrics infrastructure and adds transaction content instrumentation. A new internal/metrics package centralizes Prometheus metrics for transaction submissions, including counters for requests (labeled by IP and result), script types, and transaction features (minting, reference inputs). The API handler now extracts client IP from request headers via a new realClientIP helper, captures transaction content details through a new submit.ParseTxInfo function, and records metrics using the centralized package. Tests are added to validate metrics recording and transaction parsing across various transaction types. One indirect dependency is added to go.mod.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately captures the main changes: adding metrics for per-IP tracking and DeFi transaction content analysis.
Linked Issues check ✅ Passed The PR fully implements the stated objectives in issue #32: per-IP metrics via RecordTxRequest() [#32] and transaction content metrics via RecordTxContent() including script types and minting/reference inputs [#32].
Out of Scope Changes check ✅ Passed All changes align with issue #32 objectives. The refactoring of metric increments from direct calls to centralized functions, TxInfo parsing, and comprehensive tests are all necessary to support the per-IP and content metrics requirements.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 worktree-feat-improve-metrics

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.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="internal/metrics/metrics.go">

<violation number="1" location="internal/metrics/metrics.go:105">
P1: Using raw client IP as a Prometheus label creates unbounded cardinality and allows metric-series explosion from user-controlled inputs.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

// RecordTxRequest records a submission attempt. result is one of "accepted",
// "rejected" (node rejected the tx), or "error" (parse or internal error).
func RecordTxRequest(ip, result string) {
txSubmitRequestsTotal.WithLabelValues(ip, result).Inc()
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Apr 6, 2026

Choose a reason for hiding this comment

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

P1: Using raw client IP as a Prometheus label creates unbounded cardinality and allows metric-series explosion from user-controlled inputs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At internal/metrics/metrics.go, line 105:

<comment>Using raw client IP as a Prometheus label creates unbounded cardinality and allows metric-series explosion from user-controlled inputs.</comment>

<file context>
@@ -0,0 +1,132 @@
+// RecordTxRequest records a submission attempt. result is one of "accepted",
+// "rejected" (node rejected the tx), or "error" (parse or internal error).
+func RecordTxRequest(ip, result string) {
+	txSubmitRequestsTotal.WithLabelValues(ip, result).Inc()
+}
+
</file context>
Fix with Cubic

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: 3

🧹 Nitpick comments (1)
submit/txinfo_test.go (1)

49-123: Cover the remaining script-type branches.

The parser has explicit native and plutus_v2 outputs, but this suite only asserts "none", "plutus_v1", and "plutus_v3". A typo or precedence regression in either untested branch would skew the new metrics without failing CI.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@submit/txinfo_test.go` around lines 49 - 123, Add tests covering the missing
"native" and "plutus_v2" branches by adding two new parallel test functions
(e.g. TestParseTxInfo_NativeScript and TestParseTxInfo_PlutusV2) that call
ParseTxInfo with the existing fixture hex blobs (nativeScriptTxHex and
plutusV2TxHex via mustDecodeHex), assert info.ScriptType equals "native" and
"plutus_v2" respectively, and assert the expected HasMinting and
HasReferenceInputs booleans for those fixtures (match the fixtures' expected
values, e.g. typically false if they don't include minting/ref inputs); keep the
same error handling pattern used in the other tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/api/api.go`:
- Around line 372-380: The tx-content parsing using submit.ParseTxInfo should be
best-effort, not a hard validation gate; change the error branch so that on
parse failure you log the error (include err and context such as clientIP),
increment any relevant metrics for a parse failure if desired, set txInfo to a
nil/empty value or a safe default, and continue the normal submission flow
instead of calling writeJSON(...) and returning; update the same pattern in the
other block around lines where txInfo is parsed (also references to
metrics.IncTxSubmitFailCount and metrics.RecordTxRequest) so parsing failures
only affect the content metric and do not abort the request.
- Around line 344-345: The code currently sets clientIP := realClientIP(r)
trusting X-Real-IP/X-Forwarded-For from any caller; change realClientIP handling
so it only honors forwarded headers when the immediate peer (r.RemoteAddr or
parsed remote IP) is in the configured trusted proxies list, otherwise fall back
to using r.RemoteAddr (or the parsed remote IP) as the client IP; update the
logic used wherever realClientIP is called (including the similar block around
the code handling lines 440-456) to validate the immediate peer against the
trusted proxies set before parsing X-Forwarded-For/X-Real-IP and ensure metrics
use the resulting non-spoofable clientIP variable.

In `@internal/metrics/metrics.go`:
- Around line 17-21: The collectors are currently lazily created in Register()
causing IncTxSubmitCount() and IncTxSubmitFailCount() to panic if called earlier
and Register()/Start() to panic on duplicate calls; fix by eagerly initializing
all prometheus collectors in package init() (so globals used by
IncTxSubmitCount/IncTxSubmitFailCount are always non-nil) and protect the
prometheus.MustRegister(...) path with a sync.Once (e.g., a package-level var
registerOnce sync.Once used inside Register/Start) to make registration
idempotent and safe on repeated Start() calls.

---

Nitpick comments:
In `@submit/txinfo_test.go`:
- Around line 49-123: Add tests covering the missing "native" and "plutus_v2"
branches by adding two new parallel test functions (e.g.
TestParseTxInfo_NativeScript and TestParseTxInfo_PlutusV2) that call ParseTxInfo
with the existing fixture hex blobs (nativeScriptTxHex and plutusV2TxHex via
mustDecodeHex), assert info.ScriptType equals "native" and "plutus_v2"
respectively, and assert the expected HasMinting and HasReferenceInputs booleans
for those fixtures (match the fixtures' expected values, e.g. typically false if
they don't include minting/ref inputs); keep the same error handling pattern
used in the other tests.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ecd81817-9090-45db-8eb1-feedd0f853d4

📥 Commits

Reviewing files that changed from the base of the PR and between f854315 and 9a781cc.

📒 Files selected for processing (7)
  • go.mod
  • internal/api/api.go
  • internal/api/api_test.go
  • internal/metrics/metrics.go
  • internal/metrics/metrics_test.go
  • submit/txinfo.go
  • submit/txinfo_test.go

@verbotenj verbotenj force-pushed the worktree-feat-improve-metrics branch 4 times, most recently from 474f47a to 75d6c19 Compare April 6, 2026 04:40
Signed-off-by: Ales Verbic <verbotenj@blinklabs.io>
@verbotenj verbotenj force-pushed the worktree-feat-improve-metrics branch from 75d6c19 to 69b3106 Compare April 6, 2026 04:43
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.

Improved metrics

1 participant