Η πρώτη φορά που χρειάζεστε πραγματικά παρατηρησιμότητα δεν είναι όταν κοιτάτε ήρεμα ένα ταμπλό. Είναι όταν ένας χρήστης γράφει "το checkout είναι αργό", το γράφημα σφάλματος φαίνεται κανονικό και στα αρχεία καταγραφής βρίσκετε μόνο μια σειρά αποσυνδεδεμένων μηνυμάτων.
Το OpenTelemetry δημιουργήθηκε για να αποφύγει αυτή τη στιγμή: όχι για να έχει περισσότερα γραφικά, αλλά για να συνδέσει τα κομμάτια. Ένα αίτημα εισέρχεται στο API, καλεί μια βάση δεδομένων, περνά από έναν εξωτερικό πάροχο, δημοσιεύει μια εργασία στην ουρά και ίσως αποτύχει τρεις υπηρεσίες αργότερα. Χωρίς κατανεμημένη ιχνηλάτηση, ανασκευάζετε αυτήν την ιστορία με το χέρι. Με OpenTelemetry τουλάχιστον έχετε χάρτη.
Το θέμα δεν είναι το trace, είναι η ιστορία
Το trace είναι μια ακολουθία του span. Βάλτε έτσι ακούγεται κρύο. Στην πράξη, κάθε span είναι ένα κομμάτι της ιστορίας: POST /checkout, SELECT inventory, call payment provider, publish order.created.
Η αξία έρχεται όταν αρχίσετε να απαντάτε σε πραγματικές ερωτήσεις:
- ποια εξωτερική υπηρεσία επιβραδύνεται;
- τα λάθη προέρχονται από συγκεκριμένη έκδοση;
- το πρόβλημα επηρεάζει όλους ή μόνο έναν ενοικιαστή;
- η επανάληψη κρύβει τάιμ άουτ;
- η ασύγχρονη δουλειά ξεκινά αλλά μετά πεθαίνει κάπου αλλού;
Αυτές οι ερωτήσεις δεν μπορούν να λυθούν με ένα console.log που πετάμε βιαστικά. Πράγματι, συχνά το αρχείο καταγραφής που προστίθεται σε περίπτωση έκτακτης ανάγκης σας βοηθά σήμερα και γίνεται θόρυβος αύριο.
Πώς θα το έβαζα σε μια εφαρμογή Node.js
Η πιο υγιεινή ρύθμιση είναι απλή: η εφαρμογή παράγει τηλεμετρία, το Collector αποφασίζει πού θα τη στείλει.
Node.js app -> OpenTelemetry Collector -> backend di observability
Γιατί να μην εξάγετε απευθείας στον πωλητή; Επειδή στην αρχή φαίνεται πιο γρήγορο, μετά συνειδητοποιείς ότι κάθε υπηρεσία έχει διαφορετικές διαμορφώσεις, διαφορετικές επαναλήψεις, διαφορετικά φίλτρα και κανένα κεντρικό σημείο για την αφαίρεση ευαίσθητων δεδομένων ή την αλλαγή προορισμού.
Το Collector είναι βαρετό με όλους τους σωστούς τρόπους. Λαμβάνει OTLP, κάνει ομαδοποίηση, μπορεί να φιλτράρει, μπορεί να κάνει δειγματοληψία, μπορεί να προσθέσει κοινά χαρακτηριστικά και μπορεί να εξάγει σε πολλαπλά συστήματα.
Αυτο-οργάνωση: καλό, αλλά όχι αρκετό
Το Node.js θα ξεκινούσα με την αυτόματη οργάνωση. Σας δίνει άμεση ορατότητα σε HTTP, υποστηριζόμενα πλαίσια, βάσεις δεδομένων και κοινές βιβλιοθήκες.
npm install @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/exporter-trace-otlp-http
Στη συνέχεια, αρχικοποιείτε το SDK πριν από την υπόλοιπη εφαρμογή:
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();
Ωστόσο, αυτό βλέπει το πλαίσιο, όχι το προϊόν σας. Γνωρίζει ότι κάνατε ένα ερώτημα, αλλά δεν γνωρίζει ότι το ερώτημα ήταν σε "σειρά δημιουργίας" ή "ανανέωση συνδρομής". Για αυτό χρειάζεστε span εγχειρίδια στα σημεία όπου μετράει η κυριαρχία.
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(); }
Εγχειρίδια span δεν θα έβαζα πουθενά. Θα τα έβαζα εκεί που, στις τρεις τα ξημερώματα, θα ήθελα να καταλάβω τι έγινε χωρίς να διαβάσω τη μισή βάση του κώδικα.
Τρεις κανόνες που αποφεύγουν το πολύ χάος
Πρώτος κανόνας: κάθε υπηρεσία πρέπει να έχει service.name, περιβάλλον και έκδοση. Φαίνεται ασήμαντο, αλλά χωρίς αυτά τα χαρακτηριστικά ένα trace είναι πολύ λιγότερο χρήσιμο. Όταν μια ανάπτυξη χαλάει κάτι, θέλετε να φιλτράρετε ανά έκδοση σε δύο δευτερόλεπτα.
Δεύτερος κανόνας: μην τοποθετείτε ευαίσθητα δεδομένα στα χαρακτηριστικά. Τα email, τα διακριτικά, τα ωφέλιμα φορτία ακέραιων αριθμών και οι διευθύνσεις δεν θα πρέπει να καταλήγουν τυχαία σε ένα backend παρατηρητικότητας. Εάν πρέπει να προσδιορίσετε έναν χρήστη, εξετάστε τα εσωτερικά αναγνωριστικά, τον κατακερματισμό ή τα λιγότερο ευαίσθητα πεδία.
Τρίτος κανόνας: δώστε προσοχή στην καρδιναλικότητα. Το user.id ως χαρακτηριστικό του trace μπορεί να έχει νόημα. Ως μετρική ετικέτα μπορεί να καταστρέψει το κόστος και την απόδοσή σας.
Μετρήσεις: λίγες, αλλά καλές
Θα ξεκινούσα με πολύ πρακτικές μετρήσεις:
- ποσοστά, λάθη και διάρκεια αιτημάτων·
- λανθάνουσα κατάσταση εξωτερικών εξαρτήσεων.
- αριθμός χρονικών ορίων και επαναλήψεων.
- βάθος των ουρών.
- διάρκεια εργασίας·
- ποσοστό σφαλμάτων ανά έκδοση.
Το υπόλοιπο προστίθεται όταν χρειάζεται. Τα ταμπλό γεμάτα γραφήματα που κανείς δεν κοιτάζει είναι έπιπλα, όχι παρατηρησιμότητα.
Αρχεία καταγραφής: Εξακολουθούν να είναι χρήσιμα, αλλά συνδέονται
Τα κούτσουρα δεν εξαφανίζονται. Απλώς γίνονται πολύ πιο χρήσιμα όταν φέρουν trace_id και span_id. Έτσι, μπορείτε να ξεκινήσετε από ένα αρχείο καταγραφής σφαλμάτων και να ανοίξετε το trace ή να ξεκινήσετε από ένα αργό trace και να διαβάσετε μόνο τα αρχεία καταγραφής που παράγονται σε αυτήν τη διαδρομή.
Χωρίς συσχετισμό, ψάχνεις για βελόνες. Με τη συσχέτιση, τουλάχιστον ξέρεις σε ποιο συρτάρι να κοιτάξεις.
Η λίστα ελέγχου που θα χρησιμοποιούσα πριν πω "είμαστε καλυμμένοι"
- Το trace διασχίζει πραγματικά πολλές υπηρεσίες.
- Τα αρχεία καταγραφής περιλαμβάνουν
trace_idκαιspan_id. - Το Collector έχει διαμορφωθεί με όρια παρτίδας και μνήμης.
- Τα σφάλματα καταγράφονται στο span.
- Υπάρχει πολιτική δειγματοληψίας.
- Οι μετρήσεις έχουν ελεγχόμενη καρδινάτητα.
- Τα ευαίσθητα δεδομένα φιλτράρονται.
- Οι ειδοποιήσεις ξεκινούν από συμπτώματα χρήστη και όχι από τυχαία γραφήματα.
Συμπέρασμα
Το OpenTelemetry δεν λύνει από μόνο του προβλήματα παραγωγής. Αλλά ο τρόπος που τα αντιμετωπίζεις αλλάζει. Αντί να προσθέτετε τυφλά αρχεία καταγραφής, αρχίζετε να ακολουθείτε την πραγματική διαδρομή ενός αιτήματος.
Για μένα το σημάδι ότι λειτουργεί είναι απλό: όταν συμβαίνει κάτι, η ομάδα σταματά να ρωτά "πού κοιτάμε;" και αρχίζει να ρωτά "γιατί αυτό το κομμάτι είναι αργό;". Εκεί η παρατηρησιμότητα γίνεται εργαλείο, όχι συλλογή πινάκων εργαλείων.