Slide 1

Slide 1 text

Exploring the OpenTelemetry Client Library for Go (Unofficial)Go Conference 2024 Pre Party 7 June, 2024 Keisuke Akari @k-akari @akarin0519

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

3. Looking More Specifically Image Source: https://opentelemetry.io/docs/specs/otel/library-guidelines/

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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() // }

Slide 8

Slide 8 text

7. What is the Context Propagation?

Slide 9

Slide 9 text

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()), ))) // }

Slide 10

Slide 10 text

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) }

Slide 11

Slide 11 text

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, }) }

Slide 12

Slide 12 text

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) }

Slide 13

Slide 13 text

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) }

Slide 14

Slide 14 text

Thank you for your attention🙏