...

Source file src/github.com/go-kit/kit/tracing/opencensus/http.go

Documentation: github.com/go-kit/kit/tracing/opencensus

     1  package opencensus
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  
     7  	"go.opencensus.io/plugin/ochttp"
     8  	"go.opencensus.io/plugin/ochttp/propagation/b3"
     9  	"go.opencensus.io/trace"
    10  
    11  	kithttp "github.com/go-kit/kit/transport/http"
    12  )
    13  
    14  // HTTPClientTrace enables OpenCensus tracing of a Go kit HTTP transport client.
    15  func HTTPClientTrace(options ...TracerOption) kithttp.ClientOption {
    16  	cfg := TracerOptions{}
    17  
    18  	for _, option := range options {
    19  		option(&cfg)
    20  	}
    21  
    22  	if !cfg.Public && cfg.HTTPPropagate == nil {
    23  		cfg.HTTPPropagate = &b3.HTTPFormat{}
    24  	}
    25  
    26  	clientBefore := kithttp.ClientBefore(
    27  		func(ctx context.Context, req *http.Request) context.Context {
    28  			var name string
    29  
    30  			if cfg.Name != "" {
    31  				name = cfg.Name
    32  			} else {
    33  				// OpenCensus states Path being default naming for a client span
    34  				name = req.Method + " " + req.URL.Path
    35  			}
    36  
    37  			ctx, span := trace.StartSpan(
    38  				ctx,
    39  				name,
    40  				trace.WithSampler(cfg.Sampler),
    41  				trace.WithSpanKind(trace.SpanKindClient),
    42  			)
    43  
    44  			span.AddAttributes(
    45  				trace.StringAttribute(ochttp.HostAttribute, req.URL.Host),
    46  				trace.StringAttribute(ochttp.MethodAttribute, req.Method),
    47  				trace.StringAttribute(ochttp.PathAttribute, req.URL.Path),
    48  				trace.StringAttribute(ochttp.UserAgentAttribute, req.UserAgent()),
    49  			)
    50  
    51  			if !cfg.Public {
    52  				cfg.HTTPPropagate.SpanContextToRequest(span.SpanContext(), req)
    53  			}
    54  
    55  			return ctx
    56  		},
    57  	)
    58  
    59  	clientAfter := kithttp.ClientAfter(
    60  		func(ctx context.Context, res *http.Response) context.Context {
    61  			if span := trace.FromContext(ctx); span != nil {
    62  				span.SetStatus(ochttp.TraceStatus(res.StatusCode, http.StatusText(res.StatusCode)))
    63  				span.AddAttributes(
    64  					trace.Int64Attribute(ochttp.StatusCodeAttribute, int64(res.StatusCode)),
    65  				)
    66  			}
    67  			return ctx
    68  		},
    69  	)
    70  
    71  	clientFinalizer := kithttp.ClientFinalizer(
    72  		func(ctx context.Context, err error) {
    73  			if span := trace.FromContext(ctx); span != nil {
    74  				if err != nil {
    75  					span.SetStatus(trace.Status{
    76  						Code:    trace.StatusCodeUnknown,
    77  						Message: err.Error(),
    78  					})
    79  				}
    80  				span.End()
    81  			}
    82  		},
    83  	)
    84  
    85  	return func(c *kithttp.Client) {
    86  		clientBefore(c)
    87  		clientAfter(c)
    88  		clientFinalizer(c)
    89  	}
    90  }
    91  
    92  // HTTPServerTrace enables OpenCensus tracing of a Go kit HTTP transport server.
    93  func HTTPServerTrace(options ...TracerOption) kithttp.ServerOption {
    94  	cfg := TracerOptions{}
    95  
    96  	for _, option := range options {
    97  		option(&cfg)
    98  	}
    99  
   100  	if !cfg.Public && cfg.HTTPPropagate == nil {
   101  		cfg.HTTPPropagate = &b3.HTTPFormat{}
   102  	}
   103  
   104  	serverBefore := kithttp.ServerBefore(
   105  		func(ctx context.Context, req *http.Request) context.Context {
   106  			var (
   107  				spanContext trace.SpanContext
   108  				span        *trace.Span
   109  				name        string
   110  				ok          bool
   111  			)
   112  
   113  			if cfg.Name != "" {
   114  				name = cfg.Name
   115  			} else {
   116  				name = req.Method + " " + req.URL.Path
   117  			}
   118  
   119  			spanContext, ok = cfg.HTTPPropagate.SpanContextFromRequest(req)
   120  			if ok && !cfg.Public {
   121  				ctx, span = trace.StartSpanWithRemoteParent(
   122  					ctx,
   123  					name,
   124  					spanContext,
   125  					trace.WithSpanKind(trace.SpanKindServer),
   126  					trace.WithSampler(cfg.Sampler),
   127  				)
   128  			} else {
   129  				ctx, span = trace.StartSpan(
   130  					ctx,
   131  					name,
   132  					trace.WithSpanKind(trace.SpanKindServer),
   133  					trace.WithSampler(cfg.Sampler),
   134  				)
   135  				if ok {
   136  					span.AddLink(trace.Link{
   137  						TraceID:    spanContext.TraceID,
   138  						SpanID:     spanContext.SpanID,
   139  						Type:       trace.LinkTypeChild,
   140  						Attributes: nil,
   141  					})
   142  				}
   143  			}
   144  
   145  			span.AddAttributes(
   146  				trace.StringAttribute(ochttp.MethodAttribute, req.Method),
   147  				trace.StringAttribute(ochttp.PathAttribute, req.URL.Path),
   148  			)
   149  
   150  			return ctx
   151  		},
   152  	)
   153  
   154  	serverFinalizer := kithttp.ServerFinalizer(
   155  		func(ctx context.Context, code int, r *http.Request) {
   156  			if span := trace.FromContext(ctx); span != nil {
   157  				span.SetStatus(ochttp.TraceStatus(code, http.StatusText(code)))
   158  
   159  				if rs, ok := ctx.Value(kithttp.ContextKeyResponseSize).(int64); ok {
   160  					span.AddAttributes(
   161  						trace.Int64Attribute("http.response_size", rs),
   162  					)
   163  				}
   164  
   165  				span.End()
   166  			}
   167  		},
   168  	)
   169  
   170  	return func(s *kithttp.Server) {
   171  		serverBefore(s)
   172  		serverFinalizer(s)
   173  	}
   174  }
   175  

View as plain text