tracer

package module
v1.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 14, 2022 License: MIT Imports: 25 Imported by: 0

README

tracer

simple trace sdk for OpenTracing and OpenTelemetry.

Feature:

support component:

  • simple api
  • http middleware
  • grpc middleware
  • redis hook
  • function span
  • goroutine stack caller cache
  • sorted TraceID generator

OpenTelemetry Usage:

init tracer
import (
	"github.com/rfyiamcool/go-tracer/otel"
)

func main() {
	tp, err := otel.New(serviceName, otel.WithMode(otel.ModeCollectorHttp), otel.WithAddress(url), otel.WithQueueSize(3000))
	if err != nil {
		log.Fatal(err)
	}
	defer tp.Shutdown(context.Background())

	...
}
start span
func hanldePost(ctx context.Context) {
	cctx, span := otel.StartSpan(ctx, "post")
	defer span.End()

	handleGrpcService(cctx, 1111)
}

func handleGrpcService(ctx context.Context, uid int) {
	cctx, span := otel.StartSpan(ctx, "handleGrpcService")
	defer span.End()

	// inject header, fill biz header
	md := metadata.Pairs("key-111", "val-111")
	md.Set("key-222", "val-222")

	// request
	var rheader metadata.MD
	resp, err := gclient.GetUserInfo(
		cctx,
		&pb.UserRequest{ID: int32(uid)},
		grpc.Header(&rheader),
	)

	// tag
	span.SetAttributes("method", "GetUserInfo")

	// log
	span.AddEventa("req.uid", uid)
	span.AddEventa("resp.body", md)
	span.AddEventa("resp.body", resp)
	span.AddEventa("resp.error", err)

	if err != nil {
		fmt.Println("grpc request failed, err: ", err.Error())
		return
	}
}

OpenTracing Usage:

init tracer
func NewTracer(serviceName string, addr string, fns ...optionFunc) (opentracing.Tracer, io.Closer, error) {
start span
func handleLogic(ctx context.Context, params interface{}) error {
	span, cctx := tracer.StartSpanFromContext(ctx, tracer.GetFunc())
	defer func() {
		span.SetTag("request", params)
		span.Finish()
	}()

	resp, err := httpGet(cctx, "http://127.0.0.1:8181/ping", map[string]interface{}{"k1": "v1"})
	if err != nil {
		return err
	}

	return nil
}

func httpGet(ctx context.Context, url string, data map[string]interface{}) (*req.Resp, error) {
	span, _ := tracer.StartSpanFromContext(ctx, tracer.GetFunc())
	defer func() {
		span.SetTag("url", url)
		span.Finish()
	}()

	header := make(http.Header, 10)
	err := tracer.InjectHttpHeader(span, header)
	if err != nil {
		span.LogFields(tracer.LogString("inject-error", err.Error()))
	}

	resp, err := req.Get(url, header)
	return resp, err
}
gin middleware
r := gin.Default()
r.Use(tracer.TracingMiddleware(serviceName))
r.GET("/ping", handlePing)
r.Run(bindAddr)
grpc server interceptor
listener, err := net.Listen("tcp", bindAddr)
grpcServer := grpc.NewServer(tracer.GrpcServerOption())
grpcServer.Serve(listener)

For more usage, please see the code !!!

OpenTracing Example

tracer code example

request path:

  • client
  • gateway
  • service
  • cache
start jaeger all in one container
bash example/start_jaeger.sh
start servers
  1. go run example/gateway/gw.go --trace-addr=127.0.0.1:6381
  2. go run example/service/service.go --trace-addr=127.0.0.1:6381
  3. go run example/cache/cache.go --trace-addr=127.0.0.1:6381
send request to gateway

Three ways to start the client !!!

  • go run example/client/client.go --trace-addr=127.0.0.1:6381
  • bash example/curl.sh, http request with custom x-trace-id.
  • curl -vvv 127.0.0.1:8080/ping
$ > bash example/curl.sh

x-trace-id ===>  230b497c161e83e9:230b497c161e83e9:0000000000000000:1

*   Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET /ping HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.71.1
> Accept: */*
> x-trace-id: 230b497c161e83e9:230b497c161e83e9:0000000000000000:1

* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Span-Id: 07f59dea1f92f1dd
< Trace-Id: 230b497c161e83e9
< Date: Sun, 06 Feb 2022 01:29:55 GMT
< Content-Length: 18
<
* Connection #0 to host 127.0.0.1 left intact

{"message":"pong"}%

Starting processes one by one is very cumbersome, you can use goreman start these processes, ‎😃 oh, what is goreman? how to use goreman? click the project > https://github.com/mattn/goreman

go install github.com/mattn/goreman@latest

cat Procfile
goreman -f Procfile start
query trace in UI
  1. open http://${jaeger_query_addr}:16686/search in chrome browser.
  2. input trace-id in jaeger ui.

OpenTelemetry Example

Please follow opentracing Example Usage.

cd otel

cat Procfile
goreman -f Procfile start

Documentation

Index

Constants

View Source
const (
	HeaderTraceID = "trace-id"
	HeaderSpanID  = "span-id"

	HeaderXTraceID = "x-trace-id"
)

Variables

View Source
var (
	// opentrace log
	LogString = tracelog.String
	LogInt    = tracelog.Int
	LogObject = tracelog.Object
)

Functions

func ClientInterceptor

func ClientInterceptor() grpc.UnaryClientInterceptor

ClientInterceptor grpc client wrapper

func Close

func Close() error

Close

func ContextFromString

func ContextFromString(xid string) (jaeger.SpanContext, error)

ContextFromString build context by x-trace-id

func ContextWithSpan

func ContextWithSpan(ctx context.Context, span opentracing.Span) context.Context

ContextWithSpan returns a new `context.Context` that holds a reference to the span. If span is nil, a new context without an active span is returned.

func ExtractGrpcHeader

func ExtractGrpcHeader(ctx context.Context) (opentracing.SpanContext, error)

ExtractGrpcHeader

func ExtractHttpHeader

func ExtractHttpHeader(header http.Header) (opentracing.SpanContext, error)

ExtractHttpHeader

func GetCaller

func GetCaller() string

func GetCallerCache

func GetCallerCache() string

func GetFullTraceID

func GetFullTraceID(span opentracing.Span) string

GetFullTraceID

func GetFunc

func GetFunc(ns ...int) string

func GetFuncSkip

func GetFuncSkip(skip int) string

func GetParentID

func GetParentID(span opentracing.Span) string

GetParentID get parent span id

func GetSpanID

func GetSpanID(span opentracing.Span) string

GetSpanID get span id

func GetSpanIDFromCtx

func GetSpanIDFromCtx(ctx context.Context) string

GetSpanIDFromCtx get span id from context

func GetTraceID

func GetTraceID(span opentracing.Span) string

GetTraceID get trace id from span

func GetTraceIDFromCtx

func GetTraceIDFromCtx(ctx context.Context) string

GetTraceIDFromCtx get trace id from context

func GetTraceSpanIDs

func GetTraceSpanIDs(span opentracing.Span) (string, string)

GetTraceSpanIDs

func GetTraceSpanIDsFromCtx

func GetTraceSpanIDsFromCtx(ctx context.Context) (string, string)

func GetTracer

func GetTracer() opentracing.Tracer

GetTracer

func GetXTraceID

func GetXTraceID(span opentracing.Span) string

GetXTraceID get x-trace-id by span

func GrpcDialOption

func GrpcDialOption() grpc.DialOption

DialOption grpc client option

func GrpcSendHeader

func GrpcSendHeader(ctx context.Context, header metadata.MD)

GrpcSendHeader grpc.SendHeader is called only once.

func GrpcServerOption

func GrpcServerOption() grpc.ServerOption

ServerOption grpc server option

func InjectGrpcMD

func InjectGrpcMD(span opentracing.Span, header metadata.MD, ctx context.Context) (context.Context, metadata.MD)

InjectGrpcMD

func InjectHttpHeader

func InjectHttpHeader(span opentracing.Span, header http.Header) error

InjectHttpHeader

func MakeFullTraceID

func MakeFullTraceID() string

MakeFullTraceID return x-trace-id

func MakeRandomNumber

func MakeRandomNumber() uint64

func MockID

func MockID() string

func NewHttpSender

func NewHttpSender(url string) jaeger.Transport

func NewRand

func NewRand(seed int64) *rand.Rand

NewRand returns a rand.Rand that is threadsafe.

func NewRedisHook

func NewRedisHook(tracer opentracing.Tracer) redis.Hook

NewHook creates a new go-redis hook instance and that will collect spans using the provided tracer.

func NewTracer

func NewTracer(serviceName string, addr string, fns ...optionFunc) (opentracing.Tracer, io.Closer, error)

NewTracer

func NewTracerWithConfig

func NewTracerWithConfig(cfg *Config) (opentracing.Tracer, io.Closer, error)

NewTracerWithConfig

func ServerInterceptor

func ServerInterceptor() grpc.UnaryServerInterceptor

ServerInterceptor grpc server wrapper

func SeteTracer

func SeteTracer(otracer opentracing.Tracer)

SetTracer

func SpanFromContext

func SpanFromContext(ctx context.Context) opentracing.Span

SpanFromContext

func SpanFromString

func SpanFromString(operation, xid string) (opentracing.Span, error)

ContextFromString build span by x-trace-id

func StartSpan

func StartSpan(operation string, opts ...opentracing.StartSpanOption) opentracing.Span

StartSpan Create, start, and return a new Span with the given `operationName`.

func StartSpanContext

func StartSpanContext(operation string, opts ...opentracing.StartSpanOption) (context.Context, opentracing.Span)

StartSpanContext

func StartSpanFromContext

func StartSpanFromContext(ctx context.Context, operation string) (opentracing.Span, context.Context)

StartSpanFromContext starts and returns a Span with `operationName`, using any Span found within `ctx` as a ChildOfRef.

func StartSpanFromContextExt

func StartSpanFromContextExt(ctx context.Context, fname string, request, response interface{}) (opentracing.Span, context.Context, func())

SpanFromContextExt

func StartSpanFromGinContext

func StartSpanFromGinContext(ctx *gin.Context, fname string, request, response interface{}) (opentracing.Span, context.Context, func())

func TracingMiddleware

func TracingMiddleware(name string) gin.HandlerFunc

TracingMiddleware gin middleware

func WithFlushInterval

func WithFlushInterval(ms int) optionFunc

WithFlushInterval

func WithMaxTagLength

func WithMaxTagLength(size int) optionFunc

WithMaxTagLength

func WithProtoKind

func WithProtoKind(kind int) optionFunc

WithProtoKind

func WithQueueSize

func WithQueueSize(size int) optionFunc

WithQueueSize queue size, defualt: 10000

func WithReporter

func WithReporter(cfg *jaegercfg.ReporterConfig) optionFunc

WithReporter

func WithSampler

func WithSampler(sampler *jaegercfg.SamplerConfig) optionFunc

WithSampler

func WithSender

func WithSender(sender jaeger.Transport) optionFunc

WithSender

Types

type Config

type Config struct {
	ServiceName         string `yaml:"service_name"`
	Address             string `yaml:"addr"`
	QueueSize           int    `yaml:"queue_size"`
	BufferFlushInterval int    `yaml:"buffer_flush_interval"`
	MaxTagLength        int    `yaml:"max_tag_length"`
	ProtoKind           int    `yaml:"proto_kind"`
}

type MetadataHeader

type MetadataHeader struct {
	metadata.MD
}

MetadataHeader metadata Reader and Writer

func (MetadataHeader) ForeachKey

func (c MetadataHeader) ForeachKey(handler func(key, val string) error) error

ForeachKey implements ForeachKey of opentracing.TextMapReader

func (MetadataHeader) Set

func (c MetadataHeader) Set(key, val string)

Set implements Set() of opentracing.TextMapWriter

type Option

type Option struct {
	// contains filtered or unexported fields
}

type RedisTracingHook

type RedisTracingHook struct {
	// contains filtered or unexported fields
}

func (RedisTracingHook) AfterProcess

func (hook RedisTracingHook) AfterProcess(ctx context.Context, cmd redis.Cmder) error

func (RedisTracingHook) AfterProcessPipeline

func (hook RedisTracingHook) AfterProcessPipeline(ctx context.Context, cmds []redis.Cmder) error

func (RedisTracingHook) BeforeProcess

func (hook RedisTracingHook) BeforeProcess(ctx context.Context, cmd redis.Cmder) (context.Context, error)

func (RedisTracingHook) BeforeProcessPipeline

func (hook RedisTracingHook) BeforeProcessPipeline(ctx context.Context, cmds []redis.Cmder) (context.Context, error)

type Span

type Span struct {
	TraceID      string
	SpanID       string
	ParentSpanID string
	// contains filtered or unexported fields
}

func Start

func Start(ctx context.Context, operation string) (context.Context, *Span)

func (*Span) End

func (sp *Span) End()

func (*Span) LogError

func (sp *Span) LogError(err error) *Span

func (*Span) LogFields

func (sp *Span) LogFields(fields ...log.Field) *Span

func (*Span) LogKV

func (sp *Span) LogKV(key string, val interface{}) *Span

func (*Span) LogObject

func (sp *Span) LogObject(key string, obj interface{}) *Span

func (*Span) LogString

func (sp *Span) LogString(key, val string) *Span

func (*Span) SetTag

func (sp *Span) SetTag(key string, val interface{}) *Span

func (*Span) Start

func (sp *Span) Start(ctx context.Context, operation string) (context.Context, *Span)

type SpanEntry

type SpanEntry struct {
	TraceID      string
	SpanID       string
	ParentSpanID string
	Flags        string
	// contains filtered or unexported fields
}

func GetSpanEntryFromCtx

func GetSpanEntryFromCtx(ctx context.Context) SpanEntry

GetSpanEntryFromCtx

func (*SpanEntry) IsNull

func (se *SpanEntry) IsNull() bool

func (*SpanEntry) String

func (se *SpanEntry) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL