• Go语言jaeger和opentracing


    OpenTracing开放式分布式追踪规范,常见实现:jaeger和zipkin

    docker启动一个实例:

    docker run  -p 5775:5775/udp    -p 16686:16686    -p 6831:6831/udp   -p 6832:6832/udp   -p 5778:5778   -p 14268:14268    jaegertracing/all-in-one:latest

    go 

    来一个普通的go程序

    package main
     
    import (
        "fmt"
        "io"
        "io/ioutil"
        "net/http"
        "os"
     
        "github.com/uber/jaeger-client-go"
        "github.com/uber/jaeger-lib/metrics"
     
        "github.com/opentracing/opentracing-go"
        "github.com/opentracing/opentracing-go/ext"
        "github.com/uber/jaeger-client-go/config"
    )
     
    var (
        tracerServer opentracing.Tracer
    )
     
    func TraceInit(serviceName string, samplerType string, samplerParam float64) (opentracing.Tracer, io.Closer) {
        cfg := &config.Configuration{
            ServiceName: serviceName,
            Sampler: &config.SamplerConfig{
                Type:  samplerType,
                Param: samplerParam,
            },
            Reporter: &config.ReporterConfig{
                LocalAgentHostPort: "192.168.100.21:6831",
                LogSpans:           true,
            },
        }
     
        tracer, closer, err := cfg.NewTracer(config.Logger(jaeger.StdLogger), config.Metrics(metrics.NullFactory))
        if err != nil {
            panic(fmt.Sprintf("Init failed: %v
    ", err))
        }
     
        return tracer, closer
    }
     
    func GetListProc(w http.ResponseWriter, req *http.Request) {
        spanCtx, _ := tracerServer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header))
        span := tracerServer.StartSpan("GetListProc", ext.RPCServerOption(spanCtx))
        defer span.Finish()
     
        fmt.Println("Get request getList")
        respList := []string{"l1", "l2", "l3", "l4", "l5"}
        respString := ""
     
        for _, v := range respList {
            respString += v + ","
        }
     
        fmt.Println(respString)
        io.WriteString(w, respString)
    }
     
    func sendRequest(req *http.Request) {
        resp, err := http.DefaultClient.Do(req)
     
        if err != nil {
            fmt.Printf("Do send requst failed(%s)
    ", err)
            return
        }
     
        defer resp.Body.Close()
     
        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            fmt.Printf("ReadAll error(%s)
    ", err)
            return
        }
     
        if resp.StatusCode != 200 {
            return
        }
        fmt.Printf("Response:%s
    ", string(body))
     
    }
     
    func main() {
        // server
        var closerServer io.Closer
        tracerServer, closerServer = TraceInit("Trace-Server", "const", 1)
        defer closerServer.Close()
     
        http.HandleFunc("/getList", GetListProc)
     
        go http.ListenAndServe(":8080", nil)
     
        //client
        tracerClient, closerClient := TraceInit("CS-tracing", "const", 1)
        defer closerClient.Close()
     
        opentracing.SetGlobalTracer(tracerClient)
        span := tracerClient.StartSpan("getlist trace")
        span.SetTag("trace to", "getlist")
        defer span.Finish()
     
        reqURL := "http://localhost:8080/getList"
        req, err := http.NewRequest("GET", reqURL, nil)
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        }
     
        span.Tracer().Inject(
            span.Context(),
            opentracing.HTTPHeaders,
            opentracing.HTTPHeadersCarrier(req.Header),
        )
     
        sendRequest(req)
    }

    运行效果:

    访问http://192.168.100.21:16686/ 如下:

    GRPC

    我这里用以前的项目 https://github.com/dz45693/gogrpcjwt.git, 大家可以参考grpc 拦截器【 go 和 asp.net core的实现】 这里我引用了github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc 这个包

    服务端代码修改如下:

     

    客户端:

    普通程序日志:

    有些时候 我们的方法会有很多调用和日志, 我希望把这一次api请求的日志归纳在一起【elk可以通过某个字段过滤】, 这里我们可以在api 入口创建一个apn 绑定到context, 然后每个方法都传这个context,日志读取context的traceid

    package main
     
    import (
        "context"
        "encoding/json"
        "fmt"
        "io"
        "runtime"
        "strings"
        "time"
     
        "github.com/opentracing/opentracing-go"
        "github.com/uber/jaeger-client-go"
        "github.com/uber/jaeger-client-go/config"
        "github.com/uber/jaeger-lib/metrics"
        "go.uber.org/zap"
        "go.uber.org/zap/zapcore"
    )
     
    func init() {
        tracerClient, closerClient := TraceInit("CS-tracing", "const", 1)
        defer closerClient.Close()
     
        opentracing.SetGlobalTracer(tracerClient)
    }
     
    func main() {
        span := opentracing.GlobalTracer().StartSpan("gavintest")
        ctx := opentracing.ContextWithSpan(context.Background(), span)
        log(ctx, "gavin test")
    }
     
    func log(ctx context.Context, format string, args ...interface{}) {
        traceId, spanId := GetTraceId(ctx)
     
        logerData := JsonLogger{
            TraceId:  traceId,
            SpanId:   spanId,
            Content:  fmt.Sprintf(format, args...),
            CallPath: GetCallPath(),
            Level:    zap.InfoLevel,
            LogTime:  time.Now().Format("2006-01-02T15:04:05.000+08:00"),
        }
     
        jsonData, _ := json.Marshal(logerData)
     
        fmt.Println("---------------------")
        fmt.Println(string(jsonData))
    }
     
    func TraceInit(serviceName string, samplerType string, samplerParam float64) (opentracing.Tracer, io.Closer) {
        cfg := &config.Configuration{
            ServiceName: serviceName,
            Sampler: &config.SamplerConfig{
                Type:  samplerType,
                Param: samplerParam,
            },
            Reporter: &config.ReporterConfig{
                LocalAgentHostPort: "192.168.100.30:6831",
                LogSpans:           true,
            },
        }
     
        tracer, closer, err := cfg.NewTracer(config.Logger(jaeger.StdLogger), config.Metrics(metrics.NullFactory))
        if err != nil {
            panic(fmt.Sprintf("Init failed: %v
    ", err))
        }
     
        return tracer, closer
    }
     
    func GetTraceId(ctx context.Context) (string, uint64) {
        span := opentracing.SpanFromContext(ctx)
        if span == nil {
            return "", 0
        }
     
        if sc, ok := span.Context().(jaeger.SpanContext); ok {
     
            return fmt.Sprintf("%v", sc.TraceID()), uint64(sc.SpanID())
        }
        return "", 0
    }
     
    func GetCallPath() string {
        _, file, lineno, ok := runtime.Caller(2)
        if ok {
            return strings.Replace(fmt.Sprintf("%s:%d", stringTrim(file, ""), lineno), "%2e", ".", -1)
        }
        return ""
    }
     
    func stringTrim(s, cut string) string {
        ss := strings.SplitN(s, cut, 2)
        if len(ss) == 1 {
            return ss[0]
        }
        return ss[1]
    }
     
    type JsonLogger struct {
        TraceId  string        `json:"traceId"`
        SpanId   uint64        `json:"spanId"`
        Content  interface{}   `json:"content"`
        CallPath interface{}   `json:"callPath"`
        LogTime  string        `json:"logdate"`
        Level    zapcore.Level `json:"level"`
    }

    运行效果:

    windows技术爱好者
  • 相关阅读:
    将数字转化为字符串
    给定一列数字将其平移n位
    判断回文数的问题
    c语言链表逆序的问题
    python中类属性和实例属性的区别
    python中__repr__()方法
    python中模块和包
    flask如何写一个model
    遍历文件夹下excel文件并且写入一个新excel
    python统计任务耗时
  • 原文地址:https://www.cnblogs.com/majiang/p/14417352.html
Copyright © 2020-2023  润新知