Logs should answer what happened, where, and for which request without exposing sensitive data.
Course navigationPhase 30⌄
Logging & Observability
Make production behavior observable with structured logs, request correlation, error monitoring, metrics, traces/signals, and actionable alerts.
Phase outcome and project increment
Learning outcome
Make production behavior observable with structured logs, request correlation, error monitoring, metrics, traces/signals, and actionable alerts.
Concrete deliverable
Observability layer connecting Next.js/API errors and request IDs to structured logs and monitoring releases.
Principles to keep while coding
Use request or correlation identifiers to connect events across application boundaries.
Metrics reveal system trends while traces and structured logs help explain individual failures.
Alert on user-impacting symptoms and actionable conditions rather than every noisy internal event.
Guided phase lab
Do these in order. Each step should end with evidence before the next one starts.
- 01
Define the minimum structured fields every API request/error log should carry.
- 02
Generate or propagate a request ID and return it so support can correlate client reports.
- 03
Redact secrets and PII deliberately before adding rich context.
- 04
Integrate error monitoring for both Next.js and NestJS and tag releases by commit SHA.
- 05
Add a few meaningful application/HTTP/database signals rather than hundreds of vanity metrics.
- 06
Simulate a production-style error and walk from user-visible request ID to logs/monitoring evidence.
Failures you should know how to diagnose
console.log strings with no searchable structure
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
Tokens/passwords in logs
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
Alerts on every exception rather than user-impacting symptoms
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
No release/environment tags so errors cannot be tied to deployments
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
Lessons
The source chapters come first. Every phase now ends with a guided build, a debugging workshop, and an independent challenge so reading turns into transferable skill.
Observability Mental Model
Observability Mental Model Full Stack Developer 2026 Complete - TaskFlow Monitoring asks known questions such as “is error rate above 5%?” Observability is broader: it lets engineers investi
Structured Logging Log Levels and Events
Structured Logging, Levels, and Events Full Stack Developer 2026 Complete - TaskFlow NestJS 12 can emit JSON directly through ConsoleLogger and treats plain objects passed after the message
Correlation IDs and Request Context
Correlation IDs and Request Context Full Stack Developer 2026 Complete - TaskFlow TaskFlow already uses Fastify request.id. Phase 30 formalizes it as correlation context and returns x-reques
Request Logging and Latency Metrics
Request Logging and Latency Metrics Full Stack Developer 2026 Complete - TaskFlow A single request-completion record is more valuable than several disconnected “started / controller entered
Health Liveness Readiness and Graceful Shutdown
Health, Liveness, Readiness, and Graceful Shutdown Full Stack Developer 2026 Complete - TaskFlow A process can be alive but not ready to serve real traffic. TaskFlow separates those concepts
Sentry Error Monitoring for NestJS and Next.js
Sentry Error Monitoring for NestJS and Next.js Full Stack Developer 2026 Complete - TaskFlow Sentry complements the public error envelope from Phase 13. Clients still receive safe error resp
Traces and OpenTelemetry Concepts
Traces and OpenTelemetry Concepts Full Stack Developer 2026 Complete - TaskFlow A trace models one operation as related spans. For TaskFlow, an HTTP request may contain spans for authorizati
Database Realtime Storage and Background Work Observability
Database, Realtime, Storage, and Background Work Full Stack Developer 2026 Complete - TaskFlow Request logs alone are not enough once TaskFlow performs database, Realtime, Storage, and later
Dashboards SLOs and Alert Design
Dashboards, SLOs, and Alert Design Full Stack Developer 2026 Complete - TaskFlow A dashboard should answer an operational question. A good first TaskFlow dashboard focuses on traffic, errors
Privacy Redaction and Telemetry Cost
Privacy, Redaction, and Telemetry Cost Full Stack Developer 2026 Complete - TaskFlow Telemetry is a data system. Treat it with the same care as application data. Every log field, trace attri
Incident Debugging Runbooks and Testing
Incident Debugging, Runbooks, and Testing Full Stack Developer 2026 Complete - TaskFlow Observability becomes valuable during an incident only if engineers know how to use it. Phase 30 adds
Hands On Lab and Phase Exit
Hands-On Lab and Phase Exit Full Stack Developer 2026 Complete - TaskFlow Level 1 - Follow • Enable JSON logging in production mode. • Add a request completion interceptor/middleware with re
Guided Build Lab
Purpose Make production behavior observable with structured logs, request correlation, error monitoring, metrics, traces/signals, and actionable alerts.
Debugging Workshop
Goal Learn to diagnose this phase's failures systematically instead of reinstalling packages, changing random configuration, or copying a fix without understanding it.
Phase Synthesis & Independent Challenge
Mission Rebuild the capability of Phase 30 without following the exact code line-by-line. The goal is transfer: can you use the ideas when the variable names, UI, or route shape changes?
Mastery Capstone Lab
Integrate Phase 30 without following a transcript.
Exercises that increase independence
Define the minimum structured fields every API request/error log should carry.
Redact secrets and PII deliberately before adding rich context.
reproduce and diagnose — console.log strings with no searchable structure.
deliver Observability layer connecting Next.js/API errors and request IDs to structured logs and monitoring releases.
Can correlate one request across layers and Can log useful context safely.
Do not leave the phase only because you reached the bottom
Phase exit criteria
Scenario and concept quiz
These questions test engineering choices rather than whether you remember a lesson title.
Reference files
Attempt the work first. Use snapshots to compare a checkpoint, not as a substitute for understanding.
reference/TaskFlow_Observability_Snapshot/INCIDENT_RUNBOOK.md
# TaskFlow incident runbook 1. Confirm symptom, start time, affected route/workflow, environment, release. 2. Inspect request/error rate and p95/p99 latency. 3. Select a representative request/error and correlate by requestId. 4. Use traces/logs to isolate the slow/failing boundary. 5. Mitigate first; verify recovery with metrics and health checks. 6. Create follow-up action for root cause, missing telemetry, and test coverage.
reference/TaskFlow_Observability_Snapshot/OBSERVABILITY_FIELD_CATALOG.md
# Observability field catalog Allowed common fields: requestId, event, context, method, normalizedRoute, statusCode, durationMs, environment, release, workspaceId (logs/traces only where needed), internal userId (policy-dependent). Never record: Authorization headers, cookies, access/refresh tokens, passwords, service-role keys, DATABASE_URL, signed upload tokens, raw uploaded content. Metric labels should remain low-cardinality: method, normalized route, status class, environment.
reference/TaskFlow_Observability_Snapshot/README.md
# TaskFlow Phase 30 observability snapshot Study snapshot only. Merge into the evolving TaskFlow repository intentionally. Do not copy secrets into examples. The design keeps NestJS structured logging, Terminus health checks, Sentry error/performance monitoring, and vendor-neutral OpenTelemetry concepts separated by responsibility.
reference/TaskFlow_Observability_Snapshot/SOURCES.md
# Official references - https://docs.nestjs.com/techniques/logger - https://docs.nestjs.com/recipes/terminus - https://opentelemetry.io/docs/concepts/signals/ - https://opentelemetry.io/docs/concepts/signals/metrics/ - https://prometheus.io/docs/practices/histograms/ - https://www.npmjs.com/package/@sentry/nestjs - https://www.npmjs.com/package/@sentry/nextjs - https://www.npmjs.com/package/@nestjs/terminus - https://www.npmjs.com/package/@opentelemetry/api
reference/TaskFlow_Observability_Snapshot/VERSION_LOCK.md
# Phase 30 version lock - @nestjs/terminus 12.0.0 - @sentry/nestjs 10.75.0 - @sentry/nextjs 10.75.0 - @opentelemetry/api 1.9.1 - @opentelemetry/sdk-node 0.222.0 is discussed but not hard-locked as a production dependency because the package describes itself as experimental.
reference/TaskFlow_Observability_Snapshot/apps/api/package.phase30.json
{
"dependencies": {
"@nestjs/terminus": "12.0.0",
"@sentry/nestjs": "10.75.0",
"@opentelemetry/api": "1.9.1"
}
}reference/TaskFlow_Observability_Snapshot/apps/api/src/health/health.controller.ts
import { Controller, Get } from '@nestjs/common';
import { HealthCheck, HealthCheckService, PrismaHealthIndicator } from '@nestjs/terminus';
import { PrismaService } from '../prisma/prisma.service';
@Controller('health')
export class HealthController {
constructor(
private readonly health: HealthCheckService,
private readonly prismaHealth: PrismaHealthIndicator,
private readonly prisma: PrismaService,
) {}
@Get('live')
live() { return { status: 'ok' }; }
@Get('ready')
@HealthCheck()
ready() {
return this.health.check([
() => this.prismaHealth.pingCheck('database', this.prisma),reference/TaskFlow_Observability_Snapshot/apps/api/src/instrument.ts
import * as Sentry from '@sentry/nestjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: Number(process.env.SENTRY_TRACES_SAMPLE_RATE ?? '0.1'),
});reference/TaskFlow_Observability_Snapshot/apps/api/src/main.observability-example.ts
import { ConsoleLogger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import './instrument';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: new ConsoleLogger({
json: process.env.NODE_ENV === 'production',
}),
});
app.enableShutdownHooks();
await app.listen(process.env.PORT ?? 3001);
}
void bootstrap();reference/TaskFlow_Observability_Snapshot/apps/api/src/observability/request-logging.interceptor.ts
import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common';
import type { FastifyReply, FastifyRequest } from 'fastify';
import { Observable, finalize } from 'rxjs';
@Injectable()
export class RequestLoggingInterceptor implements NestInterceptor {
private readonly logger = new Logger('HTTP');
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
const http = context.switchToHttp();
const request = http.getRequest<FastifyRequest>();
const reply = http.getResponse<FastifyReply>();
const started = performance.now();
reply.header('x-request-id', request.id);
return next.handle().pipe(
finalize(() => {
this.logger.log('HTTP request completed', {
requestId: request.id,reference/TaskFlow_Observability_Snapshot/apps/web/package.phase30.json
{
"dependencies": {
"@sentry/nextjs": "10.75.0"
}
}reference/TaskFlow_Observability_Snapshot/tests/observability-test-matrix.md
# Observability verification matrix - x-request-id returned on API responses. - request completion log contains requestId, normalized route, status, duration. - logs contain no Authorization/Cookie/secret values. - /health/live remains 200 while process is healthy. - /health/ready fails when test PostgreSQL is unavailable. - synthetic error appears in non-production Sentry with requestId. - p95/p99 latency can be derived from histogram/distribution telemetry. - metrics contain no userId/taskId/requestId labels. - alert test reaches the intended channel and points to a runbook.