1. 拉取并启动docker镜像
docker run --rm --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-p 14250:14250 \
-p 14268:14268 \
-p 14269:14269 \
-p 9411:9411 \
jaegertracing/all-in-one:1.50
2. 访问UI界面
http://localhost:16686
3. 在kratos项目中使用jaeger
- 在main.go文件中加入代码,初始化provider
点击查看代码
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
)
func tracerProvider(url string) (*trace.TracerProvider, error) {
// Create the Jaeger exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return nil, err
}
tp := trace.NewTracerProvider(
// Always be sure to batch in production.
trace.WithBatcher(exp),
// Record information about this application in a Resource.
trace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(conf.ServiceName),
semconv.ServiceVersion(conf.Version),
attribute.String("environment", conf.Config.Service.Env),
)),
)
return tp, nil
}
func init() {
conf.NewViperConfig()
// 初始化jaeger
tp, err := tracerProvider(conf.Config.Jaeger.Url)
if err != nil {
log.Fatal(err)
}
otel.SetTracerProvider(tp)
}
- 在接口中注入链路追踪代码, 通过传递上下文参数将各层函数链接起来
newCtx, span := otel.Tracer("jaeger").Start(ctx, "service.QueryJaegerDemo")
defer span.End()
点击查看代码
func (s *DemoService) QueryJaegerDemoRecord(ctx context.Context, req *v1.QueryJaegerDemoRequest) (*v1.QueryJaegerDemoResponse, error) {
newCtx, span := otel.Tracer("jaeger").Start(ctx, "service.QueryJaegerDemo")
defer span.End()
// 通过请求参数查询数据
deviceData, err := s.activity.QueryJaegerDemo(newCtx, req.GetName())
if err != nil {
return nil, err
}
// 数据赋值
tmp := v1.JaegerDemo{
Id: deviceData.ID,
Name: deviceData.Name,
Age: deviceData.Age,
CreateTime: timestamppb.New(deviceData.CreateTime),
}
// 填充响应体
response := &v1.QueryJaegerDemoResponse{Data: &tmp}
utils.DefaultSuccessResponse(response)
// 返回响应
return response, nil
}
点击查看代码
func (uc *ActivityUsecase) QueryJaegerDemo(ctx context.Context, name string) (*JaegerDemo, error) {
newCtx, span := otel.Tracer("jaeger").Start(ctx, "biz.QueryJaegerDemo")
defer span.End()
coinInfo, err := uc.repo.QueryJaegerDemo(newCtx, name)
// 查询不到数据
if errors.Is(err, gorm.ErrRecordNotFound) {
// 将查询参数填入错误信息中
metaData := map[string]string{
"name": name,
}
return nil, v1.ErrorErrorReasonNotFound("Not found info").WithMetadata(metaData)
}
if err != nil {
uc.log.Errorf("option database error: %s", err.Error())
return nil, v1.ErrorErrorReasonInternalError(errcode.InternalErrorDatabase)
}
return &coinInfo, err
}
点击查看代码
func (r *activityRepo) QueryJaegerDemo(ctx context.Context, name string) (biz.JaegerDemo, error) {
_, span := otel.Tracer("jaeger").Start(ctx, "data.QueryJaegerDemo")
defer span.End()
var res biz.JaegerDemo
sql := r.data.LocalBase.
Table("test_table").
Select([]string{"id", "name", "age", "create_time"}).
Where("name = ?", name)
err := sql.Take(&res).Error
return res, err
}
4. 请求接口,在UI界面查看链路情况
- 通过链路追踪可以看到各层函数的执行情况