You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2026-06-03 18:35:08 +02:00
Add http.method attribute to http server metric (#3018)
* Add http.method attribute to http server metric Signed-off-by: Ziqi Zhao <zhaoziqi9146@gmail.com> * fix lint Signed-off-by: Ziqi Zhao <zhaoziqi9146@gmail.com> * fix lint Signed-off-by: Ziqi Zhao <zhaoziqi9146@gmail.com> * fix for reviews Signed-off-by: Ziqi Zhao <zhaoziqi9146@gmail.com> * add changelog entry Signed-off-by: Ziqi Zhao <zhaoziqi9146@gmail.com>
This commit is contained in:
@@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
The package contains semantic conventions from the `v1.12.0` version of the OpenTelemetry specification. (#3010)
|
||||
- Add the `go.opentelemetry.io/otel/semconv/v1.11.0` package.
|
||||
The package contains semantic conventions from the `v1.11.0` version of the OpenTelemetry specification. (#3009)
|
||||
- Add http.method attribute to http server metric. (#3018)
|
||||
|
||||
## [1.8.0/0.31.0] - 2022-07-08
|
||||
|
||||
|
||||
@@ -147,12 +147,6 @@ func (sc *SemanticConventions) EndUserAttributesFromHTTPRequest(request *http.Re
|
||||
func (sc *SemanticConventions) HTTPClientAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue {
|
||||
attrs := []attribute.KeyValue{}
|
||||
|
||||
if request.Method != "" {
|
||||
attrs = append(attrs, sc.HTTPMethodKey.String(request.Method))
|
||||
} else {
|
||||
attrs = append(attrs, sc.HTTPMethodKey.String(http.MethodGet))
|
||||
}
|
||||
|
||||
// remove any username/password info that may be in the URL
|
||||
// before adding it to the attributes
|
||||
userinfo := request.URL.User
|
||||
@@ -204,6 +198,12 @@ func (sc *SemanticConventions) httpBasicAttributesFromHTTPRequest(request *http.
|
||||
attrs = append(attrs, sc.HTTPFlavorKey.String(flavor))
|
||||
}
|
||||
|
||||
if request.Method != "" {
|
||||
attrs = append(attrs, sc.HTTPMethodKey.String(request.Method))
|
||||
} else {
|
||||
attrs = append(attrs, sc.HTTPMethodKey.String(http.MethodGet))
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
@@ -223,7 +223,6 @@ func (sc *SemanticConventions) HTTPServerMetricAttributesFromHTTPRequest(serverN
|
||||
// supported.
|
||||
func (sc *SemanticConventions) HTTPServerAttributesFromHTTPRequest(serverName, route string, request *http.Request) []attribute.KeyValue {
|
||||
attrs := []attribute.KeyValue{
|
||||
sc.HTTPMethodKey.String(request.Method),
|
||||
sc.HTTPTargetKey.String(request.RequestURI),
|
||||
}
|
||||
|
||||
|
||||
@@ -1236,3 +1236,288 @@ func TestHTTPClientAttributesFromHTTPRequest(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPServerMetricAttributesFromHTTPRequest(t *testing.T) {
|
||||
type testcase struct {
|
||||
name string
|
||||
serverName string
|
||||
method string
|
||||
requestURI string
|
||||
proto string
|
||||
remoteAddr string
|
||||
host string
|
||||
url *url.URL
|
||||
header http.Header
|
||||
tls tlsOption
|
||||
contentLength int64
|
||||
expected []attribute.KeyValue
|
||||
}
|
||||
testcases := []testcase{
|
||||
{
|
||||
name: "stripped",
|
||||
serverName: "",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: nil,
|
||||
tls: noTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "http"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with server name",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: nil,
|
||||
tls: noTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "http"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with tls",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: nil,
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with route",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: nil,
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with host",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "example.com",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: nil,
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
attribute.String("http.host", "example.com"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with host fallback",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "",
|
||||
url: &url.URL{
|
||||
Host: "example.com",
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: nil,
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
attribute.String("http.host", "example.com"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with user agent",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "example.com",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: http.Header{
|
||||
"User-Agent": []string{"foodownloader"},
|
||||
},
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
attribute.String("http.host", "example.com"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with proxy info",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "example.com",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: http.Header{
|
||||
"User-Agent": []string{"foodownloader"},
|
||||
"X-Forwarded-For": []string{"203.0.113.195, 70.41.3.18, 150.172.238.178"},
|
||||
},
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
attribute.String("http.host", "example.com"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with http 1.1",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.1",
|
||||
remoteAddr: "",
|
||||
host: "example.com",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: http.Header{
|
||||
"User-Agent": []string{"foodownloader"},
|
||||
"X-Forwarded-For": []string{"1.2.3.4"},
|
||||
},
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "1.1"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
attribute.String("http.host", "example.com"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with http 2",
|
||||
serverName: "my-server-name",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/2.0",
|
||||
remoteAddr: "",
|
||||
host: "example.com",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: http.Header{
|
||||
"User-Agent": []string{"foodownloader"},
|
||||
"X-Forwarded-For": []string{"1.2.3.4"},
|
||||
},
|
||||
tls: withTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "https"),
|
||||
attribute.String("http.flavor", "2"),
|
||||
attribute.String("http.server_name", "my-server-name"),
|
||||
attribute.String("http.host", "example.com"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for idx, tc := range testcases {
|
||||
r := testRequest(tc.method, tc.requestURI, tc.proto, tc.remoteAddr, tc.host, tc.url, tc.header, tc.tls)
|
||||
r.ContentLength = tc.contentLength
|
||||
got := sc.HTTPServerMetricAttributesFromHTTPRequest(tc.serverName, r)
|
||||
assertElementsMatch(t, tc.expected, got, "testcase %d - %s", idx, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHttpBasicAttributesFromHTTPRequest(t *testing.T) {
|
||||
type testcase struct {
|
||||
name string
|
||||
method string
|
||||
requestURI string
|
||||
proto string
|
||||
remoteAddr string
|
||||
host string
|
||||
url *url.URL
|
||||
header http.Header
|
||||
tls tlsOption
|
||||
contentLength int64
|
||||
expected []attribute.KeyValue
|
||||
}
|
||||
testcases := []testcase{
|
||||
{
|
||||
name: "stripped",
|
||||
method: "GET",
|
||||
requestURI: "/user/123",
|
||||
proto: "HTTP/1.0",
|
||||
remoteAddr: "",
|
||||
host: "example.com",
|
||||
url: &url.URL{
|
||||
Path: "/user/123",
|
||||
},
|
||||
header: nil,
|
||||
tls: noTLS,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("http.method", "GET"),
|
||||
attribute.String("http.scheme", "http"),
|
||||
attribute.String("http.flavor", "1.0"),
|
||||
attribute.String("http.host", "example.com"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for idx, tc := range testcases {
|
||||
r := testRequest(tc.method, tc.requestURI, tc.proto, tc.remoteAddr, tc.host, tc.url, tc.header, tc.tls)
|
||||
r.ContentLength = tc.contentLength
|
||||
got := sc.httpBasicAttributesFromHTTPRequest(r)
|
||||
assertElementsMatch(t, tc.expected, got, "testcase %d - %s", idx, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user