Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Exploring the OpenTelemetry Client Library for Go

Akari
June 06, 2024

Exploring the OpenTelemetry Client Library for Go

Akari

June 06, 2024
Tweet

More Decks by Akari

Other Decks in Programming

Transcript

  1. Exploring the OpenTelemetry Client Library for Go (Unofficial)Go Conference 2024

    Pre Party 7 June, 2024 Keisuke Akari @k-akari @akarin0519
  2. 1. Reference Please refer the following blog post if you’d

    like to know this topic in more detail. - Exploring the OpenTelemetry Client Library for Go
  3. 2. What is the OpenTelemetry? There are two key points:

    1. Vendor- and Tool-agnostic 2. Focused on the generation, collection, management, and export of telemetry
  4. 4. Where Should We Delve into? - One Signal (I’m

    going to single out Tracing here) - Context Propagation Image Source: https://opentelemetry.io/docs/specs/otel/overview/#opentelemetry-client-architecture
  5. 5. Structure of the Client Library ./opentelemetry-go ├── internal #

    Unexported Detailed Implementation │ └── global │ ├── trace.go │ └── state.go ├── sdk # Core Functionalities │ ├── trace │ │ ├── span.go │ │ └── tracer.go │ ├── go.mod │ └── go.sum ├── trace # Trace API │ ├── config.go │ ├── context.go │ ├── trace.go │ ├── go.sum │ └── go.mod ├── trace.go # API ├── go.mod └── go.sum
  6. 6. How Apps Use the Client Library for Tracing package

    main import ( "go.opentelemetry.io/otel" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) func main() { // tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), ) otel.SetTracerProvider(tp) ctx, span := otel.Tracer("example").Start(ctx, "span name") defer span.End() // }
  7. 8. Diving into Context Propagation package main import ( "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"

    "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/propagation" "google.golang.org/grpc" ) func main() { // s := grpc.NewServer(grpc.StatsHandler(otelgrpc.NewServerHandler( otelgrpc.WithPropagators(otel.GetTextMapPropagator()), ))) conn, err := grpc.NewClient("endpoint", grpc.WithStatsHandler(otelgrpc.NewClientHandler( otelgrpc.WithPropagators(otel.GetTextMapPropagator()), ))) // }
  8. NewServerHandler returns stats.Handler. 9. otelgrpc.NewServerHandler package otelgrpc import "google.golang.org/grpc/stats" type

    serverHandler struct { *config } func NewServerHandler(opts ...Option) stats.Handler { h := &serverHandler{ config: newConfig(opts, "server"), } return h } package stats type Handler interface { TagRPC(context.Context, *RPCTagInfo) context.Context HandleRPC(context.Context, RPCStats) TagConn(context.Context, *ConnTagInfo) context.Context HandleConn(context.Context, ConnStats) }
  9. In TagRPC method, propagator extracts context from metadata and embed

    it to context.Context. 10. Extracting Context func (h *serverHandler) TagRPC( ctx context.Context, info *stats.RPCTagInfo, ) context.Context { ctx = extract(ctx, h.config.Propagators) // omitted ctx, _ = h.tracer.Start( trace.ContextWithRemoteSpanContext( ctx, trace.SpanContextFromContext(ctx), ), // omitted ) // omitted return context.WithValue(ctx, gRPCContextKey{}, &gctx) } import ( "google.golang.org/grpc/metadata" "go.opentelemetry.io/otel/propagation" ) func extract( ctx context.Context, propagators propagation.TextMapPropagator, ) context.Context { md, ok := metadata.FromIncomingContext(ctx) if !ok { md = metadata.MD{} } return propagators.Extract(ctx, &metadataSupplier{ metadata: &md, }) }
  10. NewClientHandler returns stats.Handler. 11. otelgrpc.NewClientHandler package otelgrpc import "google.golang.org/grpc/stats" type

    clientHandler struct { *config } func NewClientHandler(opts ...Option) stats.Handler { h := &clientHandler{ config: newConfig(opts, "client"), } return h } package stats type Handler interface { TagRPC(context.Context, *RPCTagInfo) context.Context HandleRPC(context.Context, RPCStats) TagConn(context.Context, *ConnTagInfo) context.Context HandleConn(context.Context, ConnStats) }
  11. In TagRPC method, propagator retrieves context from context.Context and inject

    it to metadata. 12. Injecting Context func (h *clientHandler) TagRPC( ctx context.Context, info *stats.RPCTagInfo, ) context.Context { // omitted ctx, _ = h.tracer.Start( ctx, // omitted ) // omitted return inject( context.WithValue(ctx, gRPCContextKey{}, &gctx), h.config.Propagators, ) } import ( "google.golang.org/grpc/metadata" "go.opentelemetry.io/otel/propagation"re ) func inject(ctx context.Context, propagators propagation.TextMapPropagator, ) context.Context { md, ok := metadata.FromOutgoingContext(ctx) if !ok { md = metadata.MD{} } propagators.Inject(ctx, &metadataSupplier{ metadata: &md, }) return metadata.NewOutgoingContext(ctx, md) }