-
Notifications
You must be signed in to change notification settings - Fork 4
Logging and Error management
As microservices communicate with each others, debugging often requires more than a single stack trace. To ensure reliability of our project, we can rely on
- resiliency patterns to handle partial system failure (db timeout, downstream service crash, ...)
- centralization of error handling
- structured observability : generating logs that can be easily processed by ELK stack to query, filter and correlate events
-
pino-prettycan be installed as dev-dependency : generates human readable logs -
@transcendence/coreshared package
Provides standardized types and constants:
-
AppErrorclass andErrorDefinitiontype - `ERR_DEFS catalog with predefined ErrorDefinition
-
LOG_RESOURCE,LOG_ACTION,LOG_EVENTS,LOG_REASONS` constants -
LogContexttype for structured logging
Tip
If you modify core package, run make build:core (if in VSCode CTRL+P Restart TS Server to update Intellisence)
- retry : automatically retry transient (unlikely to last) failures with exponential backoff. Example : failed HTTP call to the API exposed by a downstream service
- circuit breaker : fail fast immediately if an error is very likely to happen. Example : external API, DB connection
- bulkhead : isolate a component or resource (database, network, process, ...) to prevent cascading failures
- fallback : return a default value when a request fails. Example : placeholder image
principles
-
fail fast : don't try / catch in service layers : let errors bubble up
-
single source of truth : log and respond to errors at boundaries (controller and gateway)
-
structured errors: Use
AppErrorwith consistent metadata for observability and proper info to generate HTTP reply -
separation of concerns: services throw, handlers log and respond
-
in case of need handle Fastify Errors : for instance validation erros due to invalid Zod Schemas
- have a
src/config/logger-config.tsand use inindex.tswhen declaring Fastify instance. It will define- default log level
- which fields should be redacted and how (sensitive fields)
- how to serialize errors
Note
pino is the default Fastify logger and is fast
| Level | Whem | What to log |
|---|---|---|
| trace | normal flow tracking | requests, query, replies |
| debug | temporary | variables, iterations |
| info | normal operation | service started, user logged in |
| warning | handled issues | user originated errors (4xx) handled by the app, retry attemps, fallback |
| error | system failure | unhandled exceptions, db errors |
| fatal | service shutdown |
-
LogContext: we can have derived types according to events - use constants provided by core package (
LOG_RESOURCE,LOG_ACTION,LOG_EVENTS,LOG_REASONS)
- log incoming in
onRequest - log completed in
onResponse
| โ Do | โ Don't |
|---|---|
Log in JSON: Use structured logs (JSON) to allow fields like traceId, event, and serviceName to be indexed by ELK/observability tools. |
Log plain text: Avoid console.log("Error: " + err). This creates unparseable text blobs that hinder debugging in distributed systems. |
Centralize Handling: Throw specific errors (e.g., AppError) in services and handle them only in the Global Error Handler or Gateway. |
Log and Throw: catch (e) { logger.error(e); throw e; }. This creates duplicate logs (one in the service, one in the controller), clogging the system. |
Use Correlation IDs: Ensure every request carries a request-id. Fastify handles this automatically; ensure it is propagated to downstream microservices. |
Swallow Errors: catch (e) { return null; }. This hides the root cause of failures, making "silent failures" impossible to debug. |
Differentiate Levels: Use WARN for handled user errors (400s) and ERROR for unexpected system faults (500s) that require developer intervention. |
Leak Sensitive Data: Never log PII (Personally Identifiable Information), passwords, or tokens in the details or context fields. |
| Preserve error causes: Have full stack trace for debugging | Leak stack traces to clients: insecure and confusing |
| *Redact sensitive data: Prevent PII leaks | - |
| Type | Resource | Notes |
|---|---|---|
| ๐ | Designing Microservices for Failure | Comprehensive guide on patterns like Circuit Breakers, Retries, and Bulkheads. |
| ๐ | Fastify Error Handling | Official documentation on setErrorHandler and error encapsulation. |
| ๐ฆ | fastify-circuit-breaker | Community plugin to implement the circuit breaker pattern in Fastify routes. |
| ๐ฆ | fastify-helmet | Security headers |
| ๐ฅ | Fastify - Error Handling | Practical guide to implementing custom error classes and handlers. |
- Gateway Service - API Gateway & JWT validation
- Auth Service - Authentication & 2FA/TOTP
- AI Service - AI opponent
- API Documentation - OpenAPI/Swagger
- DB Schema - Databases
- Fastify - Web framework
- Prisma - ORM
- WebSockets - Real-time communication
- Restful API - API standards
- React - UI library
- CSS - Styling
- Tailwind - CSS framework
- Accessibility - WCAG compliance
- TypeScript - Language
- Zod - Schema validation
- Nginx - Reverse proxy
- Logging and Error management - Observability
- OAuth 2.0 - Authentication flows
- Two-factor authentication - 2FA/TOTP
- Avalanche - Blockchain network
- Hardhat - Development framework
- Solidity - Smart contracts language
- Open Zeppelin - Security standards
- ESLint - Linting
- Vitest - Testing
- GitHub Actions - CI/CD
- Husky, Commit lints and git hooks - Git hooks
- ELK - Logging stack
๐ Page model