tracer.go
func RootTracer() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// split url
			segments := strings.Split(r.URL.Path, "/")

			// replace ids
			for i, s := range segments {
				if bson.IsObjectIdHex(s) {
					segments[i] = ":id"
				}
			}

			// construct name
			path := strings.Join(segments, "/")
			name := fmt.Sprintf("%s %s", r.Method, path)

			// create root span from request
			tracer := NewTracerFromRequest(r, name)
			tracer.Tag("peer.address", r.RemoteAddr)
			tracer.Tag("http.proto", r.Proto)
			tracer.Tag("http.method", r.Method)
			tracer.Tag("http.host", r.Host)
			tracer.Log("http.url", r.URL.String())
			tracer.Log("http.length", r.ContentLength)
			tracer.Log("http.header", r.Header)
			r = r.WithContext(tracer.Context(r.Context()))
			defer tracer.Finish(true)

			// call next handler
			next.ServeHTTP(w, r)
		})
	}
}
func RootTracer() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// split url
			segments := strings.Split(r.URL.Path, "/")

			// replace ids
			for i, s := range segments {
				if bson.IsObjectIdHex(s) {
					segments[i] = ":id"
				}
			}

			// construct name
			path := strings.Join(segments, "/")
			name := fmt.Sprintf("%s %s", r.Method, path)

			// create root span from request
			tracer := NewTracerFromRequest(r, name)
			tracer.Tag("peer.address", r.RemoteAddr)
			tracer.Tag("http.proto", r.Proto)
			tracer.Tag("http.method", r.Method)
			tracer.Tag("http.host", r.Host)
			tracer.Log("http.url", r.URL.String())
			tracer.Log("http.length", r.ContentLength)
			tracer.Log("http.header", r.Header)
			r = r.WithContext(tracer.Context(r.Context()))
			defer tracer.Finish(true)

			// call next handler
			next.ServeHTTP(w, r)
		})
	}
}
// RootTracer is a middleware that can be used to create root trace span for an
// incoming request.