Skip to content

Commit

Permalink
feat: add net/http (#26)
Browse files Browse the repository at this point in the history
* add test for instrumenter package

* add test in cicd

* add test in cicd

* fix test

* improve test coverage

* add more test

* feat: nethttp and gls

* fix mongo test

* fix http_attrs_extractor_test.go

* fix compile error

* add test for net http

* fix test
  • Loading branch information
123liuziming authored and y1yang0 committed Aug 9, 2024
1 parent 38f5dd7 commit 2f49f6c
Show file tree
Hide file tree
Showing 32 changed files with 2,114 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func (d *DbClientAttrsExtractor[REQUEST, RESPONSE, GETTER]) OnStart(attrs []attr
}

func (d *DbClientAttrsExtractor[REQUEST, RESPONSE, GETTER]) OnEnd(attrs []attribute.KeyValue, context context.Context, request REQUEST, response RESPONSE, err error) []attribute.KeyValue {
attrs = d.Base.OnEnd(attrs, context, request, response, err)
return attrs
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ func TestGetSpanKey(t *testing.T) {
}
}

func TestDbCommonGetSpanKey(t *testing.T) {
dbExtractor := &DbClientCommonAttrsExtractor[testRequest, any, mongoAttrsGetter]{}
if dbExtractor.GetSpanKey() != utils.DB_CLIENT_KEY {
t.Fatalf("Should have returned DB_CLIENT_KEY")
}
}

func TestDbClientExtractorStart(t *testing.T) {
dbExtractor := DbClientAttrsExtractor[testRequest, testResponse, mongoAttrsGetter]{}
attrs := make([]attribute.KeyValue, 0)
Expand Down
44 changes: 22 additions & 22 deletions pkg/inst-api-semconv/instrumenter/http/http_attrs_extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ import (
// TODO: http.route

type HttpCommonAttrsExtractor[REQUEST any, RESPONSE any, GETTER1 HttpCommonAttrsGetter[REQUEST, RESPONSE], GETTER2 net.NetworkAttrsGetter[REQUEST, RESPONSE]] struct {
httpGetter GETTER1
netGetter GETTER2
converter HttpStatusCodeConverter
HttpGetter GETTER1
NetGetter GETTER2
Converter HttpStatusCodeConverter
}

func (h *HttpCommonAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]) OnStart(attributes []attribute.KeyValue, parentContext context.Context, request REQUEST) []attribute.KeyValue {
attributes = append(attributes, attribute.KeyValue{
Key: semconv.HTTPRequestMethodKey,
Value: attribute.StringValue(h.httpGetter.GetRequestMethod(request)),
Value: attribute.StringValue(h.HttpGetter.GetRequestMethod(request)),
})
return attributes
}

func (h *HttpCommonAttrsExtractor[REQUEST, RESPONSE, GETTER, GETTER2]) OnEnd(attributes []attribute.KeyValue, context context.Context, request REQUEST, response RESPONSE, err error) []attribute.KeyValue {
statusCode := h.httpGetter.GetHttpResponseStatusCode(request, response, err)
protocolName := h.netGetter.GetNetworkProtocolName(request, response)
protocolVersion := h.netGetter.GetNetworkProtocolVersion(request, response)
statusCode := h.HttpGetter.GetHttpResponseStatusCode(request, response, err)
protocolName := h.NetGetter.GetNetworkProtocolName(request, response)
protocolVersion := h.NetGetter.GetNetworkProtocolVersion(request, response)
attributes = append(attributes, attribute.KeyValue{
Key: semconv.HTTPResponseStatusCodeKey,
Value: attribute.IntValue(statusCode),
Expand All @@ -41,13 +41,13 @@ func (h *HttpCommonAttrsExtractor[REQUEST, RESPONSE, GETTER, GETTER2]) OnEnd(att
}

type HttpClientAttrsExtractor[REQUEST any, RESPONSE any, GETTER1 HttpClientAttrsGetter[REQUEST, RESPONSE], GETTER2 net.NetworkAttrsGetter[REQUEST, RESPONSE]] struct {
base HttpCommonAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]
networkExtractor net.NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER2]
Base HttpCommonAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]
NetworkExtractor net.NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER2]
}

func (h *HttpClientAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]) OnStart(attributes []attribute.KeyValue, parentContext context.Context, request REQUEST) []attribute.KeyValue {
attributes = h.base.OnStart(attributes, parentContext, request)
fullUrl := h.base.httpGetter.GetUrlFull(request)
attributes = h.Base.OnStart(attributes, parentContext, request)
fullUrl := h.Base.HttpGetter.GetUrlFull(request)
// TODO: add resend count
attributes = append(attributes, attribute.KeyValue{
Key: semconv.URLFullKey,
Expand All @@ -57,29 +57,29 @@ func (h *HttpClientAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]) OnStart(
}

func (h *HttpClientAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]) OnEnd(attributes []attribute.KeyValue, context context.Context, request REQUEST, response RESPONSE, err error) []attribute.KeyValue {
attributes = h.base.OnEnd(attributes, context, request, response, err)
attributes = h.networkExtractor.OnEnd(attributes, context, request, response, err)
attributes = h.Base.OnEnd(attributes, context, request, response, err)
attributes = h.NetworkExtractor.OnEnd(attributes, context, request, response, err)
return attributes
}

type HttpServerAttrsExtractor[REQUEST any, RESPONSE any, GETTER1 HttpServerAttrsGetter[REQUEST, RESPONSE], GETTER2 net.NetworkAttrsGetter[REQUEST, RESPONSE], GETTER3 net.UrlAttrsGetter[REQUEST]] struct {
base HttpCommonAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]
networkExtractor net.NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER2]
urlExtractor net.UrlAttrsExtractor[REQUEST, RESPONSE, GETTER3]
Base HttpCommonAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2]
NetworkExtractor net.NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER2]
UrlExtractor net.UrlAttrsExtractor[REQUEST, RESPONSE, GETTER3]
}

func (h *HttpServerAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2, GETTER3]) OnStart(attributes []attribute.KeyValue, parentContext context.Context, request REQUEST) []attribute.KeyValue {
attributes = h.base.OnStart(attributes, parentContext, request)
attributes = h.urlExtractor.OnStart(attributes, parentContext, request)
userAgent := h.base.httpGetter.GetHttpRequestHeader(request, "User-Agent")
attributes = h.Base.OnStart(attributes, parentContext, request)
attributes = h.UrlExtractor.OnStart(attributes, parentContext, request)
userAgent := h.Base.HttpGetter.GetHttpRequestHeader(request, "User-Agent")
var firstUserAgent string
if len(userAgent) > 0 {
firstUserAgent = userAgent[0]
} else {
firstUserAgent = ""
}
attributes = append(attributes, attribute.KeyValue{Key: semconv.HTTPRouteKey,
Value: attribute.StringValue(h.base.httpGetter.GetHttpRoute(request)),
Value: attribute.StringValue(h.Base.HttpGetter.GetHttpRoute(request)),
}, attribute.KeyValue{
Key: semconv.UserAgentOriginalKey,
Value: attribute.StringValue(firstUserAgent),
Expand All @@ -88,7 +88,7 @@ func (h *HttpServerAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2, GETTER3])
}

func (h *HttpServerAttrsExtractor[REQUEST, RESPONSE, GETTER1, GETTER2, GETTER3]) OnEnd(attributes []attribute.KeyValue, context context.Context, request REQUEST, response RESPONSE, err error) []attribute.KeyValue {
attributes = h.base.OnEnd(attributes, context, request, response, err)
attributes = h.networkExtractor.OnEnd(attributes, context, request, response, err)
attributes = h.Base.OnEnd(attributes, context, request, response, err)
attributes = h.NetworkExtractor.OnEnd(attributes, context, request, response, err)
return attributes
}
20 changes: 10 additions & 10 deletions pkg/inst-api-semconv/instrumenter/http/http_attrs_extractor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ func (h httpServerAttrsGetter) GetHttpRoute(request testRequest) string {

func TestHttpClientExtractorStart(t *testing.T) {
httpClientExtractor := HttpClientAttrsExtractor[testRequest, testResponse, httpClientAttrsGetter, networkAttrsGetter]{
base: HttpCommonAttrsExtractor[testRequest, testResponse, httpClientAttrsGetter, networkAttrsGetter]{},
networkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
Base: HttpCommonAttrsExtractor[testRequest, testResponse, httpClientAttrsGetter, networkAttrsGetter]{},
NetworkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
}
attrs := make([]attribute.KeyValue, 0)
parentContext := context.Background()
Expand All @@ -210,8 +210,8 @@ func TestHttpClientExtractorStart(t *testing.T) {

func TestHttpClientExtractorEnd(t *testing.T) {
httpClientExtractor := HttpClientAttrsExtractor[testRequest, testResponse, httpClientAttrsGetter, networkAttrsGetter]{
base: HttpCommonAttrsExtractor[testRequest, testResponse, httpClientAttrsGetter, networkAttrsGetter]{},
networkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
Base: HttpCommonAttrsExtractor[testRequest, testResponse, httpClientAttrsGetter, networkAttrsGetter]{},
NetworkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
}
attrs := make([]attribute.KeyValue, 0)
parentContext := context.Background()
Expand Down Expand Up @@ -253,9 +253,9 @@ func TestHttpClientExtractorEnd(t *testing.T) {

func TestHttpServerExtractorStart(t *testing.T) {
httpServerExtractor := HttpServerAttrsExtractor[testRequest, testResponse, httpServerAttrsGetter, networkAttrsGetter, urlAttrsGetter]{
base: HttpCommonAttrsExtractor[testRequest, testResponse, httpServerAttrsGetter, networkAttrsGetter]{},
networkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
urlExtractor: net.UrlAttrsExtractor[testRequest, testResponse, urlAttrsGetter]{},
Base: HttpCommonAttrsExtractor[testRequest, testResponse, httpServerAttrsGetter, networkAttrsGetter]{},
NetworkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
UrlExtractor: net.UrlAttrsExtractor[testRequest, testResponse, urlAttrsGetter]{},
}
attrs := make([]attribute.KeyValue, 0)
parentContext := context.Background()
Expand All @@ -282,9 +282,9 @@ func TestHttpServerExtractorStart(t *testing.T) {

func TestHttpServerExtractorEnd(t *testing.T) {
httpServerExtractor := HttpServerAttrsExtractor[testRequest, testResponse, httpServerAttrsGetter, networkAttrsGetter, urlAttrsGetter]{
base: HttpCommonAttrsExtractor[testRequest, testResponse, httpServerAttrsGetter, networkAttrsGetter]{},
networkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
urlExtractor: net.UrlAttrsExtractor[testRequest, testResponse, urlAttrsGetter]{},
Base: HttpCommonAttrsExtractor[testRequest, testResponse, httpServerAttrsGetter, networkAttrsGetter]{},
NetworkExtractor: net.NetworkAttrsExtractor[testRequest, testResponse, networkAttrsGetter]{},
UrlExtractor: net.UrlAttrsExtractor[testRequest, testResponse, urlAttrsGetter]{},
}
attrs := make([]attribute.KeyValue, 0)
parentContext := context.Background()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package http

type HttpClientSpanNameExtractor[REQUEST any, RESPONSE any] struct {
getter HttpClientAttrsGetter[REQUEST, RESPONSE]
Getter HttpClientAttrsGetter[REQUEST, RESPONSE]
}

func (h *HttpClientSpanNameExtractor[REQUEST, RESPONSE]) Extract(request REQUEST) string {
method := h.getter.GetRequestMethod(request)
method := h.Getter.GetRequestMethod(request)
if method == "" {
return "HTTP"
}
return method
}

type HttpServerSpanNameExtractor[REQUEST any, RESPONSE any] struct {
getter HttpServerAttrsGetter[REQUEST, RESPONSE]
Getter HttpServerAttrsGetter[REQUEST, RESPONSE]
}

func (h *HttpServerSpanNameExtractor[REQUEST, RESPONSE]) Extract(request REQUEST) string {
method := h.getter.GetRequestMethod(request)
route := h.getter.GetHttpRoute(request)
method := h.Getter.GetRequestMethod(request)
route := h.Getter.GetHttpRoute(request)
if method == "" {
return "HTTP"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (t testServerGetter) GetHttpRoute(request testRequest) string {
}

func TestHttpClientExtractSpanName(t *testing.T) {
r := HttpClientSpanNameExtractor[testRequest, testResponse]{getter: testClientGetter{}}
r := HttpClientSpanNameExtractor[testRequest, testResponse]{Getter: testClientGetter{}}
spanName := r.Extract(testRequest{Method: "GET"})
if spanName != "GET" {
t.Errorf("want GET, got %s", spanName)
Expand All @@ -52,7 +52,7 @@ func TestHttpClientExtractSpanName(t *testing.T) {
}

func TestHttpServerExtractSpanName(t *testing.T) {
r := HttpServerSpanNameExtractor[testRequest, testResponse]{getter: testServerGetter{}}
r := HttpServerSpanNameExtractor[testRequest, testResponse]{Getter: testServerGetter{}}
spanName := r.Extract(testRequest{Method: "GET"})
if spanName != "GET" {
t.Errorf("want GET, got %s", spanName)
Expand Down
26 changes: 13 additions & 13 deletions pkg/inst-api-semconv/instrumenter/net/network_attrs_extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

type NetworkAttrsExtractor[REQUEST any, RESPONSE any, GETTER NetworkAttrsGetter[REQUEST, RESPONSE]] struct {
getter GETTER
Getter GETTER
}

func (i *NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER]) OnStart(attributes []attribute.KeyValue, parentContext context.Context, request REQUEST) []attribute.KeyValue {
Expand All @@ -18,31 +18,31 @@ func (i *NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER]) OnStart(attributes []
func (i *NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER]) OnEnd(attributes []attribute.KeyValue, context context.Context, request REQUEST, response RESPONSE, err error) []attribute.KeyValue {
attributes = append(attributes, attribute.KeyValue{
Key: semconv.NetworkTransportKey,
Value: attribute.StringValue(i.getter.GetNetworkTransport(request, response)),
Value: attribute.StringValue(i.Getter.GetNetworkTransport(request, response)),
}, attribute.KeyValue{
Key: semconv.NetworkTypeKey,
Value: attribute.StringValue(strings.ToLower(i.getter.GetNetworkType(request, response))),
Value: attribute.StringValue(strings.ToLower(i.Getter.GetNetworkType(request, response))),
}, attribute.KeyValue{
Key: semconv.NetworkProtocolNameKey,
Value: attribute.StringValue(strings.ToLower(i.getter.GetNetworkProtocolName(request, response))),
Value: attribute.StringValue(strings.ToLower(i.Getter.GetNetworkProtocolName(request, response))),
}, attribute.KeyValue{
Key: semconv.NetworkProtocolVersionKey,
Value: attribute.StringValue(strings.ToLower(i.getter.GetNetworkProtocolVersion(request, response))),
Value: attribute.StringValue(strings.ToLower(i.Getter.GetNetworkProtocolVersion(request, response))),
}, attribute.KeyValue{
Key: semconv.NetworkLocalAddressKey,
Value: attribute.StringValue(i.getter.GetNetworkLocalInetAddress(request, response)),
Value: attribute.StringValue(i.Getter.GetNetworkLocalInetAddress(request, response)),
}, attribute.KeyValue{
Key: semconv.NetworkPeerAddressKey,
Value: attribute.StringValue(i.getter.GetNetworkPeerInetAddress(request, response)),
Value: attribute.StringValue(i.Getter.GetNetworkPeerInetAddress(request, response)),
})
localPort := i.getter.GetNetworkLocalPort(request, response)
localPort := i.Getter.GetNetworkLocalPort(request, response)
if localPort > 0 {
attributes = append(attributes, attribute.KeyValue{
Key: semconv.NetworkLocalPortKey,
Value: attribute.IntValue(localPort),
})
}
peerPort := i.getter.GetNetworkPeerPort(request, response)
peerPort := i.Getter.GetNetworkPeerPort(request, response)
if peerPort > 0 {
attributes = append(attributes, attribute.KeyValue{
Key: semconv.NetworkPeerPortKey,
Expand All @@ -53,20 +53,20 @@ func (i *NetworkAttrsExtractor[REQUEST, RESPONSE, GETTER]) OnEnd(attributes []at
}

type UrlAttrsExtractor[REQUEST any, RESPONSE any, GETTER UrlAttrsGetter[REQUEST]] struct {
getter GETTER
Getter GETTER
// TODO: add scheme provider for extension
}

func (u *UrlAttrsExtractor[REQUEST, RESPONSE, GETTER]) OnStart(attributes []attribute.KeyValue, parentContext context.Context, request REQUEST) []attribute.KeyValue {
attributes = append(attributes, attribute.KeyValue{
Key: semconv.URLSchemeKey,
Value: attribute.StringValue(u.getter.GetUrlScheme(request)),
Value: attribute.StringValue(u.Getter.GetUrlScheme(request)),
}, attribute.KeyValue{
Key: semconv.URLPathKey,
Value: attribute.StringValue(u.getter.GetUrlPath(request)),
Value: attribute.StringValue(u.Getter.GetUrlPath(request)),
}, attribute.KeyValue{
Key: semconv.URLQueryKey,
Value: attribute.StringValue(u.getter.GetUrlQuery(request)),
Value: attribute.StringValue(u.Getter.GetUrlQuery(request)),
})
return attributes
}
Expand Down
17 changes: 9 additions & 8 deletions pkg/inst-api/instrumenter/instrumenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
)

type Instrumenter[REQUEST any, RESPONSE any] struct {
enabler InstrumentEnabler
spanNameExtractor SpanNameExtractor[REQUEST]
spanKindExtractor SpanKindExtractor[REQUEST]
spanStatusExtractor SpanStatusExtractor[REQUEST, RESPONSE]
Expand All @@ -23,15 +24,15 @@ type Instrumenter[REQUEST any, RESPONSE any] struct {
}

type PropagatingToDownstreamInstrumenter[REQUEST any, RESPONSE any] struct {
propagator propagation.TextMapPropagator
carrier propagation.TextMapCarrier
base Instrumenter[REQUEST, RESPONSE]
propagator propagation.TextMapPropagator
carrierGetter func(REQUEST) propagation.TextMapCarrier
base Instrumenter[REQUEST, RESPONSE]
}

type PropagatingFromUpstreamInstrumenter[REQUEST any, RESPONSE any] struct {
propagator propagation.TextMapPropagator
carrier propagation.TextMapCarrier
base Instrumenter[REQUEST, RESPONSE]
propagator propagation.TextMapPropagator
carrierGetter func(REQUEST) propagation.TextMapCarrier
base Instrumenter[REQUEST, RESPONSE]
}

func (i *Instrumenter[REQUEST, RESPONSE]) Start(parentContext context.Context, request REQUEST) context.Context {
Expand Down Expand Up @@ -90,7 +91,7 @@ func (i *Instrumenter[REQUEST, RESPONSE]) End(ctx context.Context, request REQUE

func (p *PropagatingToDownstreamInstrumenter[REQUEST, RESPONSE]) Start(parentContext context.Context, request REQUEST) context.Context {
newCtx := p.base.Start(parentContext, request)
p.propagator.Inject(newCtx, p.carrier)
p.propagator.Inject(newCtx, p.carrierGetter(request))
return newCtx
}

Expand All @@ -99,7 +100,7 @@ func (p *PropagatingToDownstreamInstrumenter[REQUEST, RESPONSE]) End(ctx context
}

func (p *PropagatingFromUpstreamInstrumenter[REQUEST, RESPONSE]) Start(parentContext context.Context, request REQUEST) context.Context {
extracted := p.propagator.Extract(parentContext, p.carrier)
extracted := p.propagator.Extract(parentContext, p.carrierGetter(request))
return p.base.Start(extracted, request)
}

Expand Down
Loading

0 comments on commit 2f49f6c

Please sign in to comment.