This service is responsible to return information about products. The service can be used to get all products, search for specific products, or return details about any single product.
Product Catalog service source
The OpenTelemetry SDK is initialized from main
using the initTracerProvider
function.
func initTracerProvider() *sdktrace.TracerProvider {
ctx := context.Background()
exporter, err := otlptracegrpc.New(ctx)
if err != nil {
log.Fatalf("OTLP Trace gRPC Creation: %v", err)
}
tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
return tp
}
You should call TracerProvider.Shutdown()
when your service is shutdown to
ensure all spans are exported. This service makes that call as part of a
deferred function in main
tp := InitTracerProvider()
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatalf("Tracer Provider Shutdown: %v", err)
}
}()
This service receives gRPC requests, which are instrumented in the main function as part of the gRPC server creation.
srv := grpc.NewServer(
grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),
)
This service will issue outgoing gRPC calls, which are all instrumented by wrapping the gRPC client with instrumentation
func createClient(ctx context.Context, svcAddr string) (*grpc.ClientConn, error) {
return grpc.DialContext(ctx, svcAddr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()),
)
}
Within the execution of auto-instrumented code you can get current span from context.
span := trace.SpanFromContext(ctx)
Adding attributes to a span is accomplished using SetAttributes
on the span
object. In the GetProduct
function an attribute for the product id is added
to the span.
span.SetAttributes(
attribute.String("app.product.id", req.Id),
)
This service can catch and handle an error condition based on a feature flag.
In an error condition, the span status is set accordingly using SetStatus
on
the span object. You can see this in the GetProduct
function.
msg := fmt.Sprintf("Error: ProductCatalogService Fail Feature Flag Enabled")
span.SetStatus(otelcodes.Error, msg)
Adding span events is accomplished using AddEvent
on the span object. In the
GetProduct
function a span event is added when an error condition is handled,
or when a product is successfully found.
span.AddEvent(msg)
TBD
TBD