fix: cross-service trace issues

This commit is contained in:
zhuyasen
2022-12-06 23:42:31 +08:00
parent 675850e2b2
commit 1ed51c8810
43 changed files with 160 additions and 91 deletions

View File

@@ -129,7 +129,7 @@ sponge web http \
**(2) If using the default configuration, skip this step, modify the configuration file configs/<server name>.yml**
- If the field `cacheType` is `redis`, the `redis` address must be set.
- If the field `enableTracing` is true, the `jaeger` address must be set.
- If the field `enableTrace` is true, the `jaeger` address must be set.
- If the field `registryDiscoveryType` is not be empty, the configuration of corresponding values must be set.
**(3) Generate swagger documentation**
@@ -218,7 +218,7 @@ sponge micro rpc \
**(2) If using the default configuration, skip this step. Modify the configuration file configs/<server name>.yml**
- If the field `cacheType` is `redis`, the `redis` address must be set.
- If the field `enableTracing` is true, the `jaeger` address must be set.
- If the field `enableTrace` is true, the `jaeger` address must be set.
- If the field `registryDiscoveryType` is not be empty, the configuration of corresponding values must be set.
**(3) Generating grpc code**

View File

@@ -10,9 +10,6 @@
package v1
import (
types "github.com/zhufuyi/sponge/api/types"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"

View File

@@ -8,7 +8,6 @@ import (
errcode "github.com/zhufuyi/sponge/pkg/errcode"
middleware "github.com/zhufuyi/sponge/pkg/gin/middleware"
zap "go.uber.org/zap"
metadata "google.golang.org/grpc/metadata"
)
// import packages: context. errcode. middleware. zap. gin. metadata.
@@ -106,12 +105,7 @@ func (r *userExampleServiceRouter) Create_0(c *gin.Context) {
return
}
md := metadata.New(nil)
for k, v := range c.Request.Header {
md.Set(k, v...)
}
newCtx := metadata.NewIncomingContext(c, md)
out, err := r.iLogic.Create(newCtx, req)
out, err := r.iLogic.Create(c.Request.Context(), req)
if err != nil {
isIgnore := r.iResponse.Error(c, err)
if !isIgnore {
@@ -138,12 +132,7 @@ func (r *userExampleServiceRouter) DeleteByID_0(c *gin.Context) {
return
}
md := metadata.New(nil)
for k, v := range c.Request.Header {
md.Set(k, v...)
}
newCtx := metadata.NewIncomingContext(c, md)
out, err := r.iLogic.DeleteByID(newCtx, req)
out, err := r.iLogic.DeleteByID(c.Request.Context(), req)
if err != nil {
isIgnore := r.iResponse.Error(c, err)
if !isIgnore {
@@ -170,12 +159,7 @@ func (r *userExampleServiceRouter) UpdateByID_0(c *gin.Context) {
return
}
md := metadata.New(nil)
for k, v := range c.Request.Header {
md.Set(k, v...)
}
newCtx := metadata.NewIncomingContext(c, md)
out, err := r.iLogic.UpdateByID(newCtx, req)
out, err := r.iLogic.UpdateByID(c.Request.Context(), req)
if err != nil {
isIgnore := r.iResponse.Error(c, err)
if !isIgnore {
@@ -202,12 +186,7 @@ func (r *userExampleServiceRouter) GetByID_0(c *gin.Context) {
return
}
md := metadata.New(nil)
for k, v := range c.Request.Header {
md.Set(k, v...)
}
newCtx := metadata.NewIncomingContext(c, md)
out, err := r.iLogic.GetByID(newCtx, req)
out, err := r.iLogic.GetByID(c.Request.Context(), req)
if err != nil {
isIgnore := r.iResponse.Error(c, err)
if !isIgnore {
@@ -228,12 +207,7 @@ func (r *userExampleServiceRouter) ListByIDs_0(c *gin.Context) {
return
}
md := metadata.New(nil)
for k, v := range c.Request.Header {
md.Set(k, v...)
}
newCtx := metadata.NewIncomingContext(c, md)
out, err := r.iLogic.ListByIDs(newCtx, req)
out, err := r.iLogic.ListByIDs(c.Request.Context(), req)
if err != nil {
isIgnore := r.iResponse.Error(c, err)
if !isIgnore {
@@ -254,12 +228,7 @@ func (r *userExampleServiceRouter) List_0(c *gin.Context) {
return
}
md := metadata.New(nil)
for k, v := range c.Request.Header {
md.Set(k, v...)
}
newCtx := metadata.NewIncomingContext(c, md)
out, err := r.iLogic.List(newCtx, req)
out, err := r.iLogic.List(c.Request.Context(), req)
if err != nil {
isIgnore := r.iResponse.Error(c, err)
if !isIgnore {

View File

@@ -19,7 +19,6 @@ const (
middlewarePkg = protogen.GoImportPath("github.com/zhufuyi/sponge/pkg/gin/middleware")
zapPkg = protogen.GoImportPath("go.uber.org/zap")
ginPkg = protogen.GoImportPath("github.com/gin-gonic/gin")
metadataPkg = protogen.GoImportPath("google.golang.org/grpc/metadata")
deprecationComment = "// Deprecated: Do not use."
)
@@ -39,9 +38,8 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated
g.P("package ", file.GoPackageName)
g.P()
// import code
g.P("// import packages: ", contextPkg.Ident(" "), errcodePkg.Ident(" "),
middlewarePkg.Ident(" "), zapPkg.Ident(" "), ginPkg.Ident(" "), metadataPkg.Ident(" "))
middlewarePkg.Ident(" "), zapPkg.Ident(" "), ginPkg.Ident(" "))
g.P()
for _, s := range file.Services {

View File

@@ -119,12 +119,7 @@ func (r *{{$.LowerName}}Router) {{ .HandlerName }} (c *gin.Context) {
return
}
{{end}}
md := metadata.New(nil)
for k, v := range c.Request.Header {
md.Set(k, v...)
}
newCtx := metadata.NewIncomingContext(c, md)
out, err := r.iLogic.{{.Name}}(newCtx, req)
out, err := r.iLogic.{{.Name}}(c.Request.Context(), req)
if err != nil {
isIgnore := r.iResponse.Error(c, err)
if !isIgnore {

View File

@@ -172,7 +172,7 @@ func initServerNameExampleClient() *grpc.ClientConn {
cliOptions = append(cliOptions, grpccli.WithDiscovery(iDiscovery))
}
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
cliOptions = append(cliOptions, grpccli.WithEnableTrace())
}
if config.Get().App.EnableCircuitBreaker {

View File

@@ -40,7 +40,7 @@ func Config() {
model.InitCache(cfg.App.CacheType)
// initializing tracing
if cfg.App.EnableTracing {
if cfg.App.EnableTrace {
tracer.InitWithConfig(
cfg.App.Name,
cfg.App.Env,

View File

@@ -33,7 +33,7 @@ func RegisterClose(servers []app.IServer) []app.Close {
}
// close tracing
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
closes = append(closes, func() error {
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) //nolint
return tracer.Close(ctx)

View File

@@ -7,6 +7,7 @@ import (
"github.com/zhufuyi/sponge/configs"
"github.com/zhufuyi/sponge/internal/config"
//"github.com/zhufuyi/sponge/internal/rpcclient"
"github.com/zhufuyi/sponge/pkg/logger"
@@ -36,7 +37,7 @@ func Config() {
)
// initializing tracing
if cfg.App.EnableTracing {
if cfg.App.EnableTrace {
tracer.InitWithConfig(
cfg.App.Name,
cfg.App.Env,

View File

@@ -27,7 +27,7 @@ func RegisterClose(servers []app.IServer) []app.Close {
//})
// close tracing
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
closes = append(closes, func() error {
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) //nolint
return tracer.Close(ctx)

View File

@@ -41,7 +41,7 @@ func Config() {
//model.InitCache(cfg.App.CacheType)
// initializing tracing
if cfg.App.EnableTracing {
if cfg.App.EnableTrace {
tracer.InitWithConfig(
cfg.App.Name,
cfg.App.Env,

View File

@@ -33,7 +33,7 @@ func RegisterClose(servers []app.IServer) []app.Close {
//}
// close tracing
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
closes = append(closes, func() error {
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) //nolint
return tracer.Close(ctx)

View File

@@ -40,7 +40,7 @@ func Config() {
model.InitCache(cfg.App.CacheType)
// initializing tracing
if cfg.App.EnableTracing {
if cfg.App.EnableTrace {
tracer.InitWithConfig(
cfg.App.Name,
cfg.App.Env,

View File

@@ -33,7 +33,7 @@ func RegisterClose(servers []app.IServer) []app.Close {
}
// close tracing
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
closes = append(closes, func() error {
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) //nolint
return tracer.Close(ctx)

View File

@@ -41,7 +41,7 @@ func Config() {
//model.InitCache(cfg.App.CacheType)
// initializing tracing
if cfg.App.EnableTracing {
if cfg.App.EnableTrace {
tracer.InitWithConfig(
cfg.App.Name,
cfg.App.Env,

View File

@@ -33,7 +33,7 @@ func RegisterClose(servers []app.IServer) []app.Close {
//}
// close tracing
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
closes = append(closes, func() error {
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) //nolint
return tracer.Close(ctx)

View File

@@ -40,7 +40,7 @@ func Config() {
model.InitCache(cfg.App.CacheType)
// initializing tracing
if cfg.App.EnableTracing {
if cfg.App.EnableTrace {
tracer.InitWithConfig(
cfg.App.Name,
cfg.App.Env,

View File

@@ -33,7 +33,7 @@ func RegisterClose(servers []app.IServer) []app.Close {
}
// close tracing
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
closes = append(closes, func() error {
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) //nolint
return tracer.Close(ctx)

View File

@@ -5,8 +5,9 @@ import (
"fmt"
"strings"
"github.com/spf13/cobra"
"github.com/zhufuyi/sponge/pkg/replacer"
"github.com/spf13/cobra"
)
// RPCClientCommand generate rpc client codes

View File

@@ -10,7 +10,7 @@ import (
"github.com/spf13/cobra"
)
// RPCClientCommand generate rpc gateway server codes base on protobuf file
// RPCGwPbCommand generate rpc gateway server codes base on protobuf file
func RPCGwPbCommand() *cobra.Command {
var (
moduleName string // module name for go.mod

View File

@@ -14,7 +14,7 @@ import (
"github.com/spf13/cobra"
)
// RPCClientCommand generate service codes
// ServiceCommand generate service codes
func ServiceCommand() *cobra.Command {
var (
moduleName string // module name for go.mod

View File

@@ -11,7 +11,7 @@ app:
enableMetrics: true # whether to enable indicator collection, true:enable, false:disable
enableLimit: false # whether to turn on rate limiting (adaptive), true:on, false:off
enableCircuitBreaker: false # whether to turn on circuit breaker(adaptive), true:on, false:off
enableTracing: false # whether to enable tracking, true:enable, false:disable, if true jaeger configuration must be set
enableTrace: false # whether to enable trace, true:enable, false:disable, if true jaeger configuration must be set
tracingSamplingRate: 1.0 # tracing sampling rate, between 0 and 1, 0 means no sampling, 1 means sampling all links
registryDiscoveryType: "" # registry and discovery types: consul, etcd, nacos, if empty, registration and discovery are not used
cacheType: "memory" # cache type, memory, redis, if set to redis, must set redis configuration

View File

@@ -16,7 +16,7 @@ data:
enableMetrics: true # whether to enable indicator collection, true:enable, false:disable
enableLimit: false # whether to turn on rate limiting (adaptive), true:on, false:off
enableCircuitBreaker: false # whether to turn on circuit breaker(adaptive), true:on, false:off
enableTracing: false # whether to enable tracking, true:enable, false:disable, if true jaeger configuration must be set
enableTrace: false # whether to enable trace, true:enable, false:disable, if true jaeger configuration must be set
tracingSamplingRate: 1.0 # tracing sampling rate, between 0 and 1, 0 means no sampling, 1 means sampling all links
registryDiscoveryType: "" # registry and discovery types: consul, etcd, nacos, if empty, registration and discovery are not used
cacheType: "memory" # cache type, memory, redis, if set to redis, must set redis configuration

View File

@@ -63,7 +63,7 @@ type App struct {
EnableMetrics bool `yaml:"enableMetrics" json:"enableMetrics"`
EnablePprof bool `yaml:"enablePprof" json:"enablePprof"`
EnableStat bool `yaml:"enableStat" json:"enableStat"`
EnableTracing bool `yaml:"enableTracing" json:"enableTracing"`
EnableTrace bool `yaml:"enableTrace" json:"enableTrace"`
Env string `yaml:"env" json:"env"`
Host string `yaml:"host" json:"host"`
Name string `yaml:"name" json:"name"`

View File

@@ -44,7 +44,7 @@ func InitMysql() {
opts = append(opts, mysql.WithLog())
}
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
opts = append(opts, mysql.WithEnableTrace())
}
@@ -119,7 +119,7 @@ func InitRedis() {
goredis.WithReadTimeout(time.Duration(config.Get().Redis.ReadTimeout) * time.Second),
goredis.WithWriteTimeout(time.Duration(config.Get().Redis.WriteTimeout) * time.Second),
}
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
opts = append(opts, goredis.WithEnableTrace())
}

View File

@@ -20,7 +20,7 @@ func TestInitMysql(t *testing.T) {
panic(err)
}
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().Mysql.EnableLog = true
time.Sleep(time.Millisecond * 10)
@@ -78,7 +78,7 @@ func TestInitRedis(t *testing.T) {
assert.NoError(t, err)
// change config error test
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().Redis.Dsn = "default:123456@127.0.0.1:6379/0"
redisCli = nil
_ = CloseRedis()

View File

@@ -59,7 +59,7 @@ func NewRouter() *gin.Engine {
}
// trace middleware
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
r.Use(middleware.Tracing(config.Get().App.Name))
}

View File

@@ -58,7 +58,7 @@ func NewRouter_pbExample() *gin.Engine { //nolint
}
// trace middleware
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
r.Use(middleware.Tracing(config.Get().App.Name))
}

View File

@@ -22,7 +22,7 @@ func TestNewRouter_pbExample(t *testing.T) {
}
config.Get().App.EnableMetrics = true
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().App.EnablePprof = true
config.Get().App.EnableLimit = true
config.Get().App.EnableCircuitBreaker = true

View File

@@ -21,7 +21,7 @@ func TestNewRouter(t *testing.T) {
}
config.Get().App.EnableMetrics = false
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().App.EnablePprof = true
config.Get().App.EnableLimit = true
config.Get().App.EnableCircuitBreaker = true

View File

@@ -87,7 +87,7 @@ func NewServerNameExampleRPCConn() {
cliOptions = append(cliOptions, grpccli.WithDiscovery(iDiscovery))
}
if cfg.App.EnableTracing {
if cfg.App.EnableTrace {
cliOptions = append(cliOptions, grpccli.WithEnableTrace())
}
if cfg.App.EnableCircuitBreaker {

View File

@@ -135,7 +135,7 @@ func (s *grpcServer) serverOptions() []grpc.ServerOption {
}
// trace interceptor
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
unaryServerInterceptors = append(unaryServerInterceptors, interceptor.UnaryServerTracing())
}

View File

@@ -24,7 +24,7 @@ func TestGRPCServer(t *testing.T) {
}
config.Get().App.EnableMetrics = true
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().App.EnablePprof = true
config.Get().App.EnableLimit = true
config.Get().App.EnableCircuitBreaker = true
@@ -50,7 +50,7 @@ func TestGRPCServerMock(t *testing.T) {
t.Fatal(err)
}
config.Get().App.EnableMetrics = true
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().App.EnablePprof = true
config.Get().App.EnableLimit = true
config.Get().App.EnableCircuitBreaker = true

View File

@@ -24,7 +24,7 @@ func TestHTTPServer(t *testing.T) {
t.Fatal(err)
}
config.Get().App.EnableMetrics = true
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().App.EnablePprof = true
config.Get().App.EnableLimit = true
config.Get().App.EnableCircuitBreaker = true
@@ -62,7 +62,7 @@ func TestHTTPServerMock(t *testing.T) {
t.Fatal(err)
}
config.Get().App.EnableMetrics = true
config.Get().App.EnableTracing = true
config.Get().App.EnableTrace = true
config.Get().App.EnablePprof = true
config.Get().App.EnableLimit = true
config.Get().App.EnableCircuitBreaker = true

View File

@@ -80,7 +80,7 @@ func initUserExampleServiceClient() serverNameExampleV1.UserExampleServiceClient
cliOptions = append(cliOptions, grpccli.WithDiscovery(iDiscovery))
}
if config.Get().App.EnableTracing {
if config.Get().App.EnableTrace {
cliOptions = append(cliOptions, grpccli.WithEnableTrace())
}
if config.Get().App.EnableCircuitBreaker {

View File

@@ -21,7 +21,7 @@ func (o *options) apply(opts ...Option) {
// default settings
func defaultOptions() *options {
return &options{
enableTrace: false, // whether to enable link tracking, default off
enableTrace: false, // whether to enable trace, default off
}
}

View File

@@ -1,6 +1,6 @@
## grpccli
grpc client with support for service discovery, logging, load balancing, link tracking, metrics, retries, circuit breaker.
grpc client with support for service discovery, logging, load balancing, trace, metrics, retries, circuit breaker.
### Example of use

View File

@@ -76,6 +76,10 @@ func dial(ctx context.Context, endpoint string, isSecure bool, opts ...Option) (
unaryClientInterceptors = append(unaryClientInterceptors, interceptor.UnaryClientRetry())
}
if o.enableTrace {
unaryClientInterceptors = append(unaryClientInterceptors, interceptor.UnaryClientTracing())
}
unaryClientInterceptors = append(unaryClientInterceptors, o.unaryInterceptors...)
streamClientInterceptors = append(streamClientInterceptors, o.streamInterceptors...)

View File

@@ -210,7 +210,7 @@ func InitTrace(serviceName string) {
tracer.Init(exporter, resource) // collect all by default
}
// set up link tracking on the client side
// set up trace on the client side
func getDialOptions() []grpc.DialOption {
var options []grpc.DialOption

55
pkg/tracer/span.go Normal file
View File

@@ -0,0 +1,55 @@
package tracer
import (
"context"
"fmt"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
var traceName = "unknown"
// SetTraceName each service corresponds to a traceName
func SetTraceName(name string) {
if name != "" {
traceName = name
}
}
// NewSpan create a span, to end a span you must call span.End()
func NewSpan(ctx context.Context, spanName string, tags map[string]interface{}) (context.Context, trace.Span) {
var opts []trace.SpanStartOption
for k, v := range tags {
var tag attribute.KeyValue
switch v.(type) {
case nil:
continue
case bool:
tag = attribute.Bool(k, v.(bool))
case string:
tag = attribute.String(k, v.(string))
case []string:
tag = attribute.StringSlice(k, v.([]string))
case int:
tag = attribute.Int(k, v.(int))
case []int:
tag = attribute.IntSlice(k, v.([]int))
case int64:
tag = attribute.Int64(k, v.(int64))
case []int64:
tag = attribute.Int64Slice(k, v.([]int64))
case float64:
tag = attribute.Float64(k, v.(float64))
case []float64:
tag = attribute.Float64Slice(k, v.([]float64))
default:
tag = attribute.String(k, fmt.Sprintf("%+v", v))
}
opts = append(opts, trace.WithAttributes(tag))
}
return otel.Tracer(traceName).Start(ctx, spanName, opts...)
}

28
pkg/tracer/span_test.go Normal file
View File

@@ -0,0 +1,28 @@
package tracer
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewSpan(t *testing.T) {
SetTraceName("foo")
tags := map[string]interface{}{
"foo1": nil,
"foo2": true,
"foo3": "bar",
"foo4": []string{"bar"},
"foo5": 1,
"foo6": []int{1},
"foo7": int64(1),
"foo8": []int64{1},
"foo9": 3.14,
"foo10": []float64{3.14},
"foo11": map[string]string{"foo": "bar"},
}
_, span := NewSpan(context.Background(), "fooSpan", tags)
assert.NotNil(t, span)
}

View File

@@ -59,4 +59,6 @@ func InitWithConfig(appName string, appEnv string, appVersion string,
}
Init(exporter, res, jaegerSamplingRate)
SetTraceName(appName)
}

View File

@@ -8,12 +8,31 @@ Switch to the elasticsearch directory and start the service
### Start jaeger service
Switch to the jaeger directory, open the. env environment variable, and fill in the url, login account, and password of elastic search
Switch to the jaeger directory, open the .env file, and fill in the url, login account, and password of elastic search
Start jaeger
Start the jaeger service
> docker-compose up -d
Check whether it is normal
> docker-compose ps
Visit the http://192.168.3.37:16686 query page in your browser
<br>
#### port
| Port | Protocol | Component | Function |
|-------|----------|-----------|----------------------------------------------------------------------------------------------|
| 6831 | UDP | agent | accept jaeger.thrift over Thrift-compact protocol (used by most SDKs) |
| 6832 | UDP | agent | accept jaeger.thrift over Thrift-binary protocol (used by Node.js SDK) |
| 5775 | UDP | agent | (deprecated) accept zipkin.thrift over compact Thrift protocol (used by legacy clients only) |
| 5778 | HTTP | agent | serve configs (sampling, etc.) |
| 16686 | HTTP | query | serve frontend |
| 4317 | HTTP | collector | accept OpenTelemetry Protocol (OTLP) over gRPC, if enabled |
| 4318 | HTTP | collector | accept OpenTelemetry Protocol (OTLP) over HTTP, if enabled |
| 14268 | HTTP | collector | accept jaeger.thrift directly from clients |
| 14250 | HTTP | collector | accept model.proto |
| 9411 | HTTP | collector | Zipkin compatible endpoint (optional |