Skip to content

Logging and Error management

Francois edited this page Jan 4, 2026 · 1 revision

Logging and Error management

Presentation

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

Setup for a microservice

  • pino-pretty can be installed as dev-dependency : generates human readable logs
  • @transcendence/core shared package

Provides standardized types and constants:

  • AppError class and ErrorDefinition type
  • `ERR_DEFS catalog with predefined ErrorDefinition
  • LOG_RESOURCE, LOG_ACTION, LOG_EVENTS, LOG_REASONS` constants
  • LogContext type for structured logging

Tip

If you modify core package, run make build:core (if in VSCode CTRL+P Restart TS Server to update Intellisence)

Resiliency patterns

  • 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

Leverage on Fastiy Global error handler

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 AppError with 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

Leverage on Fastify logger and harmonize its configuration

  • have a src/config/logger-config.ts and use in index.ts when 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

Logging levels

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

Harmonize log structure

  • LogContext : we can have derived types according to events
  • use constants provided by core package (LOG_RESOURCE, LOG_ACTION, LOG_EVENTS, LOG_REASONS)

Leverage on fastify hooks

  • log incoming in onRequest
  • log completed in onResponse

Do's & Don'ts

โœ… 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 -

Resources

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.

๐Ÿ—๏ธ Architecture

๐ŸŒ Web Technologies

Backend

Frontend

๐Ÿ”ง Core Technologies

๐Ÿ” Security

โ›“๏ธ Blockchain

๐Ÿ› ๏ธ Dev Tools & Quality


๐Ÿ“ Page model

Clone this wiki locally