Movatterモバイル変換


[0]ホーム

URL:


tracer

packagemodule
v1.0.1Latest Latest
Warning

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

Go to latest
Published: Aug 17, 2019 License:MITImports:6Imported by:1

Details

Repository

github.com/kamilsk/tracer

Links

README

🧶 tracer

Simple, lightweight tracing.

BuildQualityDocumentationCoverageAwesome

💡 Idea

The tracer provides API to trace execution flow.

func Do(ctx context.Context) {defer tracer.Fetch(ctx).Start().Stop()// do some heavy job}

Full description of the idea is availablehere.

🏆 Motivation

AtAvito, we use theJaeger - 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 awrite: broken pipe error and it was difficult to find the appropriate one intheSentry which also has trace related to it in theJaeger.

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: 2checkpoint [serialize]: 1.163587mscheckpoint [store]: 2.436265mscall FetchData: 1.192829ms, allocates: 0call StoreIntoDatabase: 10.428663ms, allocates: 0

🧩 Integration

The library usesSemVer for versioning, and it is notBC-safe through major releases.You can usego modules ordep to manage its version.

$ go get -u github.com/kamilsk/tracer$ dep ensure -add github.com/kamilsk/tracer

made with ❤️ for everyone

Documentation

Overview

Example
package mainimport ("bytes""context""encoding/gob""encoding/json""io""net/http""net/http/httptest""os""regexp""strings""time""github.com/kamilsk/tracer")type Data struct {Title    string `json:"title"`Subtitle string `json:"subtitle"`}func main() {rec := httptest.NewRecorder()req := httptest.NewRequest(http.MethodPost, "/message",strings.NewReader(`{"title": "tracer", "subtitle": "🧶 Simple, lightweight tracing mechanism."}`))req.Header.Set("X-Request-Id", "ca7a87c4-58d0-4fdf-857c-ef49fc3bf271")handler := InjectTracer(FlushTracer(http.HandlerFunc(Handle)))handler.ServeHTTP(rec, req)_, _ = io.Copy(os.Stdout, strings.NewReader(stabilize(rec.Body.String())))}func FlushTracer(handler http.Handler) http.Handler {return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {handler.ServeHTTP(rw, req)_, _ = rw.Write([]byte(tracer.Fetch(req.Context()).String()))})}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()time.Sleep(time.Millisecond)call.Checkpoint("serialize")data, err := FetchData(ctx, req.Body)if err != nil {http.Error(rw, err.Error(), http.StatusInternalServerError)return}time.Sleep(time.Millisecond)call.Checkpoint("store")if err := StoreIntoDatabase(ctx, data); err != nil {http.Error(rw, err.Error(), http.StatusInternalServerError)return}rw.WriteHeader(http.StatusOK)}func FetchData(ctx context.Context, r io.Reader) (Data, error) {defer tracer.Fetch(ctx).Start().Stop()time.Sleep(time.Millisecond)var data Dataerr := json.NewDecoder(r).Decode(&data)return data, err}func StoreIntoDatabase(ctx context.Context, data Data) error {defer tracer.Fetch(ctx).Start().Stop()time.Sleep(10 * time.Millisecond)return gob.NewEncoder(bytes.NewBuffer(nil)).Encode(data)}func stabilize(raw string) string {raw = strings.Replace(raw, "tracer_test.", "", -1)raw = regexp.MustCompile(`Handle (.+): (\d{2}\.\d+ms)`).ReplaceAllString(raw, "Handle $1: 12.345678ms")raw = regexp.MustCompile(`\[serialize]: (\d\.\d+ms)`).ReplaceAllString(raw, "[serialize]: 1.234567ms")raw = regexp.MustCompile(`\[store]: (\d\.\d+ms)`).ReplaceAllString(raw, "[store]: 1.234567ms")raw = regexp.MustCompile(`FetchData: (\d\.\d+ms)`).ReplaceAllString(raw, "FetchData: 1.234567ms")raw = regexp.MustCompile(`StoreIntoDatabase: (\d{2}\.\d+ms)`).ReplaceAllString(raw, "StoreIntoDatabase: 12.345678ms")return raw}
Output:allocates at call stack: 0, detailed call stack:call Handle [ca7a87c4-58d0-4fdf-857c-ef49fc3bf271]: 12.345678ms, allocates: 2checkpoint [serialize]: 1.234567mscheckpoint [store]: 1.234567mscall FetchData: 1.234567ms, allocates: 0call StoreIntoDatabase: 12.345678ms, allocates: 0

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

funcInject

func Inject(ctxcontext.Context, stack []*Call)context.Context

Inject returns a new context with injected into it the tracer.

func (server *server) ServeHTTP(rw http.ResponseWriter, req *http.Request) {req = req.WithContext(tracer.Inject(req.Context(), make([]*trace.Call, 0, 10)))server.routing.Handle(rw, req)}

Types

typeCall

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

Call holds information about a current function call.

func (*Call)Checkpoint

func (call *Call) Checkpoint(labels ...string)

Checkpoint stores timestamp of a current execution position of the current call.

func Do(ctx context.Context) {call := tracer.Fetch(ctx).Start()defer call.Stop()...call.Checkpoint()...call.Checkpoint("id", "labelX", "labelY")...}

func (*Call)Stop

func (call *Call) Stop()

Stop marks the end time of the current call.

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

typeCallerInfo

type CallerInfo struct {Entryuintptr// the entry address of the functionNamestring// the name of the functionFilestring// the file name andLineint// line number of the source code of the function}

CallerInfo holds information about a caller.

funcCaller

func Caller(skipint)CallerInfo

Caller returns information about a caller at position after the skip steps.

func StoreToDatabase(data Payload) error {defer stats.NewTiming().Send(Caller(2).Name)// do something heavy}

typeCheckpoint

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

Checkpoint holds information about a current execution position of a current call.

typeTrace

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

Trace holds information about a current execution flow.

funcFetch

func Fetch(ctxcontext.Context) *Trace

Fetch tries to get the tracer from a context or returns safe nil.

tracer.Fetch(context.Background()).Start().Stop() // won't panic

func (*Trace)Start

func (trace *Trace) Start(labels ...string) *Call

Start creates a call entry and marks its start time.

func Do(ctx context.Context) {call := tracer.Fetch(ctx).Start("id", "labelX", "labelY")defer call.Stop()}

func (*Trace)String

func (trace *Trace) String()string

String returns a string representation of the current execution flow.

Source Files

View all Source files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f orF : Jump to
y orY : Canonical URL
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.Learn more.

[8]ページ先頭

©2009-2025 Movatter.jp