Sporing med OpenTelemetry
Integrer OpenTelemetry for å oppnå distribuert sporing og visualisere ende-til-ende-flyten av forespørsler på tvers av tjenester.
Sporing med OpenTelemetry er en gratis leksjon i gRPC og høyytelses-API-er på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i gRPC og høyytelses-API-er, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i gRPC og høyytelses-API-er inneholder totalt 4 leksjoner.
Mikrotjenester og behovet for sporing
Moderne applikasjoner består ofte av mange små, sammenkoblede tjenester som kalles mikrotjenester. Denne arkitekturen gir fleksibilitet, men kan gjøre feilsøking av komplekse samspill til en stor utfordring.
Når en brukerforespørsel går gjennom flere tjenester, kan det å finne ut hvor en forsinkelse eller feil oppstod, føles som å lete etter en nål i en høystakk.
Følg forespørselens vei
Distribuert sporing hjelper Dem med å visualisere hele reisen til en forespørsel når den flyter gjennom ulike tjenester i systemet Deres.
- Den kobler sammen alle operasjoner som tilhører én enkelt forespørsel.
- Den viser hvor lang tid hver del av forespørselen tok.
- Dette gjør det enklere å identifisere ytelsesflaskehalser og feil på tvers av tjenestegrenser.
OpenTelemetry: standarden for observerbarhet
OpenTelemetry (OTel) er et åpen kildekode-prosjekt som tilbyr en standardisert måte å samle inn telemetridata fra applikasjonene Deres på. Dette omfatter spor, måledata og logger.
I stedet for leverandørspesifikke SDK-er tilbyr OTel ett samlet sett med API-er, SDK-er og verktøy for å instrumentere tjenestene Deres, slik at observerbarhetsdataene blir portérbare.
Spor bygges opp av spans
I OpenTelemetry representerer et spor hele kjøringsforløpet til en forespørsel gjennom systemet Deres. Det kan sammenlignes med hele historien til forespørselen.
Et spor består av én eller flere spans. Hver span representerer én enkelt operasjon eller arbeidsenhet i sporet, omtrent som et trinn i historien. Spans har et starttidspunkt, et sluttidspunkt og metadata.
Videreføring av sporkontekst
For at spans skal danne et komplett spor på tvers av ulike tjenester, må de kobles sammen. Dette gjøres gjennom kontekstvidereføring.
Når én tjeneste kaller en annen, sender den med en «sporkontekst» (ofte i HTTP/2-headere for gRPC). Denne konteksten forteller den mottakende tjenesten hvilket spor og hvilken overordnet span de nye operasjonene tilhører, og oppretter et overordnet-underordnet-forhold mellom spans.
Det viktigste om OTel-sporing
For å implementere sporing skal De arbeide med disse sentrale OpenTelemetry-komponentene:
- TracerProvider: Administrerer
Tracer-instanser og konfigurerer span-prosessorer og eksportører. - Tracer: Oppretter
Span-objekter. - SpanProcessor: Behandler spans før de eksporteres (for eksempel i grupper).
- Exporter: Sender innsamlede spans til en backend (for eksempel en konsoll, Jaeger eller en OTLP-samler).
OTel-oppsett: TracerProvider og Exporter
La oss sette opp en grunnleggende OpenTelemetry-TracerProvider i Go. Vi skal bruke en enkel stdouttrace-eksportør til å skrive sporingsdata til konsollen, slik at De kan se spans som blir generert.
Dette kodeeksempelet initialiserer den globale TracerProvider-en og sørger for at alle spans tømmes når applikasjonen avsluttes.
Kjør denne koden for å se det grunnleggende oppsettet:
package main
import (
"context"
"log"
"os"
"time"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
"go.opentelemetry.io/otel/trace"
)
// initTracerProvider initializes an OpenTelemetry TracerProvider
// with a stdout exporter for demonstration.
func initTracerProvider() *sdktrace.TracerProvider {
// Create stdout exporter to print traces to the console
exporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint())
if err != nil {
log.Fatalf("failed to create stdout exporter: %v", err)
}
// Create a new TracerProvider with the exporter and a service name
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter), // Batch spans for efficiency
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("my-simple-service"),
attribute.String("environment", "development"),
)),
)
otel.SetTracerProvider(tp) // Set the global TracerProvider
return tp
}
func main() {
tp := initTracerProvider()
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatalf("Error shutting down tracer provider: %v", err)
}
}()
// Get a tracer
tracer := otel.Tracer("my-app-tracer")
// Create a root span
ctx, span := tracer.Start(context.Background(), "main-operation")
defer span.End()
log.Println("Hello from main-operation with tracing enabled!")
time.Sleep(100 * time.Millisecond) // Simulate some work
// Create a child span
_, childSpan := tracer.Start(ctx, "sub-operation")
defer childSpan.End()
childSpan.SetAttributes(attribute.String("task", "processing"))
log.Println("Doing some sub-operation...")
time.Sleep(50 * time.Millisecond) // Simulate more work
log.Println("Trace data will be printed on shutdown.")
}Automatisk sporing av gRPC-kall
For å spore gRPC-forespørsler automatisk tilbyr OpenTelemetry interceptors. Dette er middleware-funksjoner som pakker inn gRPC-kall på både klient- og serversiden.
- Serverinterceptor: Starter en ny span for innkommende forespørsler og kobler den til sporkonteksten fra klienten.
- Klientinterceptor: Setter inn den gjeldende sporkonteksten i utgående forespørsler, slik at den kan videreføres til serveren.
Slik kan De bruke dem på gRPC-serveren og -klienten Deres:
package main
import (
"context"
"log"
"net"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
// OpenTelemetry imports
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
// gRPC OpenTelemetry instrumentation
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
// For this example, we'll define a simple service in-line
pb "google.golang.org/grpc/examples/helloworld/helloworld" // Using a standard example proto
)
// initTracerProvider initializes an OpenTelemetry TracerProvider
// with a stdout exporter for demonstration.
func initTracerProvider() *sdktrace.TracerProvider {
exporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint())
if err != nil {
log.Fatalf("failed to create stdout exporter: %v", err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("grpc-otel-demo"),
attribute.String("environment", "development"),
)),
)
otel.SetTracerProvider(tp)
return tp
}
// helloServer is a simple gRPC server for demonstration
type helloServer struct {
pb.UnimplementedGreeterServer
}
func (s *helloServer) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
// Simulate some work
time.Sleep(50 * time.Millisecond)
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
func main() {
// 1. Initialize OpenTelemetry TracerProvider
tp := initTracerProvider()
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatalf("Error shutting down tracer provider: %v", err)
}
}()
// 2. Start gRPC Server with OpenTelemetry Interceptor
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer(
grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()), // Apply OTel server interceptor
)
pb.RegisterGreeterServer(s, &helloServer{})
log.Println("Server listening on :50051")
go func() {
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}()
defer s.Stop()
// Allow server to start
time.Sleep(1 * time.Second)
// 3. Create gRPC Client with OpenTelemetry Interceptor
conn, err := grpc.Dial(
"localhost:50051",
grpc.WithInsecure(), // For simplicity, use insecure
grpc.WithBlock(),
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()), // Apply OTel client interceptor
)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// 4. Make a gRPC call
log.Println("Making gRPC call...")
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "CoddyKit User"})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
// Give some time for spans to be processed and exported
time.Sleep(1 * time.Second)
log.Println("Trace data should now be visible in console.")
}Les sporingshistorien
Etter at De har kjørt det forrige eksempelet, vises en detaljert JSON-utskrift i konsollen. Denne utskriften representerer sporingsdataene.
- Se etter
"TraceID": Denne unike ID-en kobler sammen alle spans som tilhører samme forespørsel. - Hver oppføring er en
"Span": Den har en"SpanID","ParentSpanID"(hvis den ikke er roten), navn, start- og sluttidspunkt samt attributter. - Hierarkiet mellom spans (overordnet-underordnet) viser kjøringsflyten.
Denne «historien» hjelper Dem med å forstå hvor lang tid hvert trinn tok, og hvilken tjeneste som var ansvarlig.
Berik spans med attributter
Selv om automatisk instrumentering gir grunnleggende spans, trenger De ofte å legge til mer spesifikk informasjon i sporene. Span-attributter (nøkkel-verdi-par) gjør dette mulig.
De kan registrere detaljer som bruker-ID-er, forespørselsparametere eller resultater fra spesifikk forretningslogikk direkte på en span. Dette gjør feilsøking og analyse langt mer effektivt.
Bruk span.SetAttributes() for å legge til egendefinerte attributter.
package main
import (
"context"
"log"
"time"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
"go.opentelemetry.io/otel/trace"
)
// initTracerProvider initializes an OpenTelemetry TracerProvider
func initTracerProvider() *sdktrace.TracerProvider {
exporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint())
if err != nil {
log.Fatalf("failed to create stdout exporter: %v", err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("custom-attributes-demo"),
)),
)
otel.SetTracerProvider(tp)
return tp
}
func main() {
tp := initTracerProvider()
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatalf("Error shutting down tracer provider: %v", err)
}
}()
tracer := otel.Tracer("my-custom-tracer")
// Start a root span
ctx, span := tracer.Start(context.Background(), "process-order")
defer span.End()
// Add custom attributes to the root span
span.SetAttributes(
attribute.String("user.id", "user123"),
attribute.Int("order.id", 45678),
attribute.Bool("is_premium_user", true),
)
log.Println("Processing order with custom attributes...")
time.Sleep(100 * time.Millisecond)
// Create a child span
_, childSpan := tracer.Start(ctx, "database-query")
defer childSpan.End()
childSpan.SetAttributes(
attribute.String("db.system", "postgres"),
attribute.String("db.statement", "SELECT * FROM orders WHERE id=45678"),
)
log.Println("Executing database query...")
time.Sleep(50 * time.Millisecond)
log.Println("Check the console output for custom attributes in the spans!")
time.Sleep(500 * time.Millisecond) // Ensure spans are exported
}Test av sporingskonsepter
De har lært om distribuert sporing og hvordan OpenTelemetry hjelper Dem. La oss teste forståelsen Deres.
Oppsummering: sporing med OpenTelemetry
I denne leksjonen lærte De hvordan distribuert sporing gjør det enklere å håndtere kompleksiteten i mikrotjenester ved å vise hele reisen til en forespørsel.
Vi utforsket OpenTelemetry som standarden for innsamling av spor, og så på sentrale konsepter som spor, spans og kontekstvidereføring. De så hvordan man setter opp en OTel-TracerProvider, og hvordan gRPC-interceptors gjør det enkelt å instrumentere tjenestene Deres. Til slutt så vi på hvordan spans kan berikes med egendefinerte attributter for dypere innsikt.
Med OpenTelemetry får De avgjørende innsyn i hvordan gRPC-applikasjonen Deres oppfører seg!
Lær deg gRPC og høyytelses-API-er med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 12
- Leksjoner
- 48
Ofte stilte spørsmål
Er leksjonen «Sporing med OpenTelemetry» gratis?
Ja – hele teksten i «Sporing med OpenTelemetry» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av gRPC og høyytelses-API-er-kurset, kan du oppgradere til CoddyKit PRO. Kurset i gRPC og høyytelses-API-er inneholder totalt 4 leksjoner.
Hva lærer jeg i «Sporing med OpenTelemetry»?
Integrer OpenTelemetry for å oppnå distribuert sporing og visualisere ende-til-ende-flyten av forespørsler på tvers av tjenester. Du øver på gRPC og høyytelses-API-er med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med gRPC og høyytelses-API-er?
Ingen tidligere erfaring er nødvendig. gRPC og høyytelses-API-er på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Sporing med OpenTelemetry»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne gRPC og høyytelses-API-er-leksjonen?
Ja. Alle gRPC og høyytelses-API-er-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Logging av gRPC-samhandlinger
- Sporing med OpenTelemetry
- Overvåking av gRPC-metrikker
- Helsesjekk og beredskapsprober