feat(custom-issuer-go): add health endpoints and OpenTelemetry metrics#91
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds metrics and health modules, instruments HTTP handlers with OpenTelemetry/Prometheus, exposes Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant HealthHandler
participant HealthService
participant IssuerService
participant KMSService
Client->>HealthHandler: GET /readyz
HealthHandler->>HealthService: CheckHealth(ctx)
HealthService->>IssuerService: HasValidationKeys()
IssuerService-->>HealthService: bool
HealthService->>KMSService: Ping(ctx with 3s timeout)
KMSService->>KMSService: SHA256("healthcheck") + KMS Sign
KMSService-->>HealthService: error?/ok
HealthService-->>HealthHandler: ReadyzResponse{Status, Checks}
HealthHandler-->>Client: 200 OK / 503 Service Unavailable (JSON)
sequenceDiagram
participant Client
participant IssuerHandler
participant IssuerService
participant IssuerMetrics
Client->>IssuerHandler: POST /issue
IssuerHandler->>IssuerHandler: record start time
IssuerHandler->>IssuerService: Issue(...)
alt success
IssuerService-->>IssuerHandler: token
IssuerHandler->>IssuerMetrics: TokensIssuedTotal.Add(1)
IssuerHandler->>IssuerMetrics: IssueDurationSeconds.Record(duration)
IssuerHandler-->>Client: 200 JSON token
else validation failure
IssuerHandler->>IssuerMetrics: TokensValidationFailedTotal.Add(1, reason)
IssuerHandler-->>Client: 4xx response
else service error
IssuerService-->>IssuerHandler: error
IssuerHandler->>IssuerMetrics: TokensFailedTotal.Add(1)
IssuerHandler-->>Client: error response
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/custom-issuer-go/modules/issuer/metrics/metrics.go (1)
15-18: Consider custom histogram buckets for better latency granularity.The histogram uses Prometheus default buckets (5ms to 10s), which may not provide optimal resolution for token issuance latency. If issuance typically completes in tens of milliseconds, most observations could cluster in the first bucket.
♻️ Optional: Add custom buckets tuned for expected latency
IssueDurationSeconds = prometheus.NewHistogram(prometheus.HistogramOpts{ Name: "custom_issuer_go_issue_duration_seconds", Help: "Duration of token issuance in seconds", + Buckets: []float64{0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5}, })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/custom-issuer-go/modules/issuer/metrics/metrics.go` around lines 15 - 18, The histogram IssueDurationSeconds currently uses Prometheus defaults; update the prometheus.NewHistogram call (prometheus.HistogramOpts for IssueDurationSeconds) to add a custom Buckets slice tuned to expected token issuance latency (e.g., tighter millisecond ranges such as 1ms, 2ms, 5ms, 10ms, 20ms, 50ms, 100ms, 200ms, 500ms, 1s) so observations don’t all fall into the first bucket—modify the HistogramOpts to include a Buckets: []float64{...} appropriate for tens-of-milliseconds latencies.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/custom-issuer-go/modules/issuer/metrics/metrics.go`:
- Around line 15-18: The histogram IssueDurationSeconds currently uses
Prometheus defaults; update the prometheus.NewHistogram call
(prometheus.HistogramOpts for IssueDurationSeconds) to add a custom Buckets
slice tuned to expected token issuance latency (e.g., tighter millisecond ranges
such as 1ms, 2ms, 5ms, 10ms, 20ms, 50ms, 100ms, 200ms, 500ms, 1s) so
observations don’t all fall into the first bucket—modify the HistogramOpts to
include a Buckets: []float64{...} appropriate for tens-of-milliseconds
latencies.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f9d4e5dc-309f-43b8-826b-444dde50c614
⛔ Files ignored due to path filters (1)
apps/custom-issuer-go/go.sumis excluded by!**/*.sum
📒 Files selected for processing (11)
apps/custom-issuer-go/go.modapps/custom-issuer-go/main.goapps/custom-issuer-go/modules/health/handler/handler.goapps/custom-issuer-go/modules/health/module.goapps/custom-issuer-go/modules/health/service/service.goapps/custom-issuer-go/modules/issuer/handler/issuer.goapps/custom-issuer-go/modules/issuer/metrics/metrics.goapps/custom-issuer-go/modules/issuer/module.goapps/custom-issuer-go/modules/issuer/service/service.goapps/custom-issuer-go/modules/kms/service/service.goapps/custom-issuer-go/modules/metrics/module.go
📜 Review details
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2026-03-05T14:31:30.013Z
Learnt from: kpitapeersyst
Repo: Peersyst/fast-auth PR: 78
File: apps/custom-issuer-go/go.mod:1-1
Timestamp: 2026-03-05T14:31:30.013Z
Learning: In the Peersyst/fast-auth repository, the Go module at `apps/custom-issuer-go/go.mod` intentionally declares `module github.com/peersyst/fast-auth/apps/custom-issuer` (without the `-go` suffix). The directory is named `custom-issuer-go` temporarily while the NestJS version of the app still exists; it will be renamed to `custom-issuer` once NestJS is removed. Do not flag this module path / directory name mismatch as an issue.
Applied to files:
apps/custom-issuer-go/main.goapps/custom-issuer-go/modules/issuer/module.goapps/custom-issuer-go/modules/issuer/handler/issuer.goapps/custom-issuer-go/modules/metrics/module.goapps/custom-issuer-go/modules/health/module.go
📚 Learning: 2026-03-05T14:37:07.020Z
Learnt from: kpitapeersyst
Repo: Peersyst/fast-auth PR: 78
File: apps/custom-issuer-go/server.go:24-24
Timestamp: 2026-03-05T14:37:07.020Z
Learning: In `apps/custom-issuer-go/server.go`, `middleware.RecoveryMiddleware` is intentionally applied without any prior redaction middleware. The maintainer has confirmed that no sensitive/private data (e.g., Authorization header values, `jwt`, or `signPayload` body fields) will be logged in practice, so raw header and body logging in `RecoveryMiddleware` is acceptable for this service.
Applied to files:
apps/custom-issuer-go/main.go
📚 Learning: 2026-03-11T15:50:07.064Z
Learnt from: CR
Repo: Peersyst/agent-skills PR: 0
File: skills/go-mistakes-performance/AGENTS.md:0-0
Timestamp: 2026-03-11T15:50:07.064Z
Learning: Applies to skills/go-mistakes-performance/**/*_test.go : Use net/http/httptest for testing HTTP handlers and clients without real network calls, and testing/iotest for I/O interface testing
Applied to files:
apps/custom-issuer-go/modules/issuer/handler/issuer.go
📚 Learning: 2026-03-05T14:31:22.787Z
Learnt from: kpitapeersyst
Repo: Peersyst/fast-auth PR: 78
File: apps/custom-issuer-go/go.mod:1-1
Timestamp: 2026-03-05T14:31:22.787Z
Learning: In apps/custom-issuer-go/go.mod, the module path is intentionally declared as 'github.com/peersyst/fast-auth/apps/custom-issuer' (no '-go' suffix) while the directory is named 'custom-issuer-go'. Do not flag this directory-name/module-path mismatch as an issue; this is a temporary alias during transition and will be renamed to 'custom-issuer' after NestJS is removed.
Applied to files:
apps/custom-issuer-go/go.mod
🔇 Additional comments (13)
apps/custom-issuer-go/modules/issuer/service/service.go (1)
85-88: LGTM!The
HasValidationKeys()method correctly delegates toGetKeys(), which is already thread-safe (usesRLockper context snippet 2). The implementation is concise and appropriate for the health check use case.apps/custom-issuer-go/modules/kms/service/service.go (1)
72-82: LGTM!The
Pingmethod correctly mirrors the productionSignJWTsigning pattern: it computes a SHA-256 digest and calls KMSSignwithMessageTypeDigestand the same RS256 algorithm. Discarding the signature and returning only the error is appropriate for a health probe.apps/custom-issuer-go/main.go (1)
27-28: LGTM!The module registration order correctly places
health.Moduleafterkms.Moduleandissuer.Module, which is required since the health module depends on services from both of those modules for itsValidationKeyCheckerandSignProberinterfaces.apps/custom-issuer-go/modules/issuer/module.go (1)
21-21: LGTM!Exporting the
Servicefield enables cross-module access, which is required for the health module to retrieve theIssuerServiceand callHasValidationKeys(). This follows the same pattern used by thekms.Module.Also applies to: 42-42, 63-63
apps/custom-issuer-go/modules/issuer/handler/issuer.go (1)
62-77: LGTM!The metrics instrumentation is well-placed:
- Duration is observed for all attempts (both success and failure), which provides visibility into total processing time regardless of outcome.
TokensFailedTotalis incremented on the error path before returning.TokensIssuedTotalis incremented only after successful issuance.apps/custom-issuer-go/modules/issuer/metrics/metrics.go (1)
21-23: Metric registration viainit()is acceptable but has trade-offs.Using
init()withMustRegisteris a common pattern. Note that it will panic at startup if metrics are registered twice (e.g., in tests that import this package multiple times). This is generally fine for production but worth being aware of for testing scenarios.apps/custom-issuer-go/modules/health/handler/handler.go (2)
26-28: LGTM!The
/livezendpoint correctly implements a minimal liveness probe by returning only200 OKwith no body, which is appropriate for Kubernetes liveness checks.
30-36: LGTM!The
/readyzendpoint correctly maps the health service status to appropriate HTTP codes:200 OKfor healthy and503 Service Unavailablefor degraded states. The JSON response body provides additional detail for debugging.apps/custom-issuer-go/go.mod (1)
9-9: Dependency version is current.github.com/prometheus/client_golang v1.23.2is the latest release and appropriately added to support the new metrics functionality.apps/custom-issuer-go/modules/metrics/module.go (1)
1-33: LGTM!The metrics module is well-structured, follows the established
AppModulepattern, and correctly exposes the Prometheus/metricsendpoint viapromhttp.Handler(). The compile-time interface check at line 11 is a good practice.apps/custom-issuer-go/modules/health/module.go (1)
1-59: LGTM!The health module correctly retrieves and type-asserts the
issuerandkmsmodules to access their services. The module initialization order inmain.go([kms, issuer, health, metrics]) combined with sequential initialization inNewAppModulesguarantees that both dependencies are fully initialized beforehealth.Initruns. Good error handling for both module retrieval and type assertion failures.apps/custom-issuer-go/modules/health/service/service.go (2)
8-44: LGTM!Clean type definitions with appropriate JSON tags. The interfaces (
ValidationKeyChecker,SignProber) provide good abstraction for dependency injection, making the service easily testable. The constructor follows idiomatic Go patterns.
46-73: Well-implemented health check with proper timeout handling.The
CheckHealthimplementation correctly:
- Uses a bounded 3-second timeout for the KMS ping to prevent hanging health checks
- Properly defers context cancellation to avoid leaks
- Aggregates dependency statuses to compute overall health
One minor consideration: the error message from
signProber.Pingis included directly in the response (line 59). This is generally acceptable for health endpoints used by operators, but verify this doesn't expose sensitive internal details in your environment.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/custom-issuer-go/modules/health/service/service.go (1)
51-63: Accept a parent context inCheckHealthto respect caller cancellation and shutdown signals.The current implementation uses
context.Background(), which prevents request cancellation and shutdown signals from affecting the health check. For request-driven operations like health probes, the parent context should be propagated to properly handle timeouts and graceful shutdown.Proposed refactor
-func (s *HealthService) CheckHealth() ReadyzResponse { +func (s *HealthService) CheckHealth(parent context.Context) ReadyzResponse { checks := map[string]DependencyResult{} + if parent == nil { + parent = context.Background() + } - ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + ctx, cancel := context.WithTimeout(parent, 3*time.Second) defer cancel()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/custom-issuer-go/modules/health/service/service.go` around lines 51 - 63, CheckHealth currently creates its own root context via context.Background() which prevents caller cancellation; change the method signature to accept a parent context (e.g., func (s *HealthService) CheckHealth(ctx context.Context) ReadyzResponse), propagate that context into the timeout call (use ctx, cancel := context.WithTimeout(ctx, 3*time.Second)) and pass the incoming ctx to signProber.Ping; update any callers of HealthService.CheckHealth to provide their context so cancellations and shutdown signals are respected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/custom-issuer-go/modules/health/service/service.go`:
- Around line 51-63: CheckHealth currently creates its own root context via
context.Background() which prevents caller cancellation; change the method
signature to accept a parent context (e.g., func (s *HealthService)
CheckHealth(ctx context.Context) ReadyzResponse), propagate that context into
the timeout call (use ctx, cancel := context.WithTimeout(ctx, 3*time.Second))
and pass the incoming ctx to signProber.Ping; update any callers of
HealthService.CheckHealth to provide their context so cancellations and shutdown
signals are respected.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: dfcea92d-f13d-4316-a8be-e5ee961584ec
📒 Files selected for processing (1)
apps/custom-issuer-go/modules/health/service/service.go
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: integration-packages / Build
- GitHub Check: build-base / Build
🔇 Additional comments (1)
apps/custom-issuer-go/modules/health/service/service.go (1)
73-81: Status aggregation logic is clear and correct.The final reduction from per-dependency checks to overall status is straightforward and returns deterministic readiness semantics.
…trics annotations
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@infra/chart/templates/custom-issuer-go.yaml`:
- Around line 5-8: The chart currently adds prometheus.io/port,
prometheus.io/scrape and prometheus.io/path annotations (using
customIssuerGo.service.targetPort) but provides no ServiceMonitor/PodMonitor or
Prometheus scrape configuration; add a ServiceMonitor CRD template that targets
the Service created by the custom-issuer-go chart (matching labels/selectors
used by the Service) and points to port {{
.Values.customIssuerGo.service.targetPort }} and path /metrics, or alternatively
update chart documentation/values to state that Prometheus must be configured to
honor prometheus.io annotations and provide an example Prometheus scrape config;
ensure the new template references the same labels/selectors and port name used
by the Service so the monitor will discover the endpoints.
🪄 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: 16aff788-2f5b-4214-8d41-e1c067339fd8
📒 Files selected for processing (1)
infra/chart/templates/custom-issuer-go.yaml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: integration-packages / Build
- GitHub Check: build-base / Build
🔇 Additional comments (1)
infra/chart/templates/custom-issuer-go.yaml (1)
59-72: Probe configuration aligns with health handlers.Good split:
livenessProbeon/livezandreadinessProbeon/readyzmatches the registered handlers and keeps dependency checks in readiness only.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/custom-issuer-go/modules/issuer/module.go (1)
36-43:⚠️ Potential issue | 🟠 MajorInitialize metrics before constructing the issuer service.
If
issuermetrics.Init()fails here,NewIssuerService(...)has already been created and its background refresh loop never gets stopped. Move metrics init ahead of service construction, or stopsvcon the error path. ``💡 Proposed fix
- svc, err := service.NewIssuerService(cfg, kmsMod.Service) - if err != nil { - return err - } - if err := issuermetrics.Init(); err != nil { return err } + + svc, err := service.NewIssuerService(cfg, kmsMod.Service) + if err != nil { + return err + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/custom-issuer-go/modules/issuer/module.go` around lines 36 - 43, Move issuermetrics.Init() to run before creating the issuer service or ensure svc is stopped if metrics init fails: either call issuermetrics.Init() prior to invoking service.NewIssuerService(cfg, kmsMod.Service), or after creating svc, on any error from issuermetrics.Init() call the service stop/close method on svc (e.g., svc.Stop() or svc.Close() depending on the service API) before returning the error so the background refresh loop started by NewIssuerService is cleaned up.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@apps/custom-issuer-go/modules/issuer/module.go`:
- Around line 36-43: Move issuermetrics.Init() to run before creating the issuer
service or ensure svc is stopped if metrics init fails: either call
issuermetrics.Init() prior to invoking service.NewIssuerService(cfg,
kmsMod.Service), or after creating svc, on any error from issuermetrics.Init()
call the service stop/close method on svc (e.g., svc.Stop() or svc.Close()
depending on the service API) before returning the error so the background
refresh loop started by NewIssuerService is cleaned up.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: cafc38e2-6537-4879-a95b-0ac0fff63240
⛔ Files ignored due to path filters (1)
apps/custom-issuer-go/go.sumis excluded by!**/*.sum
📒 Files selected for processing (10)
apps/custom-issuer-go/go.modapps/custom-issuer-go/main.goapps/custom-issuer-go/modules/common/modules/modules.goapps/custom-issuer-go/modules/health/handler/handler.goapps/custom-issuer-go/modules/health/service/service.goapps/custom-issuer-go/modules/issuer/handler/issuer.goapps/custom-issuer-go/modules/issuer/metrics/metrics.goapps/custom-issuer-go/modules/issuer/module.goapps/custom-issuer-go/modules/metrics/module.goapps/custom-issuer-go/server.go
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/custom-issuer-go/modules/health/handler/handler.go
- apps/custom-issuer-go/modules/health/service/service.go
📜 Review details
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2026-03-11T15:50:07.064Z
Learnt from: CR
Repo: Peersyst/agent-skills PR: 0
File: skills/go-mistakes-performance/AGENTS.md:0-0
Timestamp: 2026-03-11T15:50:07.064Z
Learning: Applies to skills/go-mistakes-performance/**/*_test.go : Use net/http/httptest for testing HTTP handlers and clients without real network calls, and testing/iotest for I/O interface testing
Applied to files:
apps/custom-issuer-go/modules/common/modules/modules.go
📚 Learning: 2026-03-05T14:37:07.020Z
Learnt from: kpitapeersyst
Repo: Peersyst/fast-auth PR: 78
File: apps/custom-issuer-go/server.go:24-24
Timestamp: 2026-03-05T14:37:07.020Z
Learning: In `apps/custom-issuer-go/server.go`, `middleware.RecoveryMiddleware` is intentionally applied without any prior redaction middleware. The maintainer has confirmed that no sensitive/private data (e.g., Authorization header values, `jwt`, or `signPayload` body fields) will be logged in practice, so raw header and body logging in `RecoveryMiddleware` is acceptable for this service.
Applied to files:
apps/custom-issuer-go/server.goapps/custom-issuer-go/main.goapps/custom-issuer-go/go.mod
📚 Learning: 2026-03-05T14:31:30.013Z
Learnt from: kpitapeersyst
Repo: Peersyst/fast-auth PR: 78
File: apps/custom-issuer-go/go.mod:1-1
Timestamp: 2026-03-05T14:31:30.013Z
Learning: In the Peersyst/fast-auth repository, the Go module at `apps/custom-issuer-go/go.mod` intentionally declares `module github.com/peersyst/fast-auth/apps/custom-issuer` (without the `-go` suffix). The directory is named `custom-issuer-go` temporarily while the NestJS version of the app still exists; it will be renamed to `custom-issuer` once NestJS is removed. Do not flag this module path / directory name mismatch as an issue.
Applied to files:
apps/custom-issuer-go/modules/issuer/module.goapps/custom-issuer-go/main.goapps/custom-issuer-go/modules/metrics/module.go
📚 Learning: 2026-03-05T14:31:22.787Z
Learnt from: kpitapeersyst
Repo: Peersyst/fast-auth PR: 78
File: apps/custom-issuer-go/go.mod:1-1
Timestamp: 2026-03-05T14:31:22.787Z
Learning: In apps/custom-issuer-go/go.mod, the module path is intentionally declared as 'github.com/peersyst/fast-auth/apps/custom-issuer' (no '-go' suffix) while the directory is named 'custom-issuer-go'. Do not flag this directory-name/module-path mismatch as an issue; this is a temporary alias during transition and will be renamed to 'custom-issuer' after NestJS is removed.
Applied to files:
apps/custom-issuer-go/go.mod
🔇 Additional comments (3)
apps/custom-issuer-go/main.go (1)
42-68: Good shutdown sequencing.Waiting on
donekeeps the final"server stopped"log aligned with actual server and module teardown completion.apps/custom-issuer-go/modules/issuer/handler/issuer.go (1)
67-70: Thenilcheck is sufficient; empty payloads are already rejected during JSON decoding.The
bytearray.Array.UnmarshalJSON()method explicitly returnsErrEmptywhen the input array is empty (line 8 of the bytearray implementation). This means an empty JSON array will fail thedecoder.Decode(&req)call (lines 33–36) and be caught as an "invalid_body" error before reaching the nil check at line 67. The nil check correctly handles only the case where the field is omitted or explicitly null. The proposed fix usinglen(req.SignPayload) == 0is unreachable because empty payloads cannot produce a non-nil value.> Likely an incorrect or invalid review comment.apps/custom-issuer-go/go.mod (1)
3-3: Build tooling is compatible.Container build tooling (docker/custom-issuer-go.Dockerfile) uses Go 1.26, which satisfies the go.mod requirement of 1.25.0 and is compatible with the stdlib patterns (Handle/HandleFunc with "GET /" syntax, errors.Join) used in this module.
feat(custom-issuer-go): add health endpoints and OpenTelemetry metrics
Changes
apps/custom-issuer-go
GET /livez- liveness probe, always returns 200 OKGET /readyz- readiness probe, checks validation keys are loaded and KMS signing capability (viaPing()with 3s timeout), returns 200 OK or 503 Service Unavailable with per-check JSON detailHasValidationKeys()method toIssuerServicePing(ctx)method toKMSServicefor health-check signing probeGET /metricsendpoint serving Prometheus-formatted metricscustom_issuer_go_tokens_issued_total(counter) - successfully issued tokenscustom_issuer_go_tokens_failed_total(counter) - failed token issuance attempts (auth/internal errors)custom_issuer_go_tokens_validation_failed_total(counter) - requests rejected due to validation errors, labeled byreason(invalid_body,jwt_empty,jwt_too_long,sign_payload_empty)custom_issuer_go_issue_duration_seconds(histogram) - token issuance duration with explicit buckets (10ms-1s)otelhttpinstrumentation on application routes (skips/metrics,/livez,/readyz)infra/chart
prometheus.io/scrape,/port,/path) to the servicelivenessProbeandreadinessProbeto the deployment targeting/livezand/readyzSummary by CodeRabbit
New Features
Metrics
Behavior
Chores