[TOC] > [opencensus 官网](https://opencensus.io/quickstart/go/metrics/#0) ## opencensus ## zipkin 1. 将Trace ID记录到日志,方便追踪 ## 例子 **需要先启动 zipkin** `docker run -d -p 9411:9411 openzipkin/zipkin ` ### hello word 追踪http请求耗时情况 <details> <summary>main.go</summary> ``` package main import ( "log" "math/rand" "net/http" "time" "contrib.go.opencensus.io/exporter/zipkin" "go.opencensus.io/plugin/ochttp" "go.opencensus.io/stats/view" "go.opencensus.io/trace" openzipkin "github.com/openzipkin/zipkin-go" zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http" ) func registerZipkin(){ //设置Tags 第一参数为服务器名 ,第二为真实的标记的ip&port,不用实际程序,只做标记 localEndpoint, err := openzipkin.NewEndpoint("golangsvc", "xxxxx:port") if err != nil { log.Fatalf("Failed to create Zipkin exporter: %v", err) } reporter := zipkinHTTP.NewReporter("http://192.168.0.110:9411/api/v2/spans") exporter := zipkin.NewExporter(reporter, localEndpoint) trace.RegisterExporter(exporter) trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) } func main() { //初始化一个发送给 zipkin 的程序 registerZipkin() mux := http.NewServeMux() mux.HandleFunc("/list", list) h := &ochttp.Handler{Handler: mux} if err := view.Register(ochttp.DefaultServerViews...); err != nil { log.Fatal("Failed to register ochttp.DefaultServerViews") } log.Printf("Server listening! ...") log.Fatal(http.ListenAndServe(":8080", h)) } func list(w http.ResponseWriter, r *http.Request) { log.Printf("Serving request: %s", r.URL.Path) database(r) serviceb(r) time.Sleep(3*time.Second) w.Write([]byte("Hello, world!")) } // 每个一个 r.context() 都是片段的时间消耗 // _, span := trace.StartSpan(r.Context(), "database") // defer span.End() func database(r *http.Request) { cache(r) _, span := trace.StartSpan(r.Context(), "database") defer span.End() time.Sleep(time.Duration(rand.Intn(977)+300) * time.Millisecond) } func cache(r *http.Request) { _, span := trace.StartSpan(r.Context(), "cache") defer span.End() time.Sleep(time.Duration(rand.Intn(100)+1) * time.Millisecond) } func serviceb(r *http.Request) { _, span := trace.StartSpan(r.Context(), "serviceb") defer span.End() time.Sleep(time.Duration(rand.Intn(800)+200) * time.Millisecond) servicec(r) } func servicec(r *http.Request) { _, span := trace.StartSpan(r.Context(), "servicec") defer span.End() time.Sleep(time.Duration(rand.Intn(700)+100) * time.Millisecond) } ``` </details> <br/> ``` go run main.go ``` ### 非http程序 <details> <summary>main.go</summary> ``` package main import ( "bytes" "context" "encoding/binary" "fmt" "log" "time" "contrib.go.opencensus.io/exporter/zipkin" "go.opencensus.io/trace" openzipkin "github.com/openzipkin/zipkin-go" zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http" ) func main() { // 1. 配置Zipkin出口 localEndpoint, err := openzipkin.NewEndpoint("go-quickstart", "192.168.1.5:5454") if err != nil { log.Fatalf("Failed to create the local zipkinEndpoint: %v", err) } reporter := zipkinHTTP.NewReporter("http://192.168.0.110:9411/api/v2/spans") ze := zipkin.NewExporter(reporter, localEndpoint) trace.RegisterExporter(ze) // 配置100%的采样率,否则,一些痕迹将采样 trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) // 3. 创建一个跨度与背景环境,使这个父跨度 // span 必须关闭 ctx, span := trace.StartSpan(context.Background(), "main") defer span.End() for i := 0; i < 10; i++ { doWork(ctx) } } func doWork(ctx context.Context) { _, span := trace.StartSpan(ctx, "doWork") defer span.End() fmt.Println("doing busy work") time.Sleep(80 * time.Millisecond) buf := bytes.NewBuffer([]byte{0xFF, 0x00, 0x00, 0x00}) num, err := binary.ReadVarint(buf) if err != nil { // 6. Set status upon error span.SetStatus(trace.Status{ Code: trace.StatusCodeUnknown, Message: err.Error(), }) } // 7. Annotate our span to capture metadata about our operation span.Annotate([]trace.Attribute{ trace.Int64Attribute("bytes to int", num), }, "Invoking doWork") time.Sleep(20 * time.Millisecond) } ``` </details> <br/> 运行 `go run main.go` ### rpc 调用时的实例 在rpc 夸程序调用时候,如何追踪 > [详情查看 idcpj/LearnRpcx](https://github.com/idcpj/LearnRpcx) ![UTOOLS1584070117483.png](https://github.com/idcpj/LearnRpcx/raw/master/image/1.png) ![](https://github.com/idcpj/LearnRpcx/raw/master/image/2.png) ``` ctx := context.Background() span, ctx, _ := opentracing.GenerateSpanWithContext(ctx, "proxy") // 设置标签 span.SetTag("1111", "2222") // 设置注释 span.LogKV( "event", "soft error", "type", "cache timeout", "waited.millis", 1500) ```