• Stars
    star
    85
  • Rank 385,668 (Top 8 %)
  • Language
    Go
  • License
    MIT License
  • Created over 5 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

๐Ÿชก Dead simple, lightweight tracing.

๐Ÿงถ tracer

Dead simple, lightweight tracing.

Build Documentation Quality Template Coverage Awesome

๐Ÿ’ก Idea

The tracer provides API to trace execution flow.

func Do(ctx context.Context) {
	defer tracer.Fetch(ctx).Start().Stop()

	// do some heavy job
}

A full description of the idea is available here.

๐Ÿ† Motivation

At Avito, we use the Jaeger - a distributed tracing platform. It is handy in most cases, but at production, we also use sampling. So, what is a problem, you say?

I had 0.02% requests with a write: broken pipe error and it was difficult to find the appropriate one in the Sentry which also has trace related to it in the Jaeger.

For that reason, I wrote the simple solution to handle this specific case and found the bottleneck in our code quickly.

๐Ÿคผโ€โ™‚๏ธ How to

import (
	"context"
	"io"
	"net/http"
	"time"

	"github.com/kamilsk/tracer"
)

func InjectTracer(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		req = req.WithContext(tracer.Inject(req.Context(), make([]*tracer.Call, 0, 10)))
		handler.ServeHTTP(rw, req)
	})
}

func Handle(rw http.ResponseWriter, req *http.Request) {
	ctx, cancel := context.WithTimeout(req.Context(), time.Second)
	defer cancel()

	call := tracer.Fetch(req.Context()).Start(req.Header.Get("X-Request-Id"))
	defer call.Stop()

	...

	call.Checkpoint("serialize")
	data, err := FetchData(ctx, req.Body)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	call.Checkpoint("store")
	if err := StoreIntoDatabase(ctx, data); err != nil {
		http.Error(rw,
			http.StatusText(http.StatusInternalServerError),
			http.StatusInternalServerError)
		return
	}
	rw.WriteHeader(http.StatusOK)
}

func FetchData(ctx context.Context, r io.Reader) (Data, error) {
	defer tracer.Fetch(ctx).Start().Stop()

	// fetch a data into a struct
}

func StoreIntoDatabase(ctx context.Context, data Data) error {
	defer tracer.Fetch(ctx).Start().Stop()

	// store the data into a database
}

Output:

allocates at call stack: 0, detailed call stack:
	call Handle [ca7a87c4-58d0-4fdf-857c-ef49fc3bf271]: 14.038083ms, allocates: 2
		checkpoint [serialize]: 1.163587ms
		checkpoint [store]: 2.436265ms
	call FetchData: 1.192829ms, allocates: 0
	call StoreIntoDatabase: 10.428663ms, allocates: 0

๐Ÿงฉ Integration

The library uses SemVer for versioning, and it is not BC-safe through major releases. You can use go modules to manage its version.

$ go get github.com/kamilsk/tracer@latest

made with โค๏ธ for everyone