mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
opentracing -> opencensus (#802)
* update vendor directory, add go.opencensus.io * update imports * oops * s/opentracing/opencensus/ & remove prometheus / zipkin stuff & remove old stats * the dep train rides again * fix gin build * deps from last guy * start in on the agent metrics * she builds * remove tags for now, cardinality error is fussing. subscribe instead of register * update to patched version of opencensus to proceed for now TODO switch to a release * meh fix imports * println debug the bad boys * lace it with the tags * update deps again * fix all inconsistent cardinality errors * add our own logger * fix init * fix oom measure * remove bugged removal code * fix s3 measures * fix prom handler nil
This commit is contained in:
131
vendor/github.com/openzipkin/zipkin-go/middleware/http/client.go
generated
vendored
Normal file
131
vendor/github.com/openzipkin/zipkin-go/middleware/http/client.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
zipkin "github.com/openzipkin/zipkin-go"
|
||||
"github.com/openzipkin/zipkin-go/model"
|
||||
)
|
||||
|
||||
// ErrValidTracerRequired error
|
||||
var ErrValidTracerRequired = errors.New("valid tracer required")
|
||||
|
||||
// Client holds a Zipkin instrumented HTTP Client.
|
||||
type Client struct {
|
||||
*http.Client
|
||||
tracer *zipkin.Tracer
|
||||
httpTrace bool
|
||||
defaultTags map[string]string
|
||||
transportOptions []TransportOption
|
||||
}
|
||||
|
||||
// ClientOption allows optional configuration of Client.
|
||||
type ClientOption func(*Client)
|
||||
|
||||
// WithClient allows one to add a custom configured http.Client to use.
|
||||
func WithClient(client *http.Client) ClientOption {
|
||||
return func(c *Client) {
|
||||
if client == nil {
|
||||
client = &http.Client{}
|
||||
}
|
||||
c.Client = client
|
||||
}
|
||||
}
|
||||
|
||||
// ClientTrace allows one to enable Go's net/http/httptrace.
|
||||
func ClientTrace(enabled bool) ClientOption {
|
||||
return func(c *Client) {
|
||||
c.httpTrace = enabled
|
||||
}
|
||||
}
|
||||
|
||||
// ClientTags adds default Tags to inject into client application spans.
|
||||
func ClientTags(tags map[string]string) ClientOption {
|
||||
return func(c *Client) {
|
||||
c.defaultTags = tags
|
||||
}
|
||||
}
|
||||
|
||||
// TransportOptions passes optional Transport configuration to the internal
|
||||
// transport used by Client.
|
||||
func TransportOptions(options ...TransportOption) ClientOption {
|
||||
return func(c *Client) {
|
||||
c.transportOptions = options
|
||||
}
|
||||
}
|
||||
|
||||
// NewClient returns an HTTP Client adding Zipkin instrumentation around an
|
||||
// embedded standard Go http.Client.
|
||||
func NewClient(tracer *zipkin.Tracer, options ...ClientOption) (*Client, error) {
|
||||
if tracer == nil {
|
||||
return nil, ErrValidTracerRequired
|
||||
}
|
||||
|
||||
c := &Client{tracer: tracer, Client: &http.Client{}}
|
||||
for _, option := range options {
|
||||
option(c)
|
||||
}
|
||||
|
||||
c.transportOptions = append(
|
||||
c.transportOptions,
|
||||
// the following Client settings override provided transport settings.
|
||||
RoundTripper(c.Client.Transport),
|
||||
TransportTrace(c.httpTrace),
|
||||
)
|
||||
transport, err := NewTransport(tracer, c.transportOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.Client.Transport = transport
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// DoWithAppSpan wraps http.Client's Do with tracing using an application span.
|
||||
func (c *Client) DoWithAppSpan(req *http.Request, name string) (res *http.Response, err error) {
|
||||
var parentContext model.SpanContext
|
||||
|
||||
if span := zipkin.SpanFromContext(req.Context()); span != nil {
|
||||
parentContext = span.Context()
|
||||
}
|
||||
|
||||
appSpan := c.tracer.StartSpan(name, zipkin.Parent(parentContext))
|
||||
|
||||
zipkin.TagHTTPMethod.Set(appSpan, req.Method)
|
||||
zipkin.TagHTTPUrl.Set(appSpan, req.URL.String())
|
||||
zipkin.TagHTTPPath.Set(appSpan, req.URL.Path)
|
||||
|
||||
res, err = c.Client.Do(
|
||||
req.WithContext(zipkin.NewContext(req.Context(), appSpan)),
|
||||
)
|
||||
if err != nil {
|
||||
zipkin.TagError.Set(appSpan, err.Error())
|
||||
appSpan.Finish()
|
||||
return
|
||||
}
|
||||
|
||||
if c.httpTrace {
|
||||
appSpan.Annotate(time.Now(), "wr")
|
||||
}
|
||||
|
||||
if res.ContentLength > 0 {
|
||||
zipkin.TagHTTPResponseSize.Set(appSpan, strconv.FormatInt(res.ContentLength, 10))
|
||||
}
|
||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||
statusCode := strconv.FormatInt(int64(res.StatusCode), 10)
|
||||
zipkin.TagHTTPStatusCode.Set(appSpan, statusCode)
|
||||
if res.StatusCode > 399 {
|
||||
zipkin.TagError.Set(appSpan, statusCode)
|
||||
}
|
||||
}
|
||||
|
||||
res.Body = &spanCloser{
|
||||
ReadCloser: res.Body,
|
||||
sp: appSpan,
|
||||
traceEnabled: c.httpTrace,
|
||||
}
|
||||
return
|
||||
}
|
||||
81
vendor/github.com/openzipkin/zipkin-go/middleware/http/client_test.go
generated
vendored
Normal file
81
vendor/github.com/openzipkin/zipkin-go/middleware/http/client_test.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
zipkin "github.com/openzipkin/zipkin-go"
|
||||
httpclient "github.com/openzipkin/zipkin-go/middleware/http"
|
||||
"github.com/openzipkin/zipkin-go/reporter/recorder"
|
||||
)
|
||||
|
||||
func TestHTTPClient(t *testing.T) {
|
||||
reporter := recorder.NewReporter()
|
||||
defer reporter.Close()
|
||||
|
||||
ep, _ := zipkin.NewEndpoint("httpClient", "")
|
||||
tracer, err := zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(ep))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create tracer: %+v", err)
|
||||
}
|
||||
|
||||
clientTags := map[string]string{
|
||||
"client": "testClient",
|
||||
}
|
||||
|
||||
transportTags := map[string]string{
|
||||
"conf.timeout": "default",
|
||||
}
|
||||
|
||||
client, err := httpclient.NewClient(
|
||||
tracer,
|
||||
httpclient.WithClient(&http.Client{}),
|
||||
httpclient.ClientTrace(true),
|
||||
httpclient.ClientTags(clientTags),
|
||||
httpclient.TransportOptions(httpclient.TransportTags(transportTags)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create http client: %+v", err)
|
||||
}
|
||||
|
||||
req, _ := http.NewRequest("GET", "https://www.google.com", nil)
|
||||
|
||||
res, err := client.DoWithAppSpan(req, "Get Google")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to execute client request: %+v", err)
|
||||
}
|
||||
res.Body.Close()
|
||||
|
||||
spans := reporter.Flush()
|
||||
if len(spans) < 2 {
|
||||
t.Errorf("Span Count want 2+, have %d", len(spans))
|
||||
}
|
||||
|
||||
req, _ = http.NewRequest("GET", "https://www.google.com", nil)
|
||||
|
||||
res, err = client.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to execute client request: %+v", err)
|
||||
}
|
||||
res.Body.Close()
|
||||
|
||||
spans = reporter.Flush()
|
||||
if len(spans) == 0 {
|
||||
t.Errorf("Span Count want 1+, have 0")
|
||||
}
|
||||
|
||||
span := tracer.StartSpan("ParentSpan")
|
||||
|
||||
req, _ = http.NewRequest("GET", "http://www.google.com", nil)
|
||||
|
||||
ctx := zipkin.NewContext(req.Context(), span)
|
||||
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
res, err = client.DoWithAppSpan(req, "ChildSpan")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to execute client request: %+v", err)
|
||||
}
|
||||
res.Body.Close()
|
||||
|
||||
}
|
||||
5
vendor/github.com/openzipkin/zipkin-go/middleware/http/doc.go
generated
vendored
Normal file
5
vendor/github.com/openzipkin/zipkin-go/middleware/http/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Package http contains several http middlewares which can be used for
|
||||
instrumenting calls with Zipkin.
|
||||
*/
|
||||
package http
|
||||
149
vendor/github.com/openzipkin/zipkin-go/middleware/http/server.go
generated
vendored
Normal file
149
vendor/github.com/openzipkin/zipkin-go/middleware/http/server.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
|
||||
zipkin "github.com/openzipkin/zipkin-go"
|
||||
"github.com/openzipkin/zipkin-go/model"
|
||||
"github.com/openzipkin/zipkin-go/propagation/b3"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
tracer *zipkin.Tracer
|
||||
name string
|
||||
next http.Handler
|
||||
tagResponseSize bool
|
||||
defaultTags map[string]string
|
||||
}
|
||||
|
||||
// ServerOption allows Middleware to be optionally configured.
|
||||
type ServerOption func(*handler)
|
||||
|
||||
// ServerTags adds default Tags to inject into server spans.
|
||||
func ServerTags(tags map[string]string) ServerOption {
|
||||
return func(h *handler) {
|
||||
h.defaultTags = tags
|
||||
}
|
||||
}
|
||||
|
||||
// TagResponseSize will instruct the middleware to Tag the http response size
|
||||
// in the server side span.
|
||||
func TagResponseSize(enabled bool) ServerOption {
|
||||
return func(h *handler) {
|
||||
h.tagResponseSize = enabled
|
||||
}
|
||||
}
|
||||
|
||||
// SpanName sets the name of the spans the middleware creates. Use this if
|
||||
// wrapping each endpoint with its own Middleware.
|
||||
// If omitting the SpanName option, the middleware will use the http request
|
||||
// method as span name.
|
||||
func SpanName(name string) ServerOption {
|
||||
return func(h *handler) {
|
||||
h.name = name
|
||||
}
|
||||
}
|
||||
|
||||
// NewServerMiddleware returns a http.Handler middleware with Zipkin tracing.
|
||||
func NewServerMiddleware(t *zipkin.Tracer, options ...ServerOption) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
h := &handler{
|
||||
tracer: t,
|
||||
next: next,
|
||||
}
|
||||
for _, option := range options {
|
||||
option(h)
|
||||
}
|
||||
return h
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler.
|
||||
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
var spanName string
|
||||
|
||||
// try to extract B3 Headers from upstream
|
||||
sc := h.tracer.Extract(b3.ExtractHTTP(r))
|
||||
|
||||
remoteEndpoint, _ := zipkin.NewEndpoint("", r.RemoteAddr)
|
||||
|
||||
if len(h.name) == 0 {
|
||||
spanName = r.Method
|
||||
} else {
|
||||
spanName = h.name
|
||||
}
|
||||
|
||||
// create Span using SpanContext if found
|
||||
sp := h.tracer.StartSpan(
|
||||
spanName,
|
||||
zipkin.Kind(model.Server),
|
||||
zipkin.Parent(sc),
|
||||
zipkin.RemoteEndpoint(remoteEndpoint),
|
||||
)
|
||||
|
||||
for k, v := range h.defaultTags {
|
||||
sp.Tag(k, v)
|
||||
}
|
||||
|
||||
// add our span to context
|
||||
ctx := zipkin.NewContext(r.Context(), sp)
|
||||
|
||||
// tag typical HTTP request items
|
||||
zipkin.TagHTTPMethod.Set(sp, r.Method)
|
||||
zipkin.TagHTTPUrl.Set(sp, r.URL.String())
|
||||
zipkin.TagHTTPRequestSize.Set(sp, strconv.FormatInt(r.ContentLength, 10))
|
||||
|
||||
// create http.ResponseWriter interceptor for tracking response size and
|
||||
// status code.
|
||||
ri := &rwInterceptor{w: w, statusCode: 200}
|
||||
|
||||
// tag found response size and status code on exit
|
||||
defer func() {
|
||||
code := ri.getStatusCode()
|
||||
sCode := strconv.Itoa(code)
|
||||
if code > 399 {
|
||||
zipkin.TagError.Set(sp, sCode)
|
||||
}
|
||||
zipkin.TagHTTPStatusCode.Set(sp, sCode)
|
||||
if h.tagResponseSize {
|
||||
zipkin.TagHTTPResponseSize.Set(sp, ri.getResponseSize())
|
||||
}
|
||||
sp.Finish()
|
||||
}()
|
||||
|
||||
// call next http Handler func using our updated context.
|
||||
h.next.ServeHTTP(ri, r.WithContext(ctx))
|
||||
}
|
||||
|
||||
// rwInterceptor intercepts the ResponseWriter so it can track response size
|
||||
// and returned status code.
|
||||
type rwInterceptor struct {
|
||||
w http.ResponseWriter
|
||||
size uint64
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (r *rwInterceptor) Header() http.Header {
|
||||
return r.w.Header()
|
||||
}
|
||||
|
||||
func (r *rwInterceptor) Write(b []byte) (n int, err error) {
|
||||
n, err = r.w.Write(b)
|
||||
atomic.AddUint64(&r.size, uint64(n))
|
||||
return
|
||||
}
|
||||
|
||||
func (r *rwInterceptor) WriteHeader(i int) {
|
||||
r.statusCode = i
|
||||
r.w.WriteHeader(i)
|
||||
}
|
||||
|
||||
func (r *rwInterceptor) getStatusCode() int {
|
||||
return r.statusCode
|
||||
}
|
||||
|
||||
func (r *rwInterceptor) getResponseSize() string {
|
||||
return strconv.FormatUint(atomic.LoadUint64(&r.size), 10)
|
||||
}
|
||||
141
vendor/github.com/openzipkin/zipkin-go/middleware/http/server_test.go
generated
vendored
Normal file
141
vendor/github.com/openzipkin/zipkin-go/middleware/http/server_test.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
zipkin "github.com/openzipkin/zipkin-go"
|
||||
mw "github.com/openzipkin/zipkin-go/middleware/http"
|
||||
"github.com/openzipkin/zipkin-go/reporter/recorder"
|
||||
)
|
||||
|
||||
var (
|
||||
lep, _ = zipkin.NewEndpoint("testSvc", "127.0.0.1:0")
|
||||
)
|
||||
|
||||
func httpHandler(code int, headers http.Header, body *bytes.Buffer) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(code)
|
||||
for key, value := range headers {
|
||||
w.Header().Add(key, value[0])
|
||||
}
|
||||
w.Write(body.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPHandlerWrapping(t *testing.T) {
|
||||
var (
|
||||
spanRecorder = &recorder.ReporterRecorder{}
|
||||
tr, _ = zipkin.NewTracer(spanRecorder, zipkin.WithLocalEndpoint(lep))
|
||||
httpRecorder = httptest.NewRecorder()
|
||||
requestBuf = bytes.NewBufferString("incoming data")
|
||||
responseBuf = bytes.NewBufferString("oh oh we have a 404")
|
||||
headers = make(http.Header)
|
||||
spanName = "wrapper_test"
|
||||
code = 404
|
||||
)
|
||||
headers.Add("some-key", "some-value")
|
||||
headers.Add("other-key", "other-value")
|
||||
|
||||
request, err := http.NewRequest("POST", "/test", requestBuf)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create request")
|
||||
}
|
||||
|
||||
httpHandlerFunc := http.HandlerFunc(httpHandler(code, headers, responseBuf))
|
||||
|
||||
tags := map[string]string{
|
||||
"component": "testServer",
|
||||
}
|
||||
handler := mw.NewServerMiddleware(
|
||||
tr,
|
||||
mw.SpanName(spanName),
|
||||
mw.TagResponseSize(true),
|
||||
mw.ServerTags(tags),
|
||||
)(httpHandlerFunc)
|
||||
|
||||
handler.ServeHTTP(httpRecorder, request)
|
||||
|
||||
spans := spanRecorder.Flush()
|
||||
|
||||
if want, have := 1, len(spans); want != have {
|
||||
t.Errorf("Expected %d spans, got %d", want, have)
|
||||
}
|
||||
|
||||
span := spans[0]
|
||||
|
||||
if want, have := spanName, span.Name; want != have {
|
||||
t.Errorf("Expected span name %s, got %s", want, have)
|
||||
}
|
||||
|
||||
if want, have := strconv.Itoa(requestBuf.Len()), span.Tags["http.request.size"]; want != have {
|
||||
t.Errorf("Expected span request size %s, got %s", want, have)
|
||||
}
|
||||
|
||||
if want, have := strconv.Itoa(responseBuf.Len()), span.Tags["http.response.size"]; want != have {
|
||||
t.Errorf("Expected span response size %s, got %s", want, have)
|
||||
|
||||
}
|
||||
|
||||
if want, have := strconv.Itoa(code), span.Tags["http.status_code"]; want != have {
|
||||
t.Errorf("Expected span status code %s, got %s", want, have)
|
||||
}
|
||||
|
||||
if want, have := strconv.Itoa(code), span.Tags["error"]; want != have {
|
||||
t.Errorf("Expected span error %q, got %q", want, have)
|
||||
}
|
||||
|
||||
if want, have := len(headers), len(httpRecorder.HeaderMap); want != have {
|
||||
t.Errorf("Expected http header count %d, got %d", want, have)
|
||||
}
|
||||
|
||||
if want, have := code, httpRecorder.Code; want != have {
|
||||
t.Errorf("Expected http status code %d, got %d", want, have)
|
||||
}
|
||||
|
||||
for key, value := range headers {
|
||||
if want, have := value, httpRecorder.HeaderMap.Get(key); want[0] != have {
|
||||
t.Errorf("Expected header %s value %s, got %s", key, want, have)
|
||||
}
|
||||
}
|
||||
|
||||
if want, have := responseBuf.String(), httpRecorder.Body.String(); want != have {
|
||||
t.Errorf("Expected body value %q, got %q", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPDefaultSpanName(t *testing.T) {
|
||||
var (
|
||||
spanRecorder = &recorder.ReporterRecorder{}
|
||||
tr, _ = zipkin.NewTracer(spanRecorder, zipkin.WithLocalEndpoint(lep))
|
||||
httpRecorder = httptest.NewRecorder()
|
||||
requestBuf = bytes.NewBufferString("incoming data")
|
||||
methodType = "POST"
|
||||
)
|
||||
|
||||
request, err := http.NewRequest(methodType, "/test", requestBuf)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create request")
|
||||
}
|
||||
|
||||
httpHandlerFunc := http.HandlerFunc(httpHandler(200, nil, bytes.NewBufferString("")))
|
||||
|
||||
handler := mw.NewServerMiddleware(tr)(httpHandlerFunc)
|
||||
|
||||
handler.ServeHTTP(httpRecorder, request)
|
||||
|
||||
spans := spanRecorder.Flush()
|
||||
|
||||
if want, have := 1, len(spans); want != have {
|
||||
t.Errorf("Expected %d spans, got %d", want, have)
|
||||
}
|
||||
|
||||
span := spans[0]
|
||||
|
||||
if want, have := methodType, span.Name; want != have {
|
||||
t.Errorf("Expected span name %s, got %s", want, have)
|
||||
}
|
||||
}
|
||||
23
vendor/github.com/openzipkin/zipkin-go/middleware/http/spancloser.go
generated
vendored
Normal file
23
vendor/github.com/openzipkin/zipkin-go/middleware/http/spancloser.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
zipkin "github.com/openzipkin/zipkin-go"
|
||||
)
|
||||
|
||||
type spanCloser struct {
|
||||
io.ReadCloser
|
||||
sp zipkin.Span
|
||||
traceEnabled bool
|
||||
}
|
||||
|
||||
func (s *spanCloser) Close() (err error) {
|
||||
if s.traceEnabled {
|
||||
s.sp.Annotate(time.Now(), "Body Close")
|
||||
}
|
||||
err = s.ReadCloser.Close()
|
||||
s.sp.Finish()
|
||||
return
|
||||
}
|
||||
103
vendor/github.com/openzipkin/zipkin-go/middleware/http/spantrace.go
generated
vendored
Normal file
103
vendor/github.com/openzipkin/zipkin-go/middleware/http/spantrace.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http/httptrace"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
zipkin "github.com/openzipkin/zipkin-go"
|
||||
)
|
||||
|
||||
type spanTrace struct {
|
||||
zipkin.Span
|
||||
c *httptrace.ClientTrace
|
||||
}
|
||||
|
||||
func (s *spanTrace) getConn(hostPort string) {
|
||||
s.Annotate(time.Now(), "Connecting")
|
||||
s.Tag("httptrace.get_connection.host_port", hostPort)
|
||||
}
|
||||
|
||||
func (s *spanTrace) gotConn(info httptrace.GotConnInfo) {
|
||||
s.Annotate(time.Now(), "Connected")
|
||||
s.Tag("httptrace.got_connection.reused", fmt.Sprintf("%t", info.Reused))
|
||||
s.Tag("httptrace.got_connection.was_idle", fmt.Sprintf("%t", info.WasIdle))
|
||||
if info.WasIdle {
|
||||
s.Tag("httptrace.got_connection.idle_time", info.IdleTime.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *spanTrace) putIdleConn(err error) {
|
||||
s.Annotate(time.Now(), "Put Idle Connection")
|
||||
if err != nil {
|
||||
s.Tag("httptrace.put_idle_connection.error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *spanTrace) gotFirstResponseByte() {
|
||||
s.Annotate(time.Now(), "First Response Byte")
|
||||
}
|
||||
|
||||
func (s *spanTrace) got100Continue() {
|
||||
s.Annotate(time.Now(), "Got 100 Continue")
|
||||
}
|
||||
|
||||
func (s *spanTrace) dnsStart(info httptrace.DNSStartInfo) {
|
||||
s.Annotate(time.Now(), "DNS Start")
|
||||
s.Tag("httptrace.dns_start.host", info.Host)
|
||||
}
|
||||
|
||||
func (s *spanTrace) dnsDone(info httptrace.DNSDoneInfo) {
|
||||
s.Annotate(time.Now(), "DNS Done")
|
||||
var addrs []string
|
||||
for _, addr := range info.Addrs {
|
||||
addrs = append(addrs, addr.String())
|
||||
}
|
||||
s.Tag("httptrace.dns_done.addrs", strings.Join(addrs, " , "))
|
||||
if info.Err != nil {
|
||||
s.Tag("httptrace.dns_done.error", info.Err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *spanTrace) connectStart(network, addr string) {
|
||||
s.Annotate(time.Now(), "Connect Start")
|
||||
s.Tag("httptrace.connect_start.network", network)
|
||||
s.Tag("httptrace.connect_start.addr", addr)
|
||||
}
|
||||
|
||||
func (s *spanTrace) connectDone(network, addr string, err error) {
|
||||
s.Annotate(time.Now(), "Connect Done")
|
||||
s.Tag("httptrace.connect_done.network", network)
|
||||
s.Tag("httptrace.connect_done.addr", addr)
|
||||
if err != nil {
|
||||
s.Tag("httptrace.connect_done.error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *spanTrace) tlsHandshakeStart() {
|
||||
s.Annotate(time.Now(), "TLS Handshake Start")
|
||||
}
|
||||
|
||||
func (s *spanTrace) tlsHandshakeDone(_ tls.ConnectionState, err error) {
|
||||
s.Annotate(time.Now(), "TLS Handshake Done")
|
||||
if err != nil {
|
||||
s.Tag("httptrace.tls_handshake_done.error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *spanTrace) wroteHeaders() {
|
||||
s.Annotate(time.Now(), "Wrote Headers")
|
||||
}
|
||||
|
||||
func (s *spanTrace) wait100Continue() {
|
||||
s.Annotate(time.Now(), "Wait 100 Continue")
|
||||
}
|
||||
|
||||
func (s *spanTrace) wroteRequest(info httptrace.WroteRequestInfo) {
|
||||
s.Annotate(time.Now(), "Wrote Request")
|
||||
if info.Err != nil {
|
||||
s.Tag("httptrace.wrote_request.error", info.Err.Error())
|
||||
}
|
||||
}
|
||||
128
vendor/github.com/openzipkin/zipkin-go/middleware/http/transport.go
generated
vendored
Normal file
128
vendor/github.com/openzipkin/zipkin-go/middleware/http/transport.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptrace"
|
||||
"strconv"
|
||||
|
||||
zipkin "github.com/openzipkin/zipkin-go"
|
||||
"github.com/openzipkin/zipkin-go/model"
|
||||
"github.com/openzipkin/zipkin-go/propagation/b3"
|
||||
)
|
||||
|
||||
type transport struct {
|
||||
tracer *zipkin.Tracer
|
||||
rt http.RoundTripper
|
||||
httpTrace bool
|
||||
defaultTags map[string]string
|
||||
}
|
||||
|
||||
// TransportOption allows one to configure optional transport configuration.
|
||||
type TransportOption func(*transport)
|
||||
|
||||
// RoundTripper adds the Transport RoundTripper to wrap.
|
||||
func RoundTripper(rt http.RoundTripper) TransportOption {
|
||||
return func(t *transport) {
|
||||
if rt != nil {
|
||||
t.rt = rt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TransportTags adds default Tags to inject into transport spans.
|
||||
func TransportTags(tags map[string]string) TransportOption {
|
||||
return func(t *transport) {
|
||||
t.defaultTags = tags
|
||||
}
|
||||
}
|
||||
|
||||
// TransportTrace allows one to enable Go's net/http/httptrace.
|
||||
func TransportTrace(enable bool) TransportOption {
|
||||
return func(t *transport) {
|
||||
t.httpTrace = enable
|
||||
}
|
||||
}
|
||||
|
||||
// NewTransport returns a new Zipkin instrumented http RoundTripper which can be
|
||||
// used with a standard library http Client.
|
||||
func NewTransport(tracer *zipkin.Tracer, options ...TransportOption) (http.RoundTripper, error) {
|
||||
if tracer == nil {
|
||||
return nil, ErrValidTracerRequired
|
||||
}
|
||||
|
||||
t := &transport{
|
||||
tracer: tracer,
|
||||
rt: http.DefaultTransport,
|
||||
httpTrace: false,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(t)
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// RoundTrip satisfies the RoundTripper interface.
|
||||
func (t *transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
|
||||
sp, _ := t.tracer.StartSpanFromContext(
|
||||
req.Context(), req.URL.Scheme+"/"+req.Method, zipkin.Kind(model.Client),
|
||||
)
|
||||
|
||||
for k, v := range t.defaultTags {
|
||||
sp.Tag(k, v)
|
||||
}
|
||||
|
||||
if t.httpTrace {
|
||||
sptr := spanTrace{
|
||||
Span: sp,
|
||||
}
|
||||
sptr.c = &httptrace.ClientTrace{
|
||||
GetConn: sptr.getConn,
|
||||
GotConn: sptr.gotConn,
|
||||
PutIdleConn: sptr.putIdleConn,
|
||||
GotFirstResponseByte: sptr.gotFirstResponseByte,
|
||||
Got100Continue: sptr.got100Continue,
|
||||
DNSStart: sptr.dnsStart,
|
||||
DNSDone: sptr.dnsDone,
|
||||
ConnectStart: sptr.connectStart,
|
||||
ConnectDone: sptr.connectDone,
|
||||
TLSHandshakeStart: sptr.tlsHandshakeStart,
|
||||
TLSHandshakeDone: sptr.tlsHandshakeDone,
|
||||
WroteHeaders: sptr.wroteHeaders,
|
||||
Wait100Continue: sptr.wait100Continue,
|
||||
WroteRequest: sptr.wroteRequest,
|
||||
}
|
||||
|
||||
req = req.WithContext(
|
||||
httptrace.WithClientTrace(req.Context(), sptr.c),
|
||||
)
|
||||
}
|
||||
|
||||
zipkin.TagHTTPMethod.Set(sp, req.Method)
|
||||
zipkin.TagHTTPUrl.Set(sp, req.URL.String())
|
||||
zipkin.TagHTTPPath.Set(sp, req.URL.Path)
|
||||
|
||||
_ = b3.InjectHTTP(req)(sp.Context())
|
||||
|
||||
res, err = t.rt.RoundTrip(req)
|
||||
|
||||
if err != nil {
|
||||
zipkin.TagError.Set(sp, err.Error())
|
||||
sp.Finish()
|
||||
return
|
||||
}
|
||||
|
||||
if res.ContentLength > 0 {
|
||||
zipkin.TagHTTPResponseSize.Set(sp, strconv.FormatInt(res.ContentLength, 10))
|
||||
}
|
||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||
statusCode := strconv.FormatInt(int64(res.StatusCode), 10)
|
||||
zipkin.TagHTTPStatusCode.Set(sp, statusCode)
|
||||
if res.StatusCode > 399 {
|
||||
zipkin.TagError.Set(sp, statusCode)
|
||||
}
|
||||
}
|
||||
sp.Finish()
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user