๐Ÿ“ฆ go-chi / traceid

Go middleware for simple TraceId header propagation across multiple services

โ˜… 8 stars โ‘‚ 1 forks ๐Ÿ‘ 8 watching โš–๏ธ MIT License
๐Ÿ“ฅ Clone https://github.com/go-chi/traceid.git
HTTPS git clone https://github.com/go-chi/traceid.git
SSH git clone git@github.com:go-chi/traceid.git
CLI gh repo clone go-chi/traceid
David Sedlรกฤek David Sedlรกฤek Slog handler (#2) 479dd4e 9 months ago ๐Ÿ“ History
๐Ÿ“‚ master View all commits โ†’
๐Ÿ“ cmd
๐Ÿ“ example
๐Ÿ“„ go.mod
๐Ÿ“„ go.sum
๐Ÿ“„ go.work
๐Ÿ“„ LICENSE
๐Ÿ“„ logger.go
๐Ÿ“„ middleware.go
๐Ÿ“„ README.md
๐Ÿ“„ traceid.go
๐Ÿ“„ transport.go
๐Ÿ“„ README.md

TraceId

Go pkg to propagate TraceId header across multiple services.

  • Enables simple tracing capabilities and log grouping.
  • The value can be exposed to end-users in case of an error.
  • The value is UUIDv7, which lets you infer the timestamp.
  • Unlike OTEL, this package doesn't trace spans or metrics, doesn't require any backend and doesn't have large dependencies (GRPC).

Example - HTTP middleware

package main

import (
	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/go-chi/httplog/v2"
	"github.com/go-chi/traceid"
)

func main() {
	r := chi.NewRouter()

	r.Use(traceid.Middleware)
	r.Use(httplog.RequestLogger(logger()))
	r.Use(middleware.Recoverer)

	r.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			ctx := r.Context()

			// Log traceId to request logger.
			traceID := traceid.FromContext(r.Context())
			httplog.LogEntrySetField(ctx, "traceId", slog.StringValue(traceID))

			next.ServeHTTP(w, r.WithContext(ctx))
		})
	})

See example/main.go

Example: Send HTTP request with TraceId header

import (
	"github.com/go-chi/traceid"
)

func main() {
	// Set TraceId in context, if not set from parent ctx yet.
	ctx := traceid.NewContext(context.Background())

	// Make a request with TraceId header.
	req, _ := http.NewRequestWithContext(ctx, "GET", "http://localhost:3333/proxy", nil)
	traceid.SetHeader(ctx, req)

	resp, err := http.DefaultClient.Do(req)
	//...
}

Example: Set TraceId header in all outgoing HTTP requests globally

import (
	"github.com/go-chi/traceid"
	"github.com/go-chi/transport"
)

func main() {
	// Send TraceId in all outgoing HTTP requests.
	http.DefaultTransport = transport.Chain(
		http.DefaultTransport,
		transport.SetHeader("User-Agent", "my-app/v1.0.0"),
		traceid.Transport,
	)
	
	// This will automatically send TraceId header.
	req, _ := http.NewRequest("GET", "http://localhost:3333/proxy", nil)
	_, _ = http.DefaultClient.Do(req)
}

Get time from UUIDv7 value

$ go run github.com/go-chi/traceid/cmd/traceid 018e0ee7-3605-7d75-b344-01062c6fd8bc
2024-03-05 14:56:57.477 +0100 CET

You can also create a new UUIDv7:

$ go run github.com/go-chi/traceid/cmd/traceid
018e0ee7-3605-7d75-b344-01062c6fd8bc

License

MIT