Skip to content

Commit 5418788

Browse files
committed
feat: add the gRPC interceptor logic, add the open-telemetry logic, update the readme
1 parent 6321239 commit 5418788

File tree

8 files changed

+158
-18
lines changed

8 files changed

+158
-18
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ Microservice framework implemented based on Golang.
6161
│ ├─app 服务启动相关的结构体
6262
│ │ └─app.go 这个 app 是 GRPC,服务名称,注册中心等的集合
6363
│ ├─code
64-
│ ├─core
64+
│ ├─core 底层共通核心的包
6565
│ │ ├─metric
66-
│ │ └─trace
66+
│ │ └─trace 链路追踪,采用 opentemlemetry
6767
│ ├─registry
6868
│ │ └─consul 服务注册中心相关逻辑,参考 kratos
6969
│ └─server

configs/admin/admin.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,10 @@ server:
2424
middlewares: # 中间件
2525
- recovery # panic 恢复
2626
- cors # 跨域
27-
- context
27+
- context
28+
29+
telemetry:
30+
Name: user-srv
31+
Endpoint: http://127.0.0.1:14268/api/traces
32+
Sampler: 1.0
33+
Bathcer: jaeger

gmicro/core/trace/agent.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package trace
2+
3+
import (
4+
"sync"
5+
6+
"github.com/CoderI421/gframework/pkg/log"
7+
8+
"go.opentelemetry.io/otel"
9+
"go.opentelemetry.io/otel/propagation"
10+
11+
"go.opentelemetry.io/otel/exporters/jaeger"
12+
"go.opentelemetry.io/otel/exporters/zipkin"
13+
"go.opentelemetry.io/otel/sdk/resource"
14+
"go.opentelemetry.io/otel/sdk/trace"
15+
semconv "go.opentelemetry.io/otel/semconv/v1.18.0"
16+
)
17+
18+
const (
19+
kindJaeger = "jaeger"
20+
kingZipkin = "zipkin"
21+
)
22+
23+
var (
24+
// struct{}空结构体 不占内存,zerobase
25+
agents = make(map[string]struct{})
26+
lock sync.Mutex
27+
)
28+
29+
func InitAgent(o Options) {
30+
lock.Lock()
31+
defer lock.Unlock()
32+
33+
// 如果已经存在了,就不再初始化
34+
_, ok := agents[o.Endpoint]
35+
if ok {
36+
return
37+
}
38+
39+
err := startAgent(o)
40+
if err != nil {
41+
return
42+
}
43+
// 无错误后,将endpoint加入到map中
44+
agents[o.Endpoint] = struct{}{}
45+
}
46+
47+
func startAgent(o Options) error {
48+
var sexp trace.SpanExporter
49+
var err error
50+
51+
opts := []trace.TracerProviderOption{
52+
// 采样率
53+
trace.WithSampler(trace.ParentBased(trace.TraceIDRatioBased(o.Sampler))),
54+
// 设置service
55+
trace.WithResource(resource.NewSchemaless(semconv.ServiceNameKey.String(o.Name))),
56+
}
57+
58+
if len(o.Endpoint) > 0 {
59+
switch o.Batcher {
60+
case kindJaeger:
61+
sexp, err = jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(o.Endpoint)))
62+
if err != nil {
63+
return err
64+
}
65+
case kingZipkin:
66+
sexp, err = zipkin.New(o.Endpoint)
67+
if err != nil {
68+
return err
69+
}
70+
default:
71+
return nil
72+
}
73+
opts = append(opts, trace.WithBatcher(sexp))
74+
}
75+
76+
// 创建一个新的trace provider,将初始化的参数传入
77+
tp := trace.NewTracerProvider(opts...)
78+
// 设置全局的trace provider
79+
otel.SetTracerProvider(tp)
80+
// 设置全局的 propagator 传播提取器
81+
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
82+
// 设置 open-telemetry 的错误处理函数
83+
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
84+
log.Errorf("[otel] error: %v", err)
85+
}))
86+
return nil
87+
}

gmicro/core/trace/options.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package trace
2+
3+
// Options 这个配置和 业务中 app 中的 tracing 冗余,为的是将 tracing 从业务中解耦出来
4+
type Options struct {
5+
Name string `json:"name"` // jeager 名称
6+
Endpoint string `json:"endpoint"` // jeager 地址
7+
Sampler float64 `json:"sampler"` // 采样率
8+
Batcher string `json:"batcher"` // 批量发送
9+
}

gmicro/server/rpcserver/client.go

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import (
88
grpcinsecure "google.golang.org/grpc/credentials/insecure"
99

1010
"github.com/CoderI421/gframework/gmicro/registry"
11-
"github.com/CoderI421/gframework/gmicro/server/rpcserver/clientinterceptors"
1211
"github.com/CoderI421/gframework/gmicro/server/rpcserver/resolver/discovery"
1312
"github.com/CoderI421/gframework/pkg/log"
13+
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
1414
)
1515

1616
type ClientOption func(o *clientOptions)
@@ -32,65 +32,75 @@ type clientOptions struct {
3232

3333
// 客户端的日志
3434
logger log.Logger
35+
36+
// 是否开启链路追踪
37+
enableTracing bool
3538
}
3639

37-
// 设置服务端的地址
40+
// WithEndpoint 设置服务端的地址
3841
func WithEndpoint(endpoint string) ClientOption {
3942
return func(o *clientOptions) {
4043
o.endpoint = endpoint
4144
}
4245
}
4346

44-
// 设置超时时间
47+
// WithClientTimeout 设置超时时间
4548
func WithClientTimeout(timeout time.Duration) ClientOption {
4649
return func(o *clientOptions) {
4750
o.timeout = timeout
4851
}
4952
}
5053

51-
// 设置服务发现
54+
// WithDiscovery 设置服务发现
5255
func WithDiscovery(d registry.Discovery) ClientOption {
5356
return func(o *clientOptions) {
5457
o.discovery = d
5558
}
5659
}
5760

58-
// 设置拦截器
61+
// WithClientUnaryInterceptor 设置拦截器
5962
func WithClientUnaryInterceptor(in ...grpc.UnaryClientInterceptor) ClientOption {
6063
return func(o *clientOptions) {
6164
o.unaryInts = in
6265
}
6366
}
6467

65-
// 设置stream拦截器
68+
// WithClientStreamInterceptor 设置stream拦截器
6669
func WithClientStreamInterceptor(in ...grpc.StreamClientInterceptor) ClientOption {
6770
return func(o *clientOptions) {
6871
o.streamInts = in
6972
}
7073
}
7174

72-
// 设置grpc的dial选项
75+
// WithClientOptions 设置grpc的dial选项
7376
func WithClientOptions(opts ...grpc.DialOption) ClientOption {
7477
return func(o *clientOptions) {
7578
o.rpcOpts = opts
7679
}
7780
}
7881

79-
// 设置负载均衡器
82+
// WithBalancerName 设置负载均衡器
8083
func WithBalancerName(name string) ClientOption {
8184
return func(o *clientOptions) {
8285
o.balancerName = name
8386
}
8487
}
8588

86-
// 设置日志
89+
// WithClientLogger 设置日志
8790
func WithClientLogger(logger log.Logger) ClientOption {
8891
return func(o *clientOptions) {
8992
o.logger = logger
9093
}
9194
}
9295

93-
// 非安全拨号
96+
// WithClientTracing 设置链路追踪
97+
func WithClientTracing() ClientOption {
98+
return func(o *clientOptions) {
99+
o.enableTracing = true
100+
}
101+
}
102+
103+
// DialInsecure 非安全拨号
94104
func DialInsecure(ctx context.Context, opts ...ClientOption) (*grpc.ClientConn, error) {
95105
return dial(ctx, true, opts...)
96106
}
@@ -102,8 +112,9 @@ func Dial(ctx context.Context, opts ...ClientOption) (*grpc.ClientConn, error) {
102112
func dial(ctx context.Context, insecure bool, opts ...ClientOption) (*grpc.ClientConn, error) {
103113
// 默认配置
104114
options := clientOptions{
105-
timeout: 2000 * time.Millisecond,
106-
balancerName: "round_robin",
115+
timeout: 2000 * time.Millisecond,
116+
balancerName: "round_robin",
117+
enableTracing: true,
107118
}
108119

109120
for _, o := range opts {
@@ -112,7 +123,12 @@ func dial(ctx context.Context, insecure bool, opts ...ClientOption) (*grpc.Clien
112123

113124
//TODO 客户端默认拦截器
114125
ints := []grpc.UnaryClientInterceptor{
115-
clientinterceptors.TimeoutInterceptor(options.timeout),
126+
//应该是闭包特性,直接调用后返回resp供grpc拦截器调用
127+
//otelgrpc.UnaryClientInterceptor(),
128+
}
129+
// 可给用户自己设置需不需链路追踪
130+
if options.enableTracing {
131+
ints = append(ints, otelgrpc.UnaryClientInterceptor())
116132
}
117133
streamInts := []grpc.StreamClientInterceptor{}
118134

gmicro/server/rpcserver/server.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"net/url"
77
"time"
88

9+
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
10+
911
"github.com/CoderI421/gframework/pkg/log"
1012

1113
apimd "github.com/CoderI421/gframework/api/metadata"
@@ -61,6 +63,7 @@ func NewServer(opts ...ServerOption) *Server {
6163
//TODO 我们现在希望用户不设置拦截器的情况下,我们会自动默认加上一些必须的拦截器 , crash tracing
6264
unaryInts := []grpc.UnaryServerInterceptor{
6365
srvints.UnaryCrashInterceptor,
66+
otelgrpc.UnaryServerInterceptor(), // 设置链路追踪的拦截器
6467
//srvints.UnaryTimeoutInterceptor(srv.timeout),
6568
}
6669
//timeout可以交给用户设置,不设置就不用此拦截器

go.mod

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ require (
7878
github.com/mitchellh/mapstructure v1.5.0 // indirect
7979
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
8080
github.com/modern-go/reflect2 v1.0.2 // indirect
81+
github.com/openzipkin/zipkin-go v0.4.1 // indirect
8182
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
8283
github.com/pmezard/go-difflib v1.0.0 // indirect
8384
github.com/rivo/uniseg v0.2.0 // indirect
@@ -87,12 +88,16 @@ require (
8788
github.com/subosito/gotenv v1.4.2 // indirect
8889
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
8990
github.com/ugorji/go/codec v1.2.9 // indirect
91+
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.41.1 // indirect
92+
go.opentelemetry.io/otel/exporters/jaeger v1.15.1 // indirect
93+
go.opentelemetry.io/otel/exporters/zipkin v1.15.1 // indirect
94+
go.opentelemetry.io/otel/metric v0.38.1 // indirect
9095
go.uber.org/atomic v1.9.0 // indirect
9196
go.uber.org/multierr v1.8.0 // indirect
9297
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
93-
golang.org/x/net v0.8.0 // indirect
98+
golang.org/x/net v0.9.0 // indirect
9499
golang.org/x/sys v0.7.0 // indirect
95-
golang.org/x/text v0.8.0 // indirect
100+
golang.org/x/text v0.9.0 // indirect
96101
gopkg.in/ini.v1 v1.67.0 // indirect
97102
gopkg.in/yaml.v3 v3.0.1 // indirect
98103
)

go.sum

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
919919
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
920920
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
921921
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
922+
github.com/openzipkin/zipkin-go v0.4.1 h1:kNd/ST2yLLWhaWrkgchya40TJabe8Hioj9udfPcEO5A=
923+
github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAyg7Qt6/I9HecM=
922924
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
923925
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
924926
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
@@ -1049,9 +1051,17 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
10491051
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
10501052
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
10511053
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
1054+
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.41.1 h1:Ei1FUQ5CbSNkl2o/XAiksXSyQNAeJBX3ivqJpJ254Ak=
1055+
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.41.1/go.mod h1:f7TOPTlEcliCBlOYPuNnZTuND71MVTAoINWIt1SmP/c=
10521056
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
10531057
go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8=
10541058
go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc=
1059+
go.opentelemetry.io/otel/exporters/jaeger v1.15.1 h1:x3SLvwli0OyAJapNcOIzf1xXBRBA+HD3elrMQmFfmXo=
1060+
go.opentelemetry.io/otel/exporters/jaeger v1.15.1/go.mod h1:0Ck9b5oLL/bFZvfAEEqtrb1U0jZXjm5fWXMCOCG3vvM=
1061+
go.opentelemetry.io/otel/exporters/zipkin v1.15.1 h1:B6s/o48bx00ayJu7F+jIMJfhPTyxW+S8vthjTZMNBj0=
1062+
go.opentelemetry.io/otel/exporters/zipkin v1.15.1/go.mod h1:EjjV7/YfYXG+khxCOfG6PPeRGoOmtcSusyW66qPqpRQ=
1063+
go.opentelemetry.io/otel/metric v0.38.1 h1:2MM7m6wPw9B8Qv8iHygoAgkbejed59uUR6ezR5T3X2s=
1064+
go.opentelemetry.io/otel/metric v0.38.1/go.mod h1:FwqNHD3I/5iX9pfrRGZIlYICrJv0rHEUl2Ln5vdIVnQ=
10551065
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
10561066
go.opentelemetry.io/otel/sdk v1.15.1 h1:5FKR+skgpzvhPQHIEfcwMYjCBr14LWzs3uSqKiQzETI=
10571067
go.opentelemetry.io/otel/sdk v1.15.1/go.mod h1:8rVtxQfrbmbHKfqzpQkT5EzZMcbMBwTzNAggbEAM0KA=
@@ -1210,6 +1220,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
12101220
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
12111221
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
12121222
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
1223+
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
1224+
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
12131225
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
12141226
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
12151227
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1379,6 +1391,8 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
13791391
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
13801392
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
13811393
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
1394+
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
1395+
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
13821396
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
13831397
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
13841398
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

0 commit comments

Comments
 (0)