En un sistema monolític senzill n'hi havia prou amb revisar un fitxer de log quan alguna cosa fallava. Però en arquitectures modernes (microserveis, contenidors efímers, centenars d'instàncies) una sola petició pot travessar deu serveis diferents. Com saps què va passar realment? La resposta és l'observabilitat: la capacitat d'entendre l'estat intern d'un sistema a partir dels senyals que emet cap a l'exterior. No es tracta només de monitorar (saber si alguna cosa va malament), sinó de poder preguntar al sistema per què va malament, fins i tot davant de problemes que no havies previst. En aquesta lliçó dominaràs els tres pilars de l'observabilitat (logs, mètriques i traces), els formats i metodologies que els fan útils (logs estructurats, RED, USE), la traçabilitat distribuïda amb correlació, i l'estàndard que ho unifica tot: OpenTelemetry.

Contingut

  1. Els tres pilars de l'observabilitat
  2. Logging estructurat
  3. Mètriques: les metodologies RED i USE
  4. Traces distribuïdes i correlació
  5. OpenTelemetry: l'estàndard unificador
  6. Errors habituals i consells
  7. Exercicis

  1. Els tres pilars de l'observabilitat

L'observabilitat es basa en tres tipus de senyals (telemetry signals) complementaris:

Pilar Què respon Naturalesa Exemple
Logs Què va passar exactament? Esdeveniments discrets amb detall "Error en cobrar la comanda 123: targeta rebutjada"
Mètriques Quant/com de bé va? Nombres agregats en el temps "Latència p95 = 240 ms; 1.200 req/s"
Traces Per on va passar la petició? El recorregut d'una petició entre serveis "API -> Comandes -> Pagament -> Banc (380 ms total)"

Són complementaris: les mètriques t'avisen que alguna cosa va malament (la latència ha pujat), les traces et diuen on (quin servei és lent), i els logs et diuen per què (quin error concret s'ha produït). Usats junts, et permeten passar de "el sistema va lent" a "la causa exacta" en minuts.

  1. Logging estructurat

El logging tradicional escriu text lliure, fàcil de llegir per a un humà però molt difícil de processar per una màquina:

2026-06-30 10:15:32 ERROR L'usuari ana no ha pogut pagar la comanda 123 (targeta rebutjada)

Com busques "tots els errors de la comanda 123" entre milions de línies així? Impossible de manera fiable. La solució és el logging estructurat: emetre els logs com a dades (normalment JSON) amb camps ben definits.

{
  "timestamp": "2026-06-30T10:15:32Z",
  "level": "ERROR",
  "service": "pagos",
  "message": "Pagament rebutjat",
  "trace_id": "abc123",
  "order_id": 123,
  "user_id": "ana",
  "reason": "card_declined"
}

Cada camp és consultable: ara pots filtrar per order_id = 123, agrupar per reason, o seguir el trace_id per enllaçar amb la traça completa (ho veurem més endavant). Això converteix els logs en dades analitzables a escala.

// Logging estructurat amb SLF4J + MDC (Mapped Diagnostic Context)
MDC.put("trace_id", traceId);     // Afegeix context a TOTS els logs d'aquest fil
MDC.put("order_id", "123");
log.error("Pagament rebutjat", kv("reason", "card_declined"));
MDC.clear();                       // Netejar en acabar per no contaminar altres fils

El MDC (Mapped Diagnostic Context) permet "adjuntar" camps de context (com el trace_id) que s'inclouran automàticament a cada línia de log emesa en aquell fil, sense haver de passar-los a mà a cada crida. És fonamental netejar-lo (MDC.clear()) al final per no arrossegar dades a altres peticions.

Bones pràctiques de logging:

  • Fes servir nivells correctament (DEBUG, INFO, WARN, ERROR) i no inundis amb logs irrellevants.
  • Mai no registris dades sensibles (contrasenyes, targetes, dades personals). Això és una obligació legal a més d'una bona pràctica.
  • Inclou sempre identificadors de correlació (trace_id).

  1. Mètriques: les metodologies RED i USE

Les mètriques són valors numèrics mesurats al llarg del temps: comptadors (peticions totals), mesuradors (memòria usada) i histogrames (distribució de latències). Com que pots mesurar milers de coses, dues metodologies t'ajuden a triar què mesurar.

RED se centra en el servei des del punt de vista de l'usuari:

Mètrica RED Significat Pregunta
Rate Peticions per segon Quant trànsit rebo?
Errors Taxa d'errors Quantes peticions fallen?
Duration Latència (distribució) Quant triguen?

USE se centra en els recursos (CPU, memòria, disc, xarxa):

Mètrica USE Significat Pregunta
Utilization Percentatge d'ús Com d'ocupat està?
Saturation Treball en cua esperant Hi ha més demanda de la que pot atendre?
Errors Errors del recurs Està fallant el recurs?

Regla pràctica: fes servir RED per als serveis (el que veu l'usuari) i USE per als recursos (la infraestructura subjacent). Juntes et donen una visió completa.

# Format d'exposició de mètriques Prometheus
# HELP http_requests_total Total de peticions HTTP
# TYPE http_requests_total counter
http_requests_total{service="pagos",status="200"} 48210
http_requests_total{service="pagos",status="500"} 37

# HELP http_request_duration_seconds Latència de les peticions
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.3"} 47100
http_request_duration_seconds_bucket{le="1.0"} 48190

Explicació: el primer bloc és un comptador (counter) de peticions, etiquetat (labels) per servei i codi d'estat; permet calcular Rate i Errors de RED. El segon és un histograma que compta quantes peticions van caure sota cada llindar de latència (le = less or equal); amb ell es calculen percentils com el p95 (Duration de RED). Les etiquetes ({service=...}) permeten filtrar i agrupar les mètriques.

  1. Traces distribuïdes i correlació

Quan una petició travessa diversos serveis, com en segueixes el rastre complet? Amb traces distribuïdes. Una traça (trace) representa el viatge complet d'una petició; es compon de spans, on cada span és una operació (una crida a un servei, una consulta a la base de dades).

El mecanisme clau és la propagació del context: el primer servei genera un trace_id únic i el passa a cada servei que crida, normalment en capçaleres HTTP. Així, tots els logs i spans d'aquesta petició comparteixen el mateix trace_id i es poden correlacionar.

graph TD
    A["Span: API Gateway (trace_id=abc, 400ms)"] --> B["Span: Servei Comandes (120ms)"]
    A --> C["Span: Servei Pagament (250ms)"]
    C --> D["Span: Crida al Banc (230ms)"]

Aquest arbre de spans mostra d'un cop d'ull on se'n va el temps: dels 400 ms totals, el servei de Pagament consumeix 250 ms, i gairebé tots (230 ms) els gasta esperant el Banc. Sense traces, només sabries que "la petició va trigar 400 ms"; amb elles, saps exactament on és el coll d'ampolla.

# Propagació del context de traça via capçalera estàndard W3C Trace Context
curl https://api.miempresa.com/pedidos \
  -H "traceparent: 00-abc123def456...-0011223344556677-01"
#       versió-trace_id-----------------span_id---------flags

La capçalera traceparent (estàndard W3C) transporta el trace_id (identifica tota la traça) i el span_id (identifica el span pare). Cada servei llegeix aquesta capçalera, crea el seu propi span fill i la reenvia al servei següent, mantenint la cadena unida.

  1. OpenTelemetry: l'estàndard unificador

Històricament, cada eina d'observabilitat tenia el seu propi format i instrumentació, lligant-te a un proveïdor. OpenTelemetry (OTel) és l'estàndard obert (de la CNCF) que unifica la generació dels tres senyals (logs, mètriques i traces) sota una sola API i un sol protocol (OTLP). Instrumentes el teu codi una vegada i pots enviar les dades a qualsevol backend (Prometheus, Jaeger, Grafana, etc.).

graph LR
    APP[La teva aplicació + SDK OTel] -->|OTLP| COL[OpenTelemetry Collector]
    COL --> M[Mètriques: Prometheus]
    COL --> T[Traces: Jaeger]
    COL --> L[Logs: Loki]

La peça central és el Collector: l'aplicació, instrumentada amb el SDK d'OTel, envia tota la seva telemetria al Collector mitjançant el protocol OTLP, i aquest la processa i la reenvia a cada backend especialitzat. El gran avantatge: el teu codi no sap ni li importa quin backend hi ha al darrere; els pots canviar sense tocar l'aplicació.

// Crear un span manualment amb l'API d'OpenTelemetry
Span span = tracer.spanBuilder("procesar-pago").startSpan();
try (Scope scope = span.makeCurrent()) {
    span.setAttribute("order_id", 123);   // Atributs consultables al span
    procesarPago();                        // El treball real
} catch (Exception e) {
    span.recordException(e);               // Registra l'error a la traça
    throw e;
} finally {
    span.end();                            // SEMPRE tancar el span
}

Aquest codi crea un span anomenat procesar-pago que mesura el temps de l'operació. makeCurrent() el fa "actiu" perquè les crides niuades es pengin d'ell automàticament. Si hi ha un error, recordException l'adjunta a la traça (veuràs la fallada al span). L'span.end() al finally garanteix que el span es tanqui i es registri la seva durada passi el que passi.

Errors habituals i consells

  • Confondre monitoratge amb observabilitat. Monitorar és vigilar mètriques conegudes; observabilitat és poder investigar problemes que no vas anticipar. Necessites totes dues.
  • Logs en text lliure. Impossibles d'analitzar a escala. Fes servir logging estructurat (JSON) des del principi.
  • No propagar el trace_id. Sense correlació, els logs de cada servei són illes inconnexes. Propaga sempre el context de traça.
  • Registrar dades sensibles. És una fallada de seguretat i de compliment normatiu. Filtra contrasenyes, targetes i dades personals abans de fer log.
  • Massa mètriques d'alta cardinalitat. Etiquetes amb valors il·limitats (com user_id a cada mètrica) fan explotar el cost d'emmagatzematge. Fes servir cardinalitat acotada.
  • Traçar el 100% del trànsit sense mostreig. En sistemes d'alt volum genera un cost enorme. Aplica mostreig (sampling) intel·ligent.
  • Consell: instrumenta pensant en les preguntes que voldràs fer quan alguna cosa falli a les 3 de la matinada.

Exercicis

  1. Triar el pilar adequat. Per a cada situació, indica quin pilar (logs, mètriques o traces) faries servir primer: (a) un panell mostra que la taxa d'errors ha pujat al 5%; (b) vols saber per què exactament va fallar la comanda 987; (c) una petició triga 3 segons i vols saber quin servei l'està alentint.

  2. Millorar un log. Reescriu aquest log en text lliure com un log estructurat en JSON amb camps útils per al diagnòstic: "ERROR: fallada en connectar amb la base de dades després de 3 intents"

  3. RED vs USE. Classifica cada mètrica segons la metodologia més apropiada: (a) peticions per segon de l'API; (b) percentatge d'ús de CPU del servidor; (c) longitud de la cua de disc; (d) taxa de respostes HTTP 500.

Solucions

  1. (a) Mètriques (t'alerten que alguna cosa va malament: la taxa d'errors). (b) Logs (et donen el detall exacte de la fallada d'aquella comanda concreta). (c) Traces (et mostren el recorregut de la petició i quin span/servei consumeix el temps). El flux natural d'investigació sol ser mètrica -> traça -> log.

  2. Exemple de log estructurat:

    {
      "timestamp": "2026-06-30T10:20:00Z",
      "level": "ERROR",
      "service": "pedidos",
      "message": "Fallada de connexió a la base de dades",
      "component": "db_pool",
      "retries": 3,
      "db_host": "db-primary",
      "trace_id": "abc123"
    }
    

    Ara es pot filtrar per component, comptar reintents o enllaçar amb la traça via trace_id.

  3. (a) RED (Rate, mètrica de servei). (b) USE (Utilization d'un recurs). (c) USE (Saturation: treball encuat al disc). (d) RED (Errors, mètrica de servei). En resum: a i d mesuren el servei (RED); b i c mesuren recursos (USE).

Conclusió

Has après que l'observabilitat se sosté sobre tres pilars complementaris: logs (què va passar), mètriques (quant/com de bé) i traces (per on va passar). Has vist com els logs estructurats els fan analitzables, com RED i USE et guien sobre què mesurar, com la correlació mitjançant trace_id uneix tots els senyals d'una petició, i com OpenTelemetry estandarditza tota la instrumentació. Un sistema observable és un sistema que pots interrogar per entendre qualsevol problema, previst o no.

Les mètriques que hem après a recollir (latència, throughput, percentils) són precisament les que mesurarem en sotmetre el sistema a càrrega. A l'última lliçó del mòdul, Rendiment i Proves de Càrrega, veurem com mesurar i validar que el sistema aguanta el que el negoci necessita.

Curs d'Arquitectura d'Aplicacions

Mòdul 1: Fonaments de l'Arquitectura d'Aplicacions

Mòdul 2: Principis i Tàctiques de Disseny

Mòdul 3: Estils i Patrons Arquitectònics

Mòdul 4: Arquitectures Distribuïdes i Microserveis

Mòdul 5: Arquitectures Dirigides per Esdeveniments i Missatgeria

Mòdul 6: Disseny Dirigit pel Domini (DDD)

Mòdul 7: Dades i Persistència

Mòdul 8: Arquitectura al Núvol i Desplegament

Mòdul 9: Qualitat, Seguretat i Observabilitat

Mòdul 10: Evolució, Governança i Casos Pràctics

© Copyright 2026. Tots els drets reservats