Den første gang, du virkelig har brug for observerbarhed, er ikke, når du roligt kigger på et dashboard. Det er, når en bruger skriver "checkout is slow", fejlgrafen ser normal ud, og i loggene finder man kun en række afbrudte beskeder.
OpenTelemetry blev skabt for at undgå det øjeblik: ikke for at have mere grafik, men for at forbinde brikkerne. En anmodning kommer ind i API, kalder en database, går gennem en ekstern udbyder, sender et job i kø og mislykkes måske tre tjenester senere. Uden distribueret sporing rekonstruerer du den historie i hånden. Med OpenTelemetry har du i det mindste et kort.
Pointen er ikke trace, det er historien
En trace er en sekvens af span. Sådan lyder det koldt. I praksis er hver span en del af historien: POST /checkout, SELECT inventory, call payment provider, publish order.created.
Værdien kommer, når du begynder at besvare rigtige spørgsmål:
- hvilken ekstern service bremser?
- kommer fejlene fra en bestemt version?
- rammer problemet alle eller kun én lejer?
- skjuler et genforsøg en timeout?
- det asynkrone job starter, men dør så et andet sted?
Disse spørgsmål kan ikke løses med en console.log kastet i en fart. Faktisk hjælper loggen, der tilføjes i en nødsituation, dig i dag og bliver til støj i morgen.
Hvordan ville jeg placere dette i en app Node.js
Den sundeste opsætning er enkel: appen producerer telemetri, Collector bestemmer, hvor den skal sendes.
Node.js app -> OpenTelemetry Collector -> backend di observability
Hvorfor ikke eksportere direkte til leverandøren? For i første omgang virker det hurtigere, så indser du, at hver tjeneste har forskellige konfigurationer, forskellige genforsøg, forskellige filtre og intet centralt punkt til at fjerne følsomme data eller ændre destination.
Collector er kedelig på alle de rigtige måder. Den modtager OTLP, udfører batching, kan filtrere, kan udføre sampling, kan tilføje fælles attributter og kan eksportere til flere systemer.
Selvinstrumentering: god, men ikke nok
I Node.js ville jeg starte med auto-instrumentering. Det giver dig øjeblikkelig synlighed i HTTP, understøttede rammer, databaser og almindelige biblioteker.
npm install @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/exporter-trace-otlp-http
Så initialiserer du SDK før resten af appen:
import { NodeSDK } from '@opentelemetry/sdk-node'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; const sdk = new NodeSDK({ traceExporter: new OTLPTraceExporter({ url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, }), instrumentations: [getNodeAutoInstrumentations()], }); sdk.start();
Dette ser dog rammerne, ikke dit produkt. Den ved, at du har lavet en forespørgsel, men den ved ikke, at forespørgslen var i "opret rækkefølge" eller "forny abonnement". Til det har du brug for span manualer på de punkter, hvor dominans tæller.
const span = tracer.startSpan('checkout.create_order'); try { span.setAttribute('cart.items_count', input.items.length); const order = await createOrder(input); span.setAttribute('order.id', order.id); return order; } catch (error) { span.recordException(error as Error); throw error; } finally { span.end(); }
Jeg ville ikke placere span manualer nogen steder. Jeg ville placere dem, hvor jeg klokken tre om morgenen gerne ville forstå, hvad der skete uden at læse halvdelen af kodebasen.
Tre regler, der undgår en masse kaos
Første regel: hver tjeneste skal have service.name, miljø og version. Det virker trivielt, men uden disse attributter er en trace meget mindre nyttig. Når en implementering bryder noget, vil du filtrere efter version på to sekunder.
Anden regel: Indsæt ikke følsomme data i attributterne. E-mails, tokens, heltals nyttelaster og adresser bør ikke ende i en observerbar backend ved et uheld. Hvis du har brug for at identificere en bruger, skal du overveje interne id'er, hashing eller mindre følsomme felter.
Tredje regel: vær opmærksom på kardinalitet. user.id som en egenskab af trace kan give mening. Som en metrisk etiket kan den ødelægge dine omkostninger og ydeevne.
Metrics: få, men gode
Jeg vil starte med meget praktiske målinger:
- rater, fejl og varighed af anmodninger;
- latenstid af eksterne afhængigheder;
- antal timeouts og genforsøg;
- dybden af halerne;
- jobbets varighed;
- procentdel af fejl pr. version.
Resten tilsættes efter behov. Dashboards fulde af grafer, som ingen ser på, er møbler, ikke observerbarhed.
Logs: Stadig nyttige, men linkede
Logs forsvinder ikke. De bliver simpelthen meget mere nyttige, når de bærer trace_id og span_id. Så du kan starte fra en fejllog og åbne trace, eller starte fra en langsom trace og kun læse de logfiler, der er produceret i den sti.
Uden korrelation leder du efter nåle. Med korrelation ved du i det mindste, hvilken skuffe du skal kigge i.
Tjeklisten, jeg ville bruge, før jeg sagde "vi er dækket"
- trace krydser faktisk flere tjenester.
- Logs inkluderer
trace_idogspan_id. - Collector er konfigureret med batch- og hukommelsesgrænser.
- Fejl er registreret i span.
- Der er en prøveudtagningspolitik.
- Metrikker har kontrolleret kardinalitet.
- Følsomme data filtreres.
- Advarsler starter fra brugersymptomer, ikke tilfældige grafer.
Konklusion
OpenTelemetry løser ikke produktionsproblemer alene. Men måden, du håndterer dem på, ændrer sig. I stedet for blindt at tilføje logfiler, begynder du at følge den faktiske sti til en anmodning.
For mig er tegnet på, at det virker, enkelt: når der sker noget, holder teamet op med at spørge "hvor leder vi?" og begynder at spørge "hvorfor er det stykke langsomt?". Det er her observerbarhed bliver et værktøj, ikke en samling af dashboards.