产品目录服务

该服务负责返回关于产品的信息。该服务可用于获取所有产品、搜索特定产品或返回任何单个产品的详细信息。

产品目录服务源代码

跟踪

初始化跟踪

使用initTracerProvider函数从main中初始化OpenTelemetry SDK。

func initTracerProvider() *sdktrace.TracerProvider {
    ctx := context.Background()

    exporter, err := otlptracegrpc.New(ctx)
    if err != nil {
        log.Fatalf("OTLP Trace gRPC 创建失败:%v", err)
    }
    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(exporter),
        sdktrace.WithResource(initResource()),
    )
    otel.SetTracerProvider(tp)
    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
    return tp
}

在服务关闭时,应调用TracerProvider.Shutdown()以确保导出所有跨度。该服务在main函数中使用延迟函数进行此调用。

tp := InitTracerProvider()
defer func() {
    if err := tp.Shutdown(context.Background()); err != nil {
        log.Fatalf("追踪提供程序关闭失败:%v", err)
    }
}()

添加gRPC自动仪表化

该服务接收gRPC请求,在main函数作为gRPC服务器创建的一部分进行仪表化。

srv := grpc.NewServer(
    grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
    grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),
)

该服务会发出出站gRPC调用,在gRPC客户端周围进行仪表化。

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

向自动仪表化跨度添加属性

在自动仪表化代码的执行过程中,您可以从上下文中获取当前跨度。

span := trace.SpanFromContext(ctx)

使用跨度对象上的SetAttributes方法向跨度添加属性。在GetProduct函数中,为产品ID添加了一个属性。

span.SetAttributes(
    attribute.String("app.product.id", req.Id),
)

设置跨度状态

该服务可以根据功能标志来捕获和处理错误条件。在错误条件下,使用跨度对象的SetStatus方法相应地设置跨度状态。您可以在GetProduct函数中看到这一点。

msg := fmt.Sprintf("错误:ProductCatalogService 失败特性标志已启用")
span.SetStatus(otelcodes.Error, msg)

添加跨度事件

使用跨度对象上的AddEvent方法来添加跨度事件。在GetProduct函数中,处理错误条件或成功找到产品时会添加一个跨度事件。

span.AddEvent(msg)

度量

初始化度量

使用initMeterProvider函数从main中初始化OpenTelemetry SDK。

func initMeterProvider() *sdkmetric.MeterProvider {
    ctx := context.Background()

    exporter, err := otlpmetricgrpc.New(ctx)
    if err != nil {
        log.Fatalf("新的 otlp metric grpc 导出器创建失败:%v", err)
    }

    mp := sdkmetric.NewMeterProvider(sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)))
    global.SetMeterProvider(mp)
    return mp
}

在服务关闭时,应调用initMeterProvider.Shutdown()以确保导出所有记录。该服务在main函数中使用延迟函数进行此调用。

mp := initMeterProvider()
defer func() {
    if err := mp.Shutdown(context.Background()); err != nil {
        log.Fatalf("关闭度量提供程序失败:%v", err)
    }
}()

添加Go运行时自动仪表化

main函数中对Go运行时进行仪表化。

err := runtime.Start(runtime.WithMinimumReadMemStatsInterval(time.Second))
if err != nil {
    log.Fatal(err)
}

日志

待定

最后修改 December 10, 2023: translate (a4350d6e)