-
Notifications
You must be signed in to change notification settings - Fork 77
chore(observability): adds OpenTelemetry metrics for wallet balance reload check job #2323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…eload check job Introduce instrumentation service to track job health and user issues: - Job execution metrics (duration, success/failure) - Reload actions (triggered, skipped, failures) - Error tracking (validation, scheduling) - Cost and amount distributions (histograms) Metrics are Prometheus-compatible for dashboard visualization and alerting.
WalkthroughThis pull request introduces a new OpenTelemetry-based instrumentation service for the wallet balance reload check flow. It establishes a centralized MetricsService for metric creation, then uses it to define counters, histograms, and logging for tracking job execution, reload events, validation errors, and scheduling failures. The instrumentation service is integrated into the WalletBalanceReloadCheckHandler, replacing direct logging calls. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.spec.ts (2)
358-365: Consider adding coverage forrecordReloadFailedon payment intent errorsYou already mock
recordReloadFailedbut no test exercises the branch wherestripeService.createPaymentIntentrejects; adding a test that forces this failure and asserts the corresponding instrumentation call would close the last major instrumentation gap for the reload flow.
10-13: Optional: AlignJobPayloadimport withJobMetafor consistency
JobMetais imported from@src/corewhileJobPayloadcomes from a relative"../../../core"path; switchingJobPayloadto also use@src/corewould make the imports more consistent and easier to maintain.apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.ts (1)
60-78: Optional: Include job id in job execution instrumentation for easier correlationIf you find yourself debugging individual jobs, consider extending
recordJobExecution(and its metric/log payload) to also receivejob.idin addition touserId, so you can more easily correlate metrics/logs back to the underlying queue job.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check-instrumentation.service.ts(1 hunks)apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.spec.ts(12 hunks)apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.ts(5 hunks)apps/api/src/core/services/index.ts(1 hunks)apps/api/src/core/services/metrics/metrics.service.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/api/src/core/services/index.tsapps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.spec.tsapps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.tsapps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check-instrumentation.service.tsapps/api/src/core/services/metrics/metrics.service.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.spec.ts
🧬 Code graph analysis (3)
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.spec.ts (2)
packages/logging/src/services/logger/logger.service.ts (1)
error(141-143)apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.ts (1)
job(81-99)
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.ts (3)
apps/api/src/core/services/job-queue/job-queue.service.ts (2)
JobPayload(241-241)JobMeta(250-250)apps/api/src/billing/events/wallet-balance-reload-check.ts (1)
WalletBalanceReloadCheck(5-15)packages/logging/src/services/logger/logger.service.ts (1)
error(141-143)
apps/api/src/core/services/metrics/metrics.service.ts (1)
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check-instrumentation.service.ts (1)
singleton(7-154)
⏰ 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). (3)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
apps/api/src/core/services/index.ts (1)
3-3: Re-exportingmetrics.servicevia core services index looks correctThis cleanly exposes
MetricsServiceand related types through the core barrel without altering existing exports.apps/api/src/core/services/metrics/metrics.service.ts (1)
4-61: MetricsService abstraction is simple, typed, and cohesive
MetricOptionsand the three factory methods provide a clear, minimal facade over the meter API, andgetMeterkeeps call sites consistent; no issues spotted.apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.spec.ts (1)
34-85: Instrumentation expectations in handler tests are aligned and realisticThe updated tests correctly verify calls to
recordReloadTriggered,recordReloadSkipped,recordSchedulingError, andrecordValidationErrorwith arguments that mirror the handler’s logic (includingwalletAddress,balance, andcostUntilTargetDateInFiat), giving good coverage of the new observability behavior.Also applies to: 121-171, 197-213, 215-307
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.ts (3)
60-78: Job execution instrumentation inhandleis robustWrapping the core logic in
try/finallyand updating asuccessflag ensuresrecordJobExecutionalways fires, distinguishing successful runs from both validation failures and thrown errors, which is exactly what you want for job health metrics.
167-205: Reload decision logic and instrumentation are consistent and side‑effect safeThe zero‑cost and sufficient‑balance branches (Lines 179–187) now exit early after calling
recordReloadSkipped, and the reload amount is computed only when needed usingMath.max(...)with the configured minimum; success and failure of the payment intent are cleanly distinguished viarecordReloadTriggeredandrecordReloadFailed, preserving behavior while giving richer telemetry.
207-217: Scheduling error handling is correctly instrumented while preserving failure semantics
#scheduleNextChecknow records scheduling failures viarecordSchedulingErrorbefore rethrowing, so metrics/logs capture the issue without changing the fact that the handler still fails the job on scheduling errors.apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check-instrumentation.service.ts (2)
7-68: Metric setup in the instrumentation service is coherent and well‑scopedInitializing a dedicated meter plus clearly named counters/histograms for executions, reload behavior, validation, and scheduling gives a good, self‑contained observability surface for this job, and keeps metric concerns out of the handler.
70-153: Record methods correctly capture key dimensions and avoid edge‑case pitfallsThe record methods apply sensible attributes (
status,reason,error_type), reuse shared histograms (reloadAmounts,balanceCoverageRatio,projectedCost), and defensively skip balance‑coverage calculations when cost is zero, while emitting structured logs with the provided context—this all looks solid.
Codecov Report❌ Patch coverage is ❌ Your patch status has failed because the patch coverage (35.29%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #2323 +/- ##
==========================================
- Coverage 50.86% 50.52% -0.35%
==========================================
Files 1050 1037 -13
Lines 28727 28195 -532
Branches 6349 6255 -94
==========================================
- Hits 14612 14245 -367
+ Misses 13854 13698 -156
+ Partials 261 252 -9
*This pull request uses carry forward flags. Click here to find out more.
🚀 New features to boost your workflow:
|
Introduce instrumentation service to track job health and user issues:
Metrics are Prometheus-compatible for dashboard visualization and alerting.
refs #1779
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.