-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: rfc for tracing in pixiu #1
base: main
Are you sure you want to change the base?
Conversation
|
||
The tracerManager structure is as follows: | ||
```go | ||
type TracerManager struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
是不是有一个抽象的 TracerManager,然后其中一个实现是 JaegerManager,这样后续更容易扩展其他的分布式追踪后端?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TracerManager是管理所有的driver,目前只有默认的JaegerDriver,后续可以根据需要扩展成map。
defer rootSpan.Finish() | ||
s.ls.FilterChain.ServeHTTP(w, r.WithContext(ctx)) | ||
|
||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
可以分别添加一下,在 Networkfilter 和 HttpFilter 中使用 Tracer 进行上报的案例。比如说在 https://github.com/apache/dubbo-go-pixiu/blob/develop/pkg/filter/http/remote/call.go 中或者 https://github.com/apache/dubbo-go-pixiu/blob/develop/pkg/common/grpc/manager.go 也想要进行记录
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
对tracer.go进行修改,及时删改追踪完成的trace。
type Tracer struct {
Id String
T opentracing.Tracer
closer io.Closer
}
func (t *Tracer) Close() {
delete(holder.tracers, t.Id)
t.Close()
}
当http_listener监听到HTTP请求:
tracer, _, _ := NewTracer("HTTP")
defer tracer.Close()
rootSpan := tracer.StartSpan("http-listener")
ctx := tracer.T.ContextWithSpan(r.Context(), rootSpan)
defer rootSpan.Finish()
s.ls.FilterChain.ServeHTTP(w, r.WithContext(ctx))
HTTPConnectionManager 中追踪:
我们抽离出获取Tracer的公共方法:
// TODO 增强代码健壮性
func GetTracer(protocolName, tracerId string) api.Tracer {
driver := GetTraceDriverManager().getDriver()
return driver.getTracer(prtocolName, traceId);
}
func (hcm *HttpConnectionManager) ServeHTTP(w stdHttp.ResponseWriter, r *stdHttp.Request) {
...
hc.Reset()
traceId := r.Header.Get("trace-id")
tracer := trace.GetTracer("HTTP", traceId)
hcmSpan, spanContext := opentracing.StartSpanFromContextWithTracer(r.Context(), tracer, "Filter---HttpConnectionManager封装HttpContext")
hc.Ctx = spanContext
defer hcmSpan.Finish()
err := hcm.Handle(hc)
...
}
func (hcm *HttpConnectionManager) Handle(hc *pch.HttpContext) error {
// hc.Ctx = context.Background()
traceId := hc.Request.Header.Get("trace-id")
tracer := trace.GetTracer("HTTP", traceId)
hcmSpan, spanContext := opentracing.StartSpanFromContextWithTracer(r.Context(), tracer, "Filter---HttpConnectionManager查找路由,确定集群")
hc.Ctx = spanContext
defer hcmSpan.Finish()
err := hcm.findRoute(hc)
if err != nil {
return err
}
hcm.handleHTTPRequest(hc)
return nil
}
Note:hcm这里是一个空Context,这里直接注释了源代码。另外,在NetWorkFilter和HttpFilter中的处理过程与上述过程基本一致,不再演示。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个看起来不错,将一些细节隐藏到共有的抽象方法中,真正要使用 tracer 进行记录的位置只感知项目提供的接口,不需要了解底层的具体实现
Disabled bool | ||
//默认是HTTP | ||
ServiceName string | ||
Driver string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
是否需要不同 driver 所特有的 config 字段?比如 skywalking 的配置和 jaeger 的配置数据可能有些差异
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
目前只考虑了jaeger,可以考虑扩充:
type TracerConfigs struct {
jaegerConfig JaegerConfig
skywalking SkyWalkingConfig
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
一阶段可以只支持 jaeger,但是需要考虑并给出扩展机制,可以按照后续要支持 skywalking为例进行说明。比如说 :
- 不同的driver类型如何进行识别和读取不同的config设置到对应的变量中;
- 初始化建立 TracerProvider 时可能的差异怎么处理;
- 不同 lib 如果有 api 方面差异,如何统一使用,比如说 StartSpan。
可以和下面的 DriverManager 一起进行扩展性描述。
rename file name to ur [$feature-$version] |
model包下的TraceConfig如下: type TracerConfig struct {
Name string
Sampler Sampler
Config interface{}
}
type Sampler struct {
Type string
Param float64
} 系统的trace采用otel,driver结构如下: type Holder struct {
Tracers map[string]protocol.Trace
Id uint64
}
type TraceDriver struct {
holders map[protocolName]*Holder
tp *sdktrace.TracerProvider
context context.Context
} holder中Tracers的键会使用Id进行拼接之后原子递增,保证唯一性。在TraceDriverManager的初始化中,主要是对driver的初始化,包括设置exprter(支持jaeger,otlp等)和TraceProvider。 func (driver *TraceDriver) Init(bs *model.Bootstrap) *TraceDriver {
config := bs.Trace
ctx := context.Background()
exp, err := newExporter(ctx, config)
if err != nil {
//TODO 错误处理
return nil
}
provider := newTraceProvider(exp, config)
otel.SetTracerProvider(provider)
return &TraceDriver{
tp: provider,
}
} 其中可根据config的name属性选择不同的exporter设置,并在TraceProvider的生成中设置采样率。 为支持不同协议请求的Tracer,提供Trace接口,并提供默认实现Tracer。如果其他协议请求(比如HTTP)支持自己协议的span方法,重写部分方法即可。 type Trace interface {
GetId() string
StartSpan(name string, request interface{}) (context.Context, trace.Span)
StartSpanFromContext(name string, tx context.Context) (context.Context, trace.Span)
Close()
}
type Tracer struct {
Id string
T trace.Tracer
H *trace2.Holder
}
type HTTPTracer struct {
*Tracer
}
func (t *Tracer) GetId() string {
return t.Id
}
func (t *Tracer) Close() {
delete(t.H.Tracers, t.Id)
}
func (t *Tracer) StartSpan(name string, request interface{}) (context.Context, trace.Span) {
return t.T.Start(request.(*http.Request).Context(), name)
}
func (t *Tracer) StartSpanFromContext(name string, ctx context.Context) (context.Context, trace.Span) {
return t.T.Start(ctx, name)
}
func (t *HTTPTracer) StartSpan(name string, request interface{}) (context.Context, trace.Span) {
...
}
func (t *HTTPTracer) StartSpanFromContext(name string, ctx context.Context) (context.Context, trace.Span) {
...
} 最终在程序中调用流程如下: //http_listener.go
func (s *DefaultHttpWorker) ServeHTTP(w http.ResponseWriter, r *http.Request) {
tracer := trace.NewTracer(trace.HTTP)
defer tracer.Close()
ctx, span := tracer.StartSpan("http", r)
defer span.End()
r.Header.Set("trace-id", tracer.GetId())
s.ls.FilterChain.ServeHTTP(w, r.WithContext(ctx))
}
//manager.go
func (hcm *HttpConnectionManager) ServeHTTP(w stdHttp.ResponseWriter, r *stdHttp.Request) {
...
traceId := r.Header.Get("trace-id")
tracer, _ := trace.GetTracer(trace.HTTP, traceId)
ctx, span := tracer.StartSpanFromContext("HttpConnectionManager", hc.Ctx)
defer span.End()
hc.Ctx = ctx
...
} |
The main ideas about this proposal are as follows: