Skip to content

feat(metrics): add Prometheus metrics for infrastructure monitoring#914

Merged
ArtieReus merged 20 commits into
mainfrom
artie-infra-metrics
Jun 16, 2026
Merged

feat(metrics): add Prometheus metrics for infrastructure monitoring#914
ArtieReus merged 20 commits into
mainfrom
artie-infra-metrics

Conversation

@ArtieReus

@ArtieReus ArtieReus commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add Prometheus metrics collection to the aurora package for infrastructure monitoring. This implementation provides visibility into HTTP request performance, API usage patterns, and error rates.

The metrics are designed for production use with low cardinality and focus on backend API monitoring. A separate user behavior tracking layer will be implemented in the dashboard app in the future.

Changes Made

  • Added prom-client (v15.1.3) dependency for Prometheus metrics
  • Created httpMetricsCollector.ts Fastify plugin for metrics collection
  • Implemented /metrics endpoint for Prometheus scraping
  • Added intelligent route grouping to prevent cardinality explosion:
    • tRPC procedures: service/action format (e.g., compute/listImages)
    • Static assets: grouped by extension (*.js, *.css, *.png)
    • Vite dev paths: grouped as vite-dev
    • Dynamic IDs: replaced with :id placeholders
  • Added project_id label for per-project monitoring
  • Created comprehensive documentation with example Prometheus queries

Metrics Exposed

aurora_requests_total (Counter)

  • Labels: status_code, method, route, endpoint_type, project_id
  • Total HTTP requests by type and status

aurora_request_duration_seconds (Histogram)

  • Labels: status_code, method, route, endpoint_type, project_id
  • Request latency distribution

aurora_exceptions_total (Counter)

  1. Production-optimized: Handles both dev (noisy Vite paths) and prod (clean bundles) environments
  2. Low cardinality: ~50-100 tRPC procedures + ~10 asset types + grouped dev noise
  3. Per-project visibility: project_id label extracted from URL for multi-tenancy insights
  4. Infrastructure focus: Tracks backend API performance, not user behavior (separate concern)

Related Issues

N/A

Screenshots (if applicable)

Example metrics output:
aurora_requests_total{status_code="200",method="post",route="compute/listImages",endpoint_type="trpc",project_id="abc-123"} 245
aurora_request_duration_seconds_sum{status_code="200",method="post",route="compute/listImages",endpoint_type="trpc",project_id="abc-123"} 1.234

Testing Instructions

  1. pnpm i - Install dependencies (including prom-client)
  2. pnpm build - Build the aurora package
  3. Start the application and make some API requests
  4. curl http://localhost:3000/metrics - Verify metrics endpoint returns Prometheus format
  5. Check that metrics include proper labels and grouping

Manual Testing

  • Verify tRPC calls show as service/action format
  • Verify Vite dev paths are grouped as vite-dev
  • Verify project_id is extracted from /projects/{id}/... URLs
  • Verify static assets are grouped by extension

Checklist

  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have made corresponding changes to the documentation (if applicable).
  • My changes generate no new warnings or errors.

Documentation

  • Added packages/aurora/docs/0013_prometheus_metrics.md with implementation details
  • Included example Prometheus queries for common use cases
  • Documented label structure and design rationale

Summary by CodeRabbit

  • New Features

    • Added Prometheus HTTP metrics collection (request counter, duration histogram, exceptions counter)
    • Exposed a GET /metrics endpoint for Prometheus scraping
    • Metrics use normalized route labeling and include project_id where available (with /metrics excluded from counting)
  • Documentation

    • Added a Prometheus metrics implementation guide with label conventions, scrape config, and PromQL examples
  • Tests

    • Added a Fastify HTTP metrics collector test suite
  • Chores

    • Added prom-client dependency
    • Updated commit scope configuration to include metrics

Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
@ArtieReus ArtieReus requested a review from a team as a code owner June 12, 2026 13:08
@ArtieReus ArtieReus marked this pull request as draft June 12, 2026 13:08
@coderabbitai

coderabbitai Bot commented Jun 12, 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5d657c29-ea36-4119-9b4c-47a9e89922c1

📥 Commits

Reviewing files that changed from the base of the PR and between 013d6f3 and ab1613e.

📒 Files selected for processing (3)
  • .changeset/brave-eagles-rescue.md
  • packages/aurora/docs/0013_prometheus_metrics.md
  • packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts
✅ Files skipped from review due to trivial changes (2)
  • .changeset/brave-eagles-rescue.md
  • packages/aurora/docs/0013_prometheus_metrics.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts

📝 Walkthrough

Walkthrough

Adds a new AuroraHttpMetricsCollector Fastify plugin to the aurora package that records three Prometheus metric families (aurora_requests_total, aurora_request_duration_seconds, aurora_exceptions_total) with endpoint-type classification, route cardinality normalization, and project_id extraction. The plugin is wired into createServer with a dedicated Registry and a new GET /metrics endpoint. A Vitest suite, full implementation docs, and a "metrics" commitlint scope are also added.

Changes

Aurora Prometheus HTTP Metrics

Layer / File(s) Summary
Metrics plugin contract, hooks, and label extraction
packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts
Defines HttpMetricsCollectorOptions, Prometheus counter/histogram instances, onRequest/onResponse/onError Fastify hooks, endpoint-type classification (trpc, api, vite-dev, module, asset, spa), route normalization for each URL family, project_id extraction from tRPC input and SPA paths, and the fastify-plugin export with FastifyInstance.metricsRegistry type augmentation.
Server registration, plugin export, and dependency
packages/aurora/package.json, packages/aurora/src/server/aurora-fastify-plugins/index.ts, packages/aurora/src/server/server.ts
Adds prom-client to runtime dependencies, re-exports AuroraHttpMetricsCollector from the plugins index, and wires it into createServer with a dedicated Registry and a GET /metrics route returning collected metrics with the correct Content-Type.
Plugin unit tests
packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.test.ts
Vitest suite creates a standalone Fastify instance with the plugin; tests verify /metrics reachability, presence of all three metric families after traffic, label shape correctness, /metrics path exclusion from request counting, and aurora_exceptions_total definition.
Implementation docs and commitlint scope
packages/aurora/docs/0013_prometheus_metrics.md, .changeset/brave-eagles-rescue.md, commitlint.config.mjs
Adds a full guide covering metric design, label conventions, route-cardinality strategy, server integration, example output, Prometheus scrape config, and PromQL examples. Adds "metrics" to allowed commitlint scopes and includes a release changeset describing the feature.

Sequence Diagram

sequenceDiagram
  participant Fastify
  participant AuroraHttpMetricsCollector
  participant extractLabels
  participant PrometheusRegistry

  Fastify->>AuroraHttpMetricsCollector: onRequest (capture hrtime start)
  Fastify->>AuroraHttpMetricsCollector: onResponse (request complete)
  AuroraHttpMetricsCollector->>extractLabels: extractLabels(req, reply)
  extractLabels-->>AuroraHttpMetricsCollector: {status_code, method, route, endpoint_type, project_id}
  AuroraHttpMetricsCollector->>PrometheusRegistry: requestsTotal.inc(labels)
  AuroraHttpMetricsCollector->>PrometheusRegistry: requestDuration.observe(labels, duration)
  Fastify->>AuroraHttpMetricsCollector: onError (exception)
  AuroraHttpMetricsCollector->>PrometheusRegistry: exceptionsTotal.inc({exception_class})
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • andypf
  • taymoor89

Poem

🐇 Hop hop, the metrics flow,
Counters tick and histograms glow,
Each /projects/:id neatly tamed,
No cardinality explosion claimed.
A registry blooms in the Fastify den —
This rabbit counts requests, and counts again! 📊

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.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
Title check ✅ Passed The title accurately describes the main change: adding Prometheus metrics for infrastructure monitoring to the aurora package.
Description check ✅ Passed The PR description follows the template with all required sections: Summary, Changes Made, Related Issues, Testing Instructions, Checklist, and comprehensive documentation notes.
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 artie-infra-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.

@ArtieReus ArtieReus self-assigned this Jun 12, 2026
@ArtieReus ArtieReus changed the title feat(aurora): add Prometheus metrics for infrastructure monitoring feat(metrics): add Prometheus metrics for infrastructure monitoring Jun 12, 2026
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>

Copilot AI 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.

Pull request overview

Adds Prometheus metrics support to the aurora server to improve infrastructure monitoring (HTTP request volume, latency, and exceptions), including a /metrics scrape endpoint and route normalization to manage label cardinality.

Changes:

  • Add prom-client dependency and wire a dedicated Registry into the Fastify server.
  • Introduce a Fastify plugin that records request counters/histograms and exception counters with low-cardinality route labeling.
  • Add documentation describing exposed metrics, labels, and example PromQL queries.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
pnpm-lock.yaml Locks prom-client and its transitive dependencies.
packages/aurora/package.json Adds prom-client dependency.
packages/aurora/src/server/server.ts Registers the metrics collector and exposes GET /metrics.
packages/aurora/src/server/aurora-fastify-plugins/index.ts Exports the new metrics plugin.
packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts Implements request/latency/exception metrics with route grouping and labels.
packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.test.ts Adds tests for metrics exposure and basic labeling.
packages/aurora/docs/0013_prometheus_metrics.md Documents metrics design, labels, and example queries.
commitlint.config.mjs Adds metrics as an allowed commit scope.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/aurora/docs/0013_prometheus_metrics.md Outdated
Comment thread packages/aurora/src/server/server.ts
Comment thread packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts Outdated
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
1. Replace createServer() with plain Fastify instance to avoid booting
   the full server with @fastify/vite. This makes tests faster and more
   reliable by focusing on unit-testing the metrics plugin behavior.

2. Improve /metrics exclusion test to actually verify that /metrics
   route never appears in the collected metrics, not just checking the
   status code.
The previous note about server tests being excluded from vitest.config.ts
was misleading. Tests now run successfully using a plain Fastify instance
approach that avoids Vite startup issues.
The comment said Vite dev server paths are "excluded from metrics" but
they're actually recorded with endpoint_type="vite-dev" and route="vite-dev".
Updated comment to clarify they're grouped (not excluded) to prevent
cardinality explosion.
@ArtieReus ArtieReus marked this pull request as ready for review June 15, 2026 11:18

@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.

🧹 Nitpick comments (4)
packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts (4)

141-148: 💤 Low value

Consider explicit property check instead of truthy check for project_id.

The truthy check at line 141 means an explicit input.project_id = "" would fall through to the batch lookup logic, treating an empty string as "absent" rather than "explicitly set to empty". Since empty string is your sentinel for "not applicable" (line 109), this may be acceptable, but using "project_id" in input or input.hasOwnProperty("project_id") would be more explicit.

♻️ More explicit property presence check
-        if (input.project_id) {
+        if ("project_id" in input && input.project_id) {
           projectId = input.project_id
         } else if (typeof input === "object") {
🤖 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 `@packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts`
around lines 141 - 148, The condition checking input.project_id at line 141 uses
a truthy check which treats an explicitly set empty string (the sentinel value
for "not applicable") as falsy, causing it to fall through to the batch lookup
logic. Replace the truthy check with an explicit property presence check using
either "project_id" in input or input.hasOwnProperty("project_id") to properly
distinguish between a property that is not set versus one that is explicitly set
to an empty string.

216-224: ⚡ Quick win

Document that deeper SPA paths are intentionally truncated.

The special-case patterns for /projects and /accounts only preserve the top-level structure (e.g., /projects/:id/compute) and discard deeper segments like /instances or /instance-123. This is a deliberate cardinality-control decision but isn't immediately obvious. A brief comment would help future maintainers understand the trade-off.

📝 Suggested inline documentation
   // Pattern: /projects/:id/service
+  // Intentionally truncates deeper paths (e.g., /projects/abc/compute/instances → /projects/:id/compute)
+  // to limit label cardinality while preserving service-level granularity.
   if (segments[0] === "projects" && segments.length >= 3) {
     const service = segments[2] // compute, network, storage, services
     return `/projects/:id/${service}`
   }

   // Pattern: /accounts/:id
+  // Truncates sub-paths (e.g., /accounts/abc/settings → /accounts/:id) for cardinality control.
   if (segments[0] === "accounts" && segments.length >= 2) {
     return "/accounts/:id"
   }
🤖 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 `@packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts`
around lines 216 - 224, Add a comment to explain that the special-case patterns
for segments[0] === "projects" and segments[0] === "accounts" deliberately
truncate deeper path segments as a cardinality-control decision. The comment
should clarify that while deeper segments like /instances or /instance-123 are
discarded, this is intentional to limit the number of unique metric labels.
Place this comment before the if-block for projects to document this trade-off
between metric accuracy and cardinality management, so future maintainers
understand why only the top-level resource structure (e.g.,
/projects/:id/compute) is preserved.

119-119: 💤 Low value

Redundant query string removal.

The procedurePath is derived from urlPath (line 114), which already has the query string removed at line 105. This split on "?" is redundant but harmless.

♻️ Simplify by removing redundant operation
-      const cleanPath = procedurePath.split("?")[0]
+      const cleanPath = procedurePath
       const parts = cleanPath.split(".")
🤖 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 `@packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts` at
line 119, The `cleanPath` variable assignment at line 119 performs a redundant
split on "?" when the source `procedurePath` is derived from `urlPath` which has
already had its query string removed at line 105. Remove the redundant
`.split("?")[0]` operation and assign `cleanPath` directly to `procedurePath`
since it is already clean.

252-252: ⚡ Quick win

Inconsistent UUID validation between normalizeApiPath and normalizeSpaRoute.

normalizeSpaRoute (line 232) uses a strict RFC-compliant UUID regex, while normalizeApiPath (line 252) uses a loose pattern /^[0-9a-f-]{36}$/i that would match invalid strings like 36 consecutive hyphens. For consistency and correctness, both functions should use the same precise UUID pattern.

♻️ Use consistent UUID pattern
 function normalizeApiPath(path: string): string {
+  const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
   return path
     .split("/")
     .map((segment) => {
-      if (segment.match(/^\d+$/) || segment.match(/^[0-9a-f-]{36}$/i)) {
+      if (segment.match(/^\d+$/) || segment.match(UUID_REGEX)) {
         return ":id"
       }
       return segment
     })
     .join("/")
 }
🤖 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 `@packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts` at
line 252, The UUID validation pattern in normalizeApiPath uses a loose regex
`/^[0-9a-f-]{36}$/i` that can match invalid strings like 36 consecutive hyphens,
while normalizeSpaRoute already uses a strict RFC-compliant UUID pattern. Update
the UUID validation regex in the normalizeApiPath function to match the strict
pattern already implemented in normalizeSpaRoute to ensure consistency and
correctness across both functions.
🤖 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.

Nitpick comments:
In `@packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts`:
- Around line 141-148: The condition checking input.project_id at line 141 uses
a truthy check which treats an explicitly set empty string (the sentinel value
for "not applicable") as falsy, causing it to fall through to the batch lookup
logic. Replace the truthy check with an explicit property presence check using
either "project_id" in input or input.hasOwnProperty("project_id") to properly
distinguish between a property that is not set versus one that is explicitly set
to an empty string.
- Around line 216-224: Add a comment to explain that the special-case patterns
for segments[0] === "projects" and segments[0] === "accounts" deliberately
truncate deeper path segments as a cardinality-control decision. The comment
should clarify that while deeper segments like /instances or /instance-123 are
discarded, this is intentional to limit the number of unique metric labels.
Place this comment before the if-block for projects to document this trade-off
between metric accuracy and cardinality management, so future maintainers
understand why only the top-level resource structure (e.g.,
/projects/:id/compute) is preserved.
- Line 119: The `cleanPath` variable assignment at line 119 performs a redundant
split on "?" when the source `procedurePath` is derived from `urlPath` which has
already had its query string removed at line 105. Remove the redundant
`.split("?")[0]` operation and assign `cleanPath` directly to `procedurePath`
since it is already clean.
- Line 252: The UUID validation pattern in normalizeApiPath uses a loose regex
`/^[0-9a-f-]{36}$/i` that can match invalid strings like 36 consecutive hyphens,
while normalizeSpaRoute already uses a strict RFC-compliant UUID pattern. Update
the UUID validation regex in the normalizeApiPath function to match the strict
pattern already implemented in normalizeSpaRoute to ensure consistency and
correctness across both functions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3d010c92-e408-4fc1-9778-dde4dfb738e4

📥 Commits

Reviewing files that changed from the base of the PR and between 6bf0533 and 013d6f3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • commitlint.config.mjs
  • packages/aurora/docs/0013_prometheus_metrics.md
  • packages/aurora/package.json
  • packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.test.ts
  • packages/aurora/src/server/aurora-fastify-plugins/httpMetricsCollector.ts
  • packages/aurora/src/server/aurora-fastify-plugins/index.ts
  • packages/aurora/src/server/server.ts

hodanoori
hodanoori previously approved these changes Jun 15, 2026
TilmanHaupt
TilmanHaupt previously approved these changes Jun 16, 2026

@andypf andypf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Overall Review - Edge Cases & Error Handling ✅

Great implementation! I reviewed the error handling and edge cases. The good news: all error scenarios are handled defensively and won't impact the normal request flow. 🎉

Key Strengths

  • ✅ All metrics collection wrapped in try-catch
  • ✅ Defensive programming (checks for missing start time)
  • ✅ Graceful degradation on parse errors
  • ✅ No impact on application availability

Summary: Does it affect normal flow if errors happen? NO

The implementation follows the golden rule: "Metrics collection must never impact application availability"

I'll add some specific inline comments with minor suggestions for improvement (all optional, not critical).

@andypf andypf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

💡 Suggestion: Add debug logging for skipped metrics

When metricsStartTime is missing, the metric is silently skipped. Consider adding debug logging for visibility:

if (!request.metricsStartTime) {
  fastify.log.debug({ url: request.url }, 'Metrics start time missing, skipping metric collection')
  return
}

Impact: Better observability, helps debug if metrics are missing for certain requests.

Priority: Nice-to-have (not critical)

@andypf andypf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

⚠️ Note: High Cardinality Risk with project_id Label

The project_id label contains user-provided values. If you have thousands of projects, this creates high cardinality in Prometheus.

Impact:

  • Each unique label combination creates a new time series
  • Can affect Prometheus query performance and memory usage
  • Does NOT affect application availability ✅

Recommendations:

  1. Document expected cardinality (e.g., "supports up to 10,000 projects")
  2. Consider making project_id label optional via config
  3. Monitor Prometheus memory usage in production

Is this a blocker? No, but worth documenting and monitoring.

@andypf andypf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

📊 Observation: Exception Tracking Coverage

The onError hook only fires for unhandled errors that reach Fastify's error handler. It won't catch:

  • Errors caught and handled within route handlers
  • Errors transformed to HTTP 5xx responses without throwing
  • Silent failures in middleware

Impact: ✅ Does NOT affect normal flow, but exception metrics may be incomplete.

Recommendation:
For complete error visibility, also monitor status_code=~"5.." in the aurora_requests_total metric. Example Prometheus query:

rate(aurora_requests_total{status_code=~"5.."}[5m])

Optional Enhancement: Add a separate counter for 5xx responses:

if (reply.statusCode >= 500) {
  serverErrorsTotal.inc({ status_code: reply.statusCode.toString() })
}

This is optional - current implementation is fine!

@ArtieReus

ArtieReus commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator Author

monitoring

This should be fine. This is the setup we have already in Elektra. If it turns to a problem then we skip the project.
It is already documented

📊 Observation: Exception Tracking Coverage

The onError hook only fires for unhandled errors that reach Fastify's error handler. It won't catch:

  • Errors caught and handled within route handlers
  • Errors transformed to HTTP 5xx responses without throwing
  • Silent failures in middleware

Impact: ✅ Does NOT affect normal flow, but exception metrics may be incomplete.

Recommendation: For complete error visibility, also monitor status_code=~"5.." in the aurora_requests_total metric. Example Prometheus query:

rate(aurora_requests_total{status_code=~"5.."}[5m])

Optional Enhancement: Add a separate counter for 5xx responses:

if (reply.statusCode >= 500) {
  serverErrorsTotal.inc({ status_code: reply.statusCode.toString() })
}

This is optional - current implementation is fine!

Only tracks unhandled exceptions that reach Fastify's error handler. Errors caught and handled in route handlers (e.g., tRPC errors) are tracked via status_code="5xx" in the request metrics. Added a comment to the Documentation.

Add debug log when metricsStartTime is missing to improve observability
and help diagnose edge cases where the onRequest hook didn't fire.

Uses structured logging consistent with existing error logging patterns.
@ArtieReus ArtieReus dismissed stale reviews from hodanoori and TilmanHaupt via 8a97a71 June 16, 2026 09:24
andypf
andypf previously approved these changes Jun 16, 2026
Signed-off-by: Arturo Reuschenbach Puncernau <reuschenbach@gmail.com>
@ArtieReus ArtieReus merged commit fe78936 into main Jun 16, 2026
22 checks passed
@ArtieReus ArtieReus deleted the artie-infra-metrics branch June 16, 2026 11:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants