diff --git a/app/favorite/cmd/main.go b/app/favorite/cmd/main.go index 39b50be..b301243 100644 --- a/app/favorite/cmd/main.go +++ b/app/favorite/cmd/main.go @@ -18,12 +18,12 @@ package main import ( + "context" "net" - "github.com/pkg/errors" + "github.com/CocaineCong/tangseng/pkg/tracing" - "github.com/sirupsen/logrus" - "google.golang.org/grpc" + "github.com/pkg/errors" "github.com/CocaineCong/tangseng/app/favorite/internal/service" "github.com/CocaineCong/tangseng/config" @@ -32,6 +32,9 @@ import ( "github.com/CocaineCong/tangseng/loading" "github.com/CocaineCong/tangseng/pkg/discovery" logs "github.com/CocaineCong/tangseng/pkg/logger" + "github.com/sirupsen/logrus" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "google.golang.org/grpc" ) func main() { @@ -46,7 +49,18 @@ func main() { Name: config.Conf.Domain[consts.FavoriteServiceName].Name, Addr: grpcAddress, } - server := grpc.NewServer() + //注册tracer + provider := tracing.InitTracerProvider(config.Conf.Jaeger.Addr, consts.FavoriteServiceName) + defer func() { + if provider == nil { + return + } + if err := provider(context.Background()); err != nil { + logs.LogrusObj.Errorf("Failed to shutdown: %v", err) + } + }() + handler := otelgrpc.NewServerHandler() + server := grpc.NewServer(grpc.StatsHandler(handler)) defer server.Stop() // 绑定service favoritePb.RegisterFavoritesServiceServer(server, service.GetFavoriteSrv()) diff --git a/app/gateway/cmd/main.go b/app/gateway/cmd/main.go index 0919743..e3944d6 100644 --- a/app/gateway/cmd/main.go +++ b/app/gateway/cmd/main.go @@ -18,10 +18,16 @@ package main import ( + "context" "fmt" "net/http" "time" + logs "github.com/CocaineCong/tangseng/pkg/logger" + + "github.com/CocaineCong/tangseng/consts" + "github.com/CocaineCong/tangseng/pkg/tracing" + "github.com/sirupsen/logrus" "google.golang.org/grpc/resolver" @@ -35,6 +41,16 @@ import ( func main() { loading.Loading() rpc.Init() + ////注册tracer + provider := tracing.InitTracerProvider(config.Conf.Jaeger.Addr, consts.ServiceName) + defer func() { + if provider == nil { + return + } + if err := provider(context.Background()); err != nil { + logs.LogrusObj.Errorf("Failed to shutdown: %v", err) + } + }() // etcd注册 etcdAddress := []string{config.Conf.Etcd.Address} etcdRegister := discovery.NewResolver(etcdAddress, logrus.New()) diff --git a/app/gateway/routes/router.go b/app/gateway/routes/router.go index fbdf15d..0ceba4c 100644 --- a/app/gateway/routes/router.go +++ b/app/gateway/routes/router.go @@ -25,11 +25,13 @@ import ( "github.com/CocaineCong/tangseng/app/gateway/http" "github.com/CocaineCong/tangseng/app/gateway/middleware" + "github.com/CocaineCong/tangseng/consts" + "go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin" ) func NewRouter() *gin.Engine { r := gin.Default() - r.Use(middleware.Cors(), middleware.ErrorMiddleware()) + r.Use(middleware.Cors(), middleware.ErrorMiddleware(), otelgin.Middleware(consts.ServiceName)) store := cookie.NewStore([]byte("something-very-secret")) r.Use(sessions.Sessions("mysession", store)) v1 := r.Group("/api/v1") diff --git a/app/index_platform/cmd/main.go b/app/index_platform/cmd/main.go index ea47101..7b93dc8 100644 --- a/app/index_platform/cmd/main.go +++ b/app/index_platform/cmd/main.go @@ -21,6 +21,9 @@ import ( "context" "net" + "github.com/CocaineCong/tangseng/pkg/tracing" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -55,7 +58,18 @@ func main() { Name: config.Conf.Domain[consts.IndexPlatformName].Name, Addr: grpcAddress, } - server := grpc.NewServer() + //注册tracer + provider := tracing.InitTracerProvider(config.Conf.Jaeger.Addr, consts.IndexPlatformName) + defer func() { + if provider == nil { + return + } + if err := provider(context.Background()); err != nil { + logs.LogrusObj.Errorf("Failed to shutdown: %v", err) + } + }() + handler := otelgrpc.NewServerHandler() + server := grpc.NewServer(grpc.StatsHandler(handler)) defer server.Stop() index_platform.RegisterIndexPlatformServiceServer(server, service.GetIndexPlatformSrv()) diff --git a/app/search_engine/cmd/main.go b/app/search_engine/cmd/main.go index 38e2c47..fcaa4b8 100644 --- a/app/search_engine/cmd/main.go +++ b/app/search_engine/cmd/main.go @@ -21,6 +21,9 @@ import ( "context" "net" + "github.com/CocaineCong/tangseng/pkg/tracing" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + logs "github.com/CocaineCong/tangseng/pkg/logger" "github.com/pkg/errors" @@ -56,7 +59,18 @@ func main() { Name: config.Conf.Domain[consts.SearchServiceName].Name, Addr: grpcAddress, } - server := grpc.NewServer() + //注册tracer + provider := tracing.InitTracerProvider(config.Conf.Jaeger.Addr, consts.SearchServiceName) + defer func() { + if provider == nil { + return + } + if err := provider(context.Background()); err != nil { + logs.LogrusObj.Errorf("Failed to shutdown: %v", err) + } + }() + handler := otelgrpc.NewServerHandler() + server := grpc.NewServer(grpc.StatsHandler(handler)) defer server.Stop() // 绑定service pb.RegisterSearchEngineServiceServer(server, service.GetSearchEngineSrv()) diff --git a/app/user/cmd/main.go b/app/user/cmd/main.go index d7c5613..c96eec9 100644 --- a/app/user/cmd/main.go +++ b/app/user/cmd/main.go @@ -18,8 +18,12 @@ package main import ( + "context" "net" + "github.com/CocaineCong/tangseng/pkg/tracing" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + logs "github.com/CocaineCong/tangseng/pkg/logger" "github.com/pkg/errors" @@ -46,7 +50,18 @@ func main() { Name: config.Conf.Domain[consts.UserServiceName].Name, Addr: grpcAddress, } - server := grpc.NewServer() + //注册tracer + provider := tracing.InitTracerProvider(config.Conf.Jaeger.Addr, consts.UserServiceName) + defer func() { + if provider == nil { + return + } + if err := provider(context.Background()); err != nil { + logs.LogrusObj.Errorf("Failed to shutdown: %v", err) + } + }() + handler := otelgrpc.NewServerHandler() + server := grpc.NewServer(grpc.StatsHandler(handler)) defer server.Stop() // 绑定service pb.RegisterUserServiceServer(server, service.GetUserSrv()) diff --git a/config/config.go b/config/config.go index 53df41c..20e4b64 100644 --- a/config/config.go +++ b/config/config.go @@ -38,6 +38,11 @@ type Config struct { StarRocks *StarRocks `yaml:"starrock"` Vector *VectorConfig `yaml:"vector"` Milvus *MilvusConfig `yaml:"milvus"` + Jaeger *Jaeger `yaml:"jaeger"` +} + +type Jaeger struct { + Addr string `yaml:"addr"` } type VectorConfig struct { diff --git a/config/config.yaml b/config/config.yaml index f074646..f2d40aa 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -135,4 +135,6 @@ milvus: default_milvus_table_name: milvus_table_name metric_type: L2 timeout: 3 +jaeger: + addr: 127.0.0.1:4317 diff --git a/config/config.yaml.example b/config/config.yaml.example index b4619f1..f951476 100644 --- a/config/config.yaml.example +++ b/config/config.yaml.example @@ -119,3 +119,6 @@ milvus: metric_type: L2 timeout: 3 +jaeger: + addr: 127.0.0.1:4317 + diff --git a/consts/tracer.go b/consts/tracer.go new file mode 100644 index 0000000..ab2f280 --- /dev/null +++ b/consts/tracer.go @@ -0,0 +1,22 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package consts + +const ( + ServiceName = "tangseng" +) diff --git a/docker-compose.yaml b/docker-compose.yaml index b051dc8..0b8ef92 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -58,6 +58,7 @@ services: image: jaegertracing/all-in-one:latest ports: - "16686:16686" + - "4317:4317" restart: always networks: - search_engine diff --git a/pkg/clone/context.go b/pkg/clone/context.go index 8778477..9fc872a 100644 --- a/pkg/clone/context.go +++ b/pkg/clone/context.go @@ -21,8 +21,6 @@ import ( "context" "time" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" oteltrace "go.opentelemetry.io/otel/trace" ) @@ -43,9 +41,8 @@ func NewContextWithoutDeadline() *ContextWithoutDeadline { } func (c *ContextWithoutDeadline) Clone(ctx context.Context, keys ...interface{}) { - _, span := otel.GetTracerProvider().Tracer("tangseng"+"/clone"). - Start(ctx, "clone", oteltrace.WithAttributes(attribute.Int("sync", 1))) - defer span.End() + + span := oteltrace.SpanFromContext(ctx) c.ctx = oteltrace.ContextWithSpan(c.ctx, span) diff --git a/pkg/ctl/ctl.go b/pkg/ctl/ctl.go index 6520de5..a5836dc 100644 --- a/pkg/ctl/ctl.go +++ b/pkg/ctl/ctl.go @@ -18,6 +18,9 @@ package ctl import ( + "time" + + "github.com/CocaineCong/tangseng/pkg/tracing" "github.com/gin-gonic/gin" e2 "github.com/CocaineCong/tangseng/consts/e" @@ -25,10 +28,12 @@ import ( // Response 基础序列化器 type Response struct { - Status int `json:"status"` - Data interface{} `json:"data"` - Msg string `json:"msg"` - Error string `json:"error"` + Status int `json:"status"` + Data interface{} `json:"data"` + Msg string `json:"msg"` + Error string `json:"error"` + Timestamp int64 `json:"timestamps"` + TraceID string `json:"traceID"` } // RespSuccess 带data成功返回 @@ -43,9 +48,11 @@ func RespSuccess(ctx *gin.Context, data interface{}, code ...int) *Response { } r := &Response{ - Status: status, - Data: data, - Msg: e2.GetMsg(status), + Status: status, + Data: data, + Msg: e2.GetMsg(status), + Timestamp: time.Now().Unix(), + TraceID: tracing.GetTraceID(ctx), } return r @@ -58,10 +65,12 @@ func RespError(ctx *gin.Context, err error, data string, code ...int) *Response } r := &Response{ - Status: status, - Data: data, - Msg: e2.GetMsg(status), - Error: err.Error(), + Status: status, + Data: data, + Msg: e2.GetMsg(status), + Error: err.Error(), + Timestamp: time.Now().Unix(), + TraceID: tracing.GetTraceID(ctx), } return r diff --git a/pkg/tracing/tracing.go b/pkg/tracing/tracing.go new file mode 100644 index 0000000..5165b33 --- /dev/null +++ b/pkg/tracing/tracing.go @@ -0,0 +1,79 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package tracing + +import ( + "context" + + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + + logs "github.com/CocaineCong/tangseng/pkg/logger" + "go.opentelemetry.io/contrib/propagators/b3" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + tracesdk "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" +) + +func InitTracerProvider(url string, serviceName string) func(ctx context.Context) error { + ctx := context.Background() + // 创建一个新的 OTLP gRPC 客户端 + client := otlptracegrpc.NewClient( + otlptracegrpc.WithInsecure(), + otlptracegrpc.WithEndpoint(url), + ) + // 创建一个新的 OTLP 导出器 + exporter, err := otlptrace.New(ctx, client) + if err != nil { + logs.LogrusObj.Errorf("failed to init tracer, err: %v", err) + return nil + } + tp := tracesdk.NewTracerProvider( + tracesdk.WithBatcher(exporter), //注册exporter + tracesdk.WithResource(newResource(serviceName)), //设置服务信息 + ) + //设置全局tracer + otel.SetTracerProvider(tp) + b3Propagator := b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader)) + propagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}, b3Propagator) + // 设置全局Propagator + otel.SetTextMapPropagator(propagator) + return tp.Shutdown +} + +func newResource(serviceName string) *resource.Resource { + return resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceName(serviceName), + ) +} + +func GetTraceID(ctx context.Context) string { + spanCtx := trace.SpanContextFromContext(ctx) + if spanCtx.HasTraceID() { + traceID := spanCtx.TraceID() + return traceID.String() + } + + return "" +} diff --git a/repository/mysql/db/db_init.go b/repository/mysql/db/db_init.go index 019d76e..8b7f708 100644 --- a/repository/mysql/db/db_init.go +++ b/repository/mysql/db/db_init.go @@ -22,7 +22,8 @@ import ( "strings" "time" - logs "github.com/CocaineCong/tangseng/pkg/logger" + "gorm.io/plugin/opentelemetry/tracing" + "github.com/pkg/errors" "github.com/gin-gonic/gin" @@ -32,6 +33,7 @@ import ( "gorm.io/gorm/schema" "github.com/CocaineCong/tangseng/config" + logs "github.com/CocaineCong/tangseng/pkg/logger" ) var _db *gorm.DB @@ -76,6 +78,10 @@ func Database(connString string) error { err = errors.Wrap(err, "failed to open Mysql") return err } + if err = db.Use(tracing.NewPlugin()); err != nil { + err = errors.Wrap(err, "failed to use db plugin") + return err + } sqlDB, _ := db.DB() sqlDB.SetMaxIdleConns(20) // 设置连接池,空闲 sqlDB.SetMaxOpenConns(100) // 打开 diff --git a/repository/redis/init.go b/repository/redis/init.go index d64e9c0..c8e934a 100644 --- a/repository/redis/init.go +++ b/repository/redis/init.go @@ -21,6 +21,8 @@ import ( "context" "fmt" + "github.com/redis/go-redis/extra/redisotel/v9" + "github.com/redis/go-redis/v9" "github.com/CocaineCong/tangseng/config" @@ -40,6 +42,9 @@ func InitRedis() { Password: rConfig.RedisPassword, DB: rConfig.RedisDbName, }) + if err := redisotel.InstrumentTracing(client); err != nil { + logs.LogrusObj.Errorf("failed to trace redis, err = %v", err) + } _, err := client.Ping(RedisContext).Result() if err != nil { logs.LogrusObj.Errorln(err)