mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-28 18:06:34 +02:00
96 lines
2.8 KiB
Go
96 lines
2.8 KiB
Go
package trace
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
|
|
"github.com/gorilla/mux"
|
|
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
|
"google.golang.org/grpc/stats"
|
|
)
|
|
|
|
func NewHTTPMiddleware(opts ...otelhttp.Option) mux.MiddlewareFunc {
|
|
return otelhttp.NewMiddleware("Server: %s %s", append(opts, otelhttp.WithSpanNameFormatter(func(operation string, r *http.Request) string {
|
|
routeStr := ""
|
|
route := mux.CurrentRoute(r)
|
|
if route != nil {
|
|
var err error
|
|
routeStr, err = route.GetPathTemplate()
|
|
if err != nil {
|
|
routeStr, err = route.GetPathRegexp()
|
|
if err != nil {
|
|
routeStr = ""
|
|
}
|
|
}
|
|
}
|
|
return fmt.Sprintf(operation, r.Method, routeStr)
|
|
}))...)
|
|
}
|
|
|
|
type clientStatsHandlerWrapper struct {
|
|
ClientStatsHandlerOptions
|
|
base stats.Handler
|
|
}
|
|
|
|
type ClientStatsHandlerOptions struct {
|
|
statsInterceptor func(ctx context.Context, rs stats.RPCStats) stats.RPCStats
|
|
}
|
|
|
|
type ClientStatsHandlerOption func(*ClientStatsHandlerOptions)
|
|
|
|
func (o *ClientStatsHandlerOptions) apply(opts ...ClientStatsHandlerOption) {
|
|
for _, op := range opts {
|
|
op(o)
|
|
}
|
|
}
|
|
|
|
// WithStatsInterceptor calls the given function to modify the rpc stats before
|
|
// passing it to the stats handler during HandleRPC events.
|
|
//
|
|
// The interceptor MUST NOT modify the RPCStats it is given. It should instead
|
|
// return a copy of the underlying object with the same type, with any
|
|
// modifications made to the copy.
|
|
func WithStatsInterceptor(statsInterceptor func(ctx context.Context, rs stats.RPCStats) stats.RPCStats) ClientStatsHandlerOption {
|
|
return func(o *ClientStatsHandlerOptions) {
|
|
o.statsInterceptor = statsInterceptor
|
|
}
|
|
}
|
|
|
|
func NewClientStatsHandler(base stats.Handler, opts ...ClientStatsHandlerOption) stats.Handler {
|
|
options := ClientStatsHandlerOptions{}
|
|
options.apply(opts...)
|
|
return &clientStatsHandlerWrapper{
|
|
ClientStatsHandlerOptions: options,
|
|
base: base,
|
|
}
|
|
}
|
|
|
|
// HandleConn implements stats.Handler.
|
|
func (w *clientStatsHandlerWrapper) HandleConn(ctx context.Context, stats stats.ConnStats) {
|
|
w.base.HandleConn(ctx, stats)
|
|
}
|
|
|
|
// HandleRPC implements stats.Handler.
|
|
func (w *clientStatsHandlerWrapper) HandleRPC(ctx context.Context, stats stats.RPCStats) {
|
|
if w.statsInterceptor != nil {
|
|
modified := w.statsInterceptor(ctx, stats)
|
|
if reflect.TypeOf(stats) != reflect.TypeOf(modified) {
|
|
panic("bug: stats interceptor returned a message of a different type")
|
|
}
|
|
w.base.HandleRPC(ctx, modified)
|
|
} else {
|
|
w.base.HandleRPC(ctx, stats)
|
|
}
|
|
}
|
|
|
|
// TagConn implements stats.Handler.
|
|
func (w *clientStatsHandlerWrapper) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
|
|
return w.base.TagConn(ctx, info)
|
|
}
|
|
|
|
// TagRPC implements stats.Handler.
|
|
func (w *clientStatsHandlerWrapper) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
|
|
return w.base.TagRPC(ctx, info)
|
|
}
|