Skip to content

refactor: extract metrics formatter#543

Open
zereight wants to merge 2 commits into
mainfrom
refactor/metrics-formatter
Open

refactor: extract metrics formatter#543
zereight wants to merge 2 commits into
mainfrom
refactor/metrics-formatter

Conversation

@zereight

@zereight zereight commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

Part of #516.

This keeps the metrics refactor slice behavior-preserving:

  • moves Prometheus metrics escaping/formatting into server/metrics.ts
  • adds direct unit coverage for label escaping and metric output shape
  • keeps metrics counters, snapshots, and Express routes in index.ts

Verification

  • rtk npm run build
  • node --import tsx/esm --test test/server/metrics.test.ts
  • rtk npm run test:remote-auth

Note

Low Risk
Behavior-preserving refactor of observability output with no auth or request-path changes.

Overview
Moves Prometheus label escaping and /metrics text formatting out of index.ts into server/metrics.ts, with a MetricsSnapshot type and formatPrometheusMetrics(snapshot) so formatting is pure and testable.

The /metrics handler now passes getMetricsSnapshot() into that helper; counters, snapshot assembly, and /metrics.json stay in index.ts.

Adds test/server/metrics.test.ts (label escaping and output shape) and includes it in test:mock.

Reviewed by Cursor Bugbot for commit a13bbde. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1e93c6c1-a8c6-47b6-99a6-625e2b26d770

📥 Commits

Reviewing files that changed from the base of the PR and between 6b43341 and a13bbde.

📒 Files selected for processing (1)
  • package.json
📜 Recent review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: test
  • GitHub Check: coverage
🔇 Additional comments (1)
package.json (1)

54-54: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • Refactor

    • Streamlined Prometheus metrics formatting by consolidating logic into a shared utility module.
  • Tests

    • Added comprehensive test coverage for metrics formatting and label escaping.

Walkthrough

Prometheus text exposition logic previously inlined in index.ts is extracted into a new server/metrics.ts module. The module exports a MetricsSnapshot interface, an escapePrometheusLabel utility, and a formatPrometheusMetrics function. The /metrics HTTP handler in index.ts is updated to call the shared formatter. A test file is added covering label escaping and formatter output, and the test script is updated to include the new tests.

Changes

Prometheus Metrics Formatter Extraction

Layer / File(s) Summary
MetricsSnapshot interface and Prometheus formatter
server/metrics.ts
Defines MetricsSnapshot with request/session/auth/pool/memory/config fields, adds escapePrometheusLabel() for label-safe encoding, and adds formatPrometheusMetrics() to emit HELP/TYPE headers, counter/gauge lines, per-type memory labels, and a gitlab_mcp_config_info gauge.
/metrics handler wired to shared formatter
index.ts
Imports formatPrometheusMetrics and replaces ~88 lines of inline Prometheus text construction with a single formatPrometheusMetrics(getMetricsSnapshot()) call, retaining the text/plain; version=0.0.4 content-type.
Formatter and escaping tests
test/server/metrics.test.ts, package.json
Adds a node:test suite asserting escapePrometheusLabel handles quotes, backslashes, and newlines, and that formatPrometheusMetrics output contains expected metric declarations and labeled lines. Updates the test:mock npm script to include the new metrics test file.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • zereight/gitlab-mcp#535: Introduced the original Prometheus text exposition behavior (HELP/TYPE lines, label escaping, formatPrometheusMetrics-equivalent logic) in the /metrics endpoint that this PR refactors into server/metrics.ts.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Title check ✅ Passed The title accurately describes the main change: extracting metrics formatter logic from index.ts into a dedicated server/metrics.ts module.
Description check ✅ Passed The description is well-detailed and directly relates to the changeset, explaining the refactoring objectives, verification steps, and low-risk nature of the behavior-preserving changes.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/metrics-formatter
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch refactor/metrics-formatter

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

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: New metrics test omitted from CI
    • Added test/server/metrics.test.ts to the test:mock script in package.json so it runs in CI with npm run test:all

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 6b43341. Configure here.

Comment thread test/server/metrics.test.ts
This ensures the new Prometheus formatter test runs in CI with npm run test:all

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@test/server/metrics.test.ts`:
- Around line 10-49: The test "formats current MCP metrics" currently has
limited assertions and doesn't validate all the metrics being generated. Add
additional assert.match calls to verify the Prometheus exposition format for
memory usage metrics (such as memory_usage_bytes with appropriate labels for
rss, heapTotal, heapUsed, external, and arrayBuffers), and stateless-related
counters (such as gitlab_mcp_stateless_requests_total,
gitlab_mcp_stateless_auth_from_header_total,
gitlab_mcp_stateless_auth_from_sealed_sid_total,
gitlab_mcp_stateless_auth_failures_total, and
gitlab_mcp_stateless_sid_rotated_total) to ensure comprehensive validation of
the output.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: 16b81d6e-3925-4c08-92c8-12d3e2d7d974

📥 Commits

Reviewing files that changed from the base of the PR and between c662a3d and 6b43341.

📒 Files selected for processing (3)
  • index.ts
  • server/metrics.ts
  • test/server/metrics.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Cursor Bugbot Autofix
  • GitHub Check: coverage
  • GitHub Check: test
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
🪛 ast-grep (0.43.0)
index.ts

[warning] 13092-13094: Avoid allowing access to unintended directories or files
Context: app.get("/metrics", (_req: Request, res: Response) => {
res.type("text/plain; version=0.0.4").send(formatPrometheusMetrics(getMetricsSnapshot()));
})
Note: Security best practice.

(path-traversal-typescript)

🔇 Additional comments (6)
server/metrics.ts (3)

1-27: LGTM!


29-31: LGTM!


33-116: LGTM!

index.ts (2)

202-202: LGTM!


13092-13094: LGTM!

Note: The static analysis warning about path-traversal is a false positive. This endpoint is a hardcoded route that returns formatted metrics without accepting any user input for file paths.

Source: Linters/SAST tools

test/server/metrics.test.ts (1)

6-8: LGTM!

Comment on lines +10 to +49
test("formats current MCP metrics", () => {
const body = formatPrometheusMetrics({
requestsProcessed: 2,
rejectedByRateLimit: 1,
rejectedByCapacity: 0,
authFailures: 3,
totalSessions: 4,
expiredSessions: 5,
activeSessions: 6,
authenticatedSessions: 7,
gitlabClientPool: { size: 8, maxSize: 100 },
uptime: 9,
memoryUsage: {
rss: 10,
heapTotal: 11,
heapUsed: 12,
external: 13,
arrayBuffers: 14,
},
statelessRequests: 15,
statelessAuthFromHeader: 16,
statelessAuthFromSealedSid: 17,
statelessAuthFailures: 18,
statelessSidRotated: 19,
config: {
maxSessions: 1000,
maxRequestsPerMinute: 60,
sessionTimeoutSeconds: 3600,
remoteAuthEnabled: true,
mcpOAuthEnabled: false,
statelessModeEnabled: false,
statelessRotationKey: false,
},
});

assert.match(body, /# HELP gitlab_mcp_requests_processed_total/);
assert.match(body, /gitlab_mcp_requests_processed_total 2/);
assert.match(body, /gitlab_mcp_requests_rejected_total\{reason="rate_limit"\} 1/);
assert.match(body, /gitlab_mcp_config_info\{[^}]*remote_auth_enabled="true"/);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

LGTM!

The test provides solid coverage of the core formatting logic. If you want to strengthen the test suite, consider adding assertions for additional metric lines (e.g., memory_usage_bytes labels, stateless counters) to ensure comprehensive validation of the Prometheus exposition format.

🤖 Prompt for 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.

In `@test/server/metrics.test.ts` around lines 10 - 49, The test "formats current
MCP metrics" currently has limited assertions and doesn't validate all the
metrics being generated. Add additional assert.match calls to verify the
Prometheus exposition format for memory usage metrics (such as
memory_usage_bytes with appropriate labels for rss, heapTotal, heapUsed,
external, and arrayBuffers), and stateless-related counters (such as
gitlab_mcp_stateless_requests_total,
gitlab_mcp_stateless_auth_from_header_total,
gitlab_mcp_stateless_auth_from_sealed_sid_total,
gitlab_mcp_stateless_auth_failures_total, and
gitlab_mcp_stateless_sid_rotated_total) to ensure comprehensive validation of
the output.

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.

2 participants