Skip to main content

Tracing

We use OpenTelemetry for distributed tracing.

Configuration

There are two methods for configuration WithTracerProvider() and WithPropagator().

WithTracerProvider

func WithTracerProvider(provider trace.TracerProvider) Option {
return func(opts *options) {
opts.TracerProvider = provider
}
}

WithTracerProvider is for setting the provider, it accepts trace.TracerProvider

WithPropagator

func WithPropagator(propagator propagation.TextMapPropagator) Option {
return func(opts *options) {
opts.Propagator = propagator
}
}

WithPropagator is for setting the text map propagator, it accepts propagation.TextMapPropagator

Usage

Tracing for Server

package server

import (
"github.com/go-kratos/kratos/v2/middleware/tracing"
"github.com/go-kratos/kratos/v2/transport/grpc"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

// Set global trace provider
func initTracer(url string) error {
// Create the Jaeger exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return err
}
tp := tracesdk.NewTracerProvider(
// Set the sampling rate based on the parent span to 100%
tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(1.0))),
// Always be sure to batch in production.
tracesdk.WithBatcher(exp),
// Record information about this application in an Resource.
tracesdk.WithResource(resource.NewSchemaless(
semconv.ServiceNameKey.String("kratos-trace"),
attribute.String("exporter", "jaeger"),
attribute.Float64("float", 312.23),
)),
)
otel.SetTracerProvider(tp)
return nil
}

// NewGRPCServer new a gRPC server.
func NewGRPCServer(c *conf.Server, executor *service.ExecutorService) *grpc.Server {
err := initTracer("http://localhost:14268/api/traces")
if err != nil {
panic(err)
}
//tr := otel.Tracer("component-main")
var opts = []grpc.ServerOption{
grpc.Middleware(
tracing.Server(),
),
}
// ...
}

Tracing for Client

package client

import (
"context"

"github.com/go-kratos/kratos/v2/middleware/tracing"
"github.com/go-kratos/kratos/v2/transport/grpc"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
googlegrpc "google.golang.org/grpc"
)

// Set global trace provider
func initTracer(url string) error {
// Create the Jaeger exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return err
}
tp := tracesdk.NewTracerProvider(
// Set the sampling rate based on the parent span to 100%
tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(1.0))),
// Always be sure to batch in production.
tracesdk.WithBatcher(exp),
// Record information about this application in an Resource.
tracesdk.WithResource(resource.NewSchemaless(
semconv.ServiceNameKey.String("kratos-trace"),
attribute.String("exporter", "jaeger"),
attribute.Float64("float", 312.23),
)),
)
otel.SetTracerProvider(tp)
return nil
}

func grpcCli() (*googlegrpc.ClientConn, error) {
// If the project does not initialize initTracer, please initialize.
return grpc.DialInsecure(
context.Background(),
grpc.WithMiddleware(
tracing.Client(),
),
)
}

Automatic Data Collection

If you don't want to modify the code manually, you can also use Agent for automatic collection of OpenTelemetry data, such as Alibaba Go Auto Instrumentation (which will later be officially donated to OpenTelemetry Official Repository).

You can refer to the documentation to compile your Kratos application.

References