Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
traceandtrace-go is go tracing lib. It integrate multi tracer such as jeager,zipkin,skywalking and so on <br>

## Version introduction
- v1.0.0 only support jeager
### v1.0.0
- only support jeager
- support http and gRPC (or both) tracing
- support sampler, sampler type and collector env setting

### v1.0.3
- support jeager and zipkin

## API
[godoc](https://pkg.go.dev/github.com/codeandcode0x/traceandtrace-go)

Expand All @@ -22,11 +26,12 @@ traceandtrace-go is go tracing lib. It integrate multi tracer such as jeager,zip
| ---- | ---- |
| TRACE_SAMPLER_TYPE | const/probabilistic/ratelimiting/remote |
| TRACE_SAMPLER_PARAM | 0-1 |
| TRACE_ENDPOINT | http://localhost:14268/api/traces |
| TRACE_AGENT_HOST | localhost:6831 |
| TRACE_REPORTER_LOG_SPANS | false/ture |
| TRACE_ENDPOINT | http://localhost:14268/api/traces (jaeger) or http://localhost:9411/api/v2/spans (zipkin) |
| TRACE_AGENT_HOST | localhost:6831 (jaeger) |
| TRACE_REPORTER_LOG_SPANS | false or ture |
| TRACE_TYPE | jaeger or zipkin |

## Ext field
## Jaeger Ext field
spanKind <br>
component <br>
samplingPriority <br>
Expand All @@ -45,23 +50,27 @@ httpMethod <br>
dbUser <br>
messageBusDestination <br>

## quick start
## Quick Start

### start jaeger
### Start Jaeger

```shell
docker run \
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 5775:5775/udp \
-p 16686:16686 \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 14250:14250 \
-p 9411:9411 \
ethansmart-docker.pkg.coding.net/istioalltime/roandocker/jaegertracing-all-in-one:1.22.0


```

### import package
### Import Package

```shell
go get github.com/codeandcode0x/traceandtrace-go
Expand All @@ -70,14 +79,14 @@ go get github.com/codeandcode0x/traceandtrace-go
### HTTP tracing

Create a trace on the http request method side.
![http to grpc client](wiki/imgs/http_client.jpg)
![http to grpc client](wiki/imgs/http_client_2.jpg)
tags are map[string]string type, you can pass logs k-v, tag and field.


### RPC tracing
### gRPC tracing
Create a trace on the rpc request method side

- **client**
**client**

```go
import (
Expand All @@ -94,11 +103,11 @@ if err != nil {
}
...
```
- **server**
**server**

```go
import (
tracing "github.com/codeandcode0x/traceandtrace-go/wrapper/rpc"
tracing "github.com/codeandcode0x/traceandtrace-go"
)

//No need to request other rpc services
Expand Down Expand Up @@ -126,7 +135,8 @@ newRpcServiceReq(tracer)

### Http to gRPC tracing
![http to grpc client](wiki/imgs/httptogrpc_client.jpg)
To call gRPC on the http server side, you need to add the parent context to the rpc client. For details, you can see the [example](example/http/httpServer.go) .
**ptx** is parent context, it can create sub-context trace span <br>
To call gRPC on the http server side, you need to add the parent context to the gRPC client. For details, you can see the [example](example/http/httpServer.go) .

## Concurrent Processing
### goroutine context control
Expand All @@ -135,9 +145,9 @@ To call gRPC on the http server side, you need to add the parent context to the
- By context WithCancel() create sub-coroutine sessions and manage coroutine tasks ;
- every context will carry related data of parent trace and child span ;

![goroutine session](https://images2018.cnblogs.com/blog/1048291/201806/1048291-20180629074859717-1555813847.png)
![goroutine session](wiki/imgs/goroutine.png)

### trace job control
### Trace Job Control
start and end trace job

```go
Expand Down
4 changes: 3 additions & 1 deletion example/grpc/grpcClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ func main() {
func gRPCExample() {
address := "localhost:22530"
defaultName := "ethan"
rpcOption, closer := tracing.AddRpcClientTracing("RpcClientExample")
rpcOption, closer := tracing.AddRpcClientTracing(
"RpcClientExample",
map[string]string{"version": "v1"})
defer closer.Close()

// Set up a connection to the server.
Expand Down
4 changes: 3 additions & 1 deletion example/grpc/grpcServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloRe
}

func main() {
rpcOption, closer, _ := tracing.AddRpcServerTracing("RpcServer")
rpcOption, closer, _ := tracing.AddRpcServerTracing(
"RpcServer",
map[string]string{"version": "v1"})
defer closer.Close()

lis, err := net.Listen("tcp", port)
Expand Down
7 changes: 6 additions & 1 deletion example/http/httpClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ func httpClient() {
httpClient := &http.Client{}
r, _ := http.NewRequest("GET", httpTogRPCSrcUrl, nil)
// set tracing
_, cancel := tracing.AddHttpTracing("HttpClent", "rpc/tracing GET", r.Header, map[string]string{"version": "v1"})
_, cancel := tracing.AddHttpTracing(
"HttpClient",
"/rpc/tracing GET", r.Header,
map[string]string{"version": "v1"})
// or map[string]string{"traceType": "zipkin", "version": "v1"}), traceType : jaeger (default) or zipkin
// or export TRACE_TYPE=zipkin or jaeger
defer cancel()
// send reqeust
response, _ := httpClient.Do(r)
Expand Down
14 changes: 10 additions & 4 deletions example/http/httpServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"time"

tracing "github.com/codeandcode0x/traceandtrace-go"
pb "github.com/codeandcode0x/traceandtrace-go/example/helloworld/proto"
pb "github.com/codeandcode0x/traceandtrace-go/example/protos/helloworld"
"google.golang.org/grpc"
)

Expand All @@ -20,8 +20,10 @@ func main() {
// http to gRPC
func httpServer() {
http.HandleFunc("/rpc/tracing", func(w http.ResponseWriter, r *http.Request) {
log.Println(".............. header ", r.Header)
pctx, cancel := tracing.AddHttpTracing("HttpServer", "/rpc/tracing GET", r.Header, map[string]string{"version": "v1"})
pctx, cancel := tracing.AddHttpTracing(
"HttpServer",
"/rpc/tracing GET", r.Header,
map[string]string{"version": "v1"})
defer cancel()
// rpc tracing
result := RpcClient(pctx)
Expand All @@ -33,7 +35,11 @@ func httpServer() {

//grpc request
func RpcClient(ptx context.Context) string {
rpcOption, closer := tracing.AddRpcClientTracing("RpcClient")
rpcOption, closer := tracing.AddRpcClientTracing(
"RpcClient",
map[string]string{"version": "v1"})
// or map[string]string{"traceType": "zipkin", "version": "v1"}), traceType : jaeger (default) or zipkin
// or export TRACE_TYPE=zipkin or jaeger
defer closer.Close()
address := "localhost:22530"
conn, err := grpc.Dial(address, grpc.WithInsecure(), rpcOption)
Expand Down
34 changes: 28 additions & 6 deletions reporter_jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"io"
"log"
"net/http"
"os"
"strings"

tracing "github.com/codeandcode0x/traceandtrace-go/tracer"
opentracing "github.com/opentracing/opentracing-go"
Expand Down Expand Up @@ -52,26 +54,46 @@ func GenerateTracingJobs(pch chan<- context.Context, parent context.Context, svc
// do trace reporter
func doTask(ch chan context.Context, parent context.Context,
svc, spanName string, header http.Header, tags map[string]string, traceType string) {
//定义 tracer, closer
//define tracer, closer
var tracer opentracing.Tracer
var closer io.Closer
var ctx context.Context
//init tracer
tracer, closer = SelectInitTracer(svc, map[string]string{"traceType": traceType})
ctx = tracing.AddHttpTracer(svc, spanName, parent, header, tracer, tags)
//close
defer closer.Close()
ch <- ctx
}

//select init tracer
func SelectInitTracer(svc string, param ...map[string]string) (opentracing.Tracer, io.Closer) {
var tracer opentracing.Tracer
var closer io.Closer
// get tracer type
traceType := JAEGER_TRACER
if tType := os.Getenv("TRACE_TYPE"); tType != "" {
traceType = tType
} else if len(param) > 0 {
if _, exist := param[0]["traceType"]; exist {
traceType = strings.ToLower(param[0]["traceType"])
}
}

// select reporter type
switch traceType {
case "jaeger":
tracer, closer = tracing.InitJaeger(svc)
ctx = tracing.AddTracer(svc, spanName, parent, header, tracer, tags)
break
case "zipkin":
log.Println("create zipkin tracing job")
tracer, closer = tracing.InitZipkin(svc)
break
case "skywalking":
log.Println("create skywalking tracing job")
break
default:
break
}

defer closer.Close()
ch <- ctx
//return
return tracer, closer
}
120 changes: 120 additions & 0 deletions tracer/grpc_tracer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package traceandtracego

import (
logger "log"

opentracing "github.com/opentracing/opentracing-go"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)

//声明 tracer
var tracer opentracing.Tracer

//text map reader
type TextMapReader struct {
metadata.MD
}

//text map writer
type TextMapWriter struct {
metadata.MD
}

//RPC Client Dial Option
func ClientDialOption(parentTracer opentracing.Tracer) grpc.DialOption {
tracer = parentTracer
return grpc.WithUnaryInterceptor(grpcClientInterceptor)
}

//RPC Server Dial Option
func ServerDialOption(tracer opentracing.Tracer) grpc.ServerOption {
return grpc.UnaryInterceptor(grpcServerInterceptor)
}

//RPC Client 拦截器
func grpcClientInterceptor(
ctx context.Context,
method string,
req, reply interface{},
cc *grpc.ClientConn,
invoker grpc.UnaryInvoker,
opts ...grpc.CallOption) (err error) {

//从context中获取metadata
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
md = metadata.New(nil)
} else {
//如果对metadata进行修改,那么需要用拷贝的副本进行修改
md = md.Copy()
}
//carrier := opentracing.TextMapCarrier{}
carrier := TextMapWriter{md}
//父类 context
var currentContext opentracing.SpanContext
//从 context 中获取原始的 span
parentSpan := opentracing.SpanFromContext(ctx)
if parentSpan != nil {
currentContext = parentSpan.Context()
} else {
//否则创建 span
span := tracer.StartSpan(method)
defer span.Finish()
currentContext = span.Context()
}
//将 span 的 context 信息注入到 carrier 中
e := tracer.Inject(currentContext, opentracing.TextMap, carrier)
if e != nil {
logger.Fatalln("tracer inject failed", e)
}
//创建一个新的 context,把 metadata 附带上
ctx = metadata.NewOutgoingContext(ctx, md)
return invoker(ctx, method, req, reply, cc, opts...)
}

//RPC Server 拦截器
func grpcServerInterceptor(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler) (resp interface{}, err error) {
//从context中获取metadata。md.(type) == map[string][]string
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
md = metadata.New(nil)
} else {
//如果对metadata进行修改,那么需要用拷贝的副本进行修改。(FromIncomingContext的注释)
md = md.Copy()
}
carrier := TextMapReader{md}
tracer := opentracing.GlobalTracer()
spanContext, e := tracer.Extract(opentracing.TextMap, carrier)
if e != nil {
logger.Fatalln("extract span context err", e)
}

span := tracer.StartSpan(info.FullMethod, opentracing.ChildOf(spanContext))
defer span.Finish()
ctx = opentracing.ContextWithSpan(ctx, span)

return handler(ctx, req)
}

//text map writer set
func (t TextMapWriter) Set(key, val string) {
t.MD[key] = append(t.MD[key], val)
}

// 读取 metadata 中的 span 信息
func (t TextMapReader) ForeachKey(handler func(key, val string) error) error { //不能是指针
for key, val := range t.MD {
for _, v := range val {
if err := handler(key, v); err != nil {
return err
}
}
}
return nil
}
Loading