diff --git a/middleware/http/client.go b/middleware/http/client.go index 10087de..2a8b83e 100644 --- a/middleware/http/client.go +++ b/middleware/http/client.go @@ -34,6 +34,7 @@ type Client struct { httpTrace bool defaultTags map[string]string transportOptions []TransportOption + remoteEndpoint *model.Endpoint } // ClientOption allows optional configuration of Client. @@ -71,6 +72,13 @@ func TransportOptions(options ...TransportOption) ClientOption { } } +// WithRemoteEndpoint will set the remote endpoint for all spans. +func WithRemoteEndpoint(remoteEndpoint *model.Endpoint) ClientOption { + return func(c *Client) { + c.remoteEndpoint = remoteEndpoint + } +} + // NewClient returns an HTTP Client adding Zipkin instrumentation around an // embedded standard Go http.Client. func NewClient(tracer *zipkin.Tracer, options ...ClientOption) (*Client, error) { @@ -88,6 +96,7 @@ func NewClient(tracer *zipkin.Tracer, options ...ClientOption) (*Client, error) // the following Client settings override provided transport settings. RoundTripper(c.Client.Transport), TransportTrace(c.httpTrace), + TransportRemoteEndpoint(c.remoteEndpoint), ) transport, err := NewTransport(tracer, c.transportOptions...) if err != nil { @@ -106,7 +115,7 @@ func (c *Client) DoWithAppSpan(req *http.Request, name string) (res *http.Respon parentContext = span.Context() } - appSpan := c.tracer.StartSpan(name, zipkin.Parent(parentContext)) + appSpan := c.tracer.StartSpan(name, zipkin.Parent(parentContext), zipkin.RemoteEndpoint(c.remoteEndpoint)) zipkin.TagHTTPMethod.Set(appSpan, req.Method) zipkin.TagHTTPPath.Set(appSpan, req.URL.Path) diff --git a/middleware/http/client_test.go b/middleware/http/client_test.go index 4a0268d..4dcb0a1 100644 --- a/middleware/http/client_test.go +++ b/middleware/http/client_test.go @@ -41,12 +41,14 @@ func TestHTTPClient(t *testing.T) { "conf.timeout": "default", } + remoteEndpoint, _ := zipkin.NewEndpoint("google-service", "1.2.3.4:80") client, err := httpclient.NewClient( tracer, httpclient.WithClient(&http.Client{}), httpclient.ClientTrace(true), httpclient.ClientTags(clientTags), httpclient.TransportOptions(httpclient.TransportTags(transportTags)), + httpclient.WithRemoteEndpoint(remoteEndpoint), ) if err != nil { t.Fatalf("unable to create http client: %+v", err) @@ -65,6 +67,14 @@ func TestHTTPClient(t *testing.T) { t.Errorf("Span Count want 2+, have %d", len(spans)) } + rep := spans[0].RemoteEndpoint + if rep == nil { + t.Errorf("Span remoteEndpoint must not nil") + } + if rep.ServiceName != remoteEndpoint.ServiceName { + t.Errorf("Span remoteEndpoint ServiceName want %s, have %s", remoteEndpoint.ServiceName, rep.ServiceName) + } + req, _ = http.NewRequest("GET", "https://www.google.com", nil) res, err = client.Do(req) diff --git a/middleware/http/transport.go b/middleware/http/transport.go index 981013c..7facdb5 100644 --- a/middleware/http/transport.go +++ b/middleware/http/transport.go @@ -58,6 +58,7 @@ type transport struct { errResponseReader *ErrResponseReader logger *log.Logger requestSampler RequestSamplerFunc + remoteEndpoint *model.Endpoint } // TransportOption allows one to configure optional transport configuration. @@ -100,6 +101,13 @@ func TransportErrResponseReader(r ErrResponseReader) TransportOption { } } +// TransportRemoteEndpoint will set the remote endpoint for all spans. +func TransportRemoteEndpoint(remoteEndpoint *model.Endpoint) TransportOption { + return func(c *transport) { + c.remoteEndpoint = remoteEndpoint + } +} + // TransportLogger allows to plug a logger into the transport func TransportLogger(l *log.Logger) TransportOption { return func(t *transport) { @@ -143,7 +151,7 @@ func NewTransport(tracer *zipkin.Tracer, options ...TransportOption) (http.Round // 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), + req.Context(), req.URL.Scheme+"/"+req.Method, zipkin.Kind(model.Client), zipkin.RemoteEndpoint(t.remoteEndpoint), ) for k, v := range t.defaultTags {