Skip to content

Commit 096a162

Browse files
authored
Add http.method attribute to http server metric (#3018)
* Add http.method attribute to http server metric Signed-off-by: Ziqi Zhao <[email protected]> * fix lint Signed-off-by: Ziqi Zhao <[email protected]> * fix lint Signed-off-by: Ziqi Zhao <[email protected]> * fix for reviews Signed-off-by: Ziqi Zhao <[email protected]> * add changelog entry Signed-off-by: Ziqi Zhao <[email protected]>
1 parent 5568a30 commit 096a162

3 files changed

Lines changed: 292 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1414
The package contains semantic conventions from the `v1.12.0` version of the OpenTelemetry specification. (#3010)
1515
- Add the `go.opentelemetry.io/otel/semconv/v1.11.0` package.
1616
The package contains semantic conventions from the `v1.11.0` version of the OpenTelemetry specification. (#3009)
17+
- Add http.method attribute to http server metric. (#3018)
1718

1819
## [1.8.0/0.31.0] - 2022-07-08
1920

semconv/internal/http.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,6 @@ func (sc *SemanticConventions) EndUserAttributesFromHTTPRequest(request *http.Re
147147
func (sc *SemanticConventions) HTTPClientAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue {
148148
attrs := []attribute.KeyValue{}
149149

150-
if request.Method != "" {
151-
attrs = append(attrs, sc.HTTPMethodKey.String(request.Method))
152-
} else {
153-
attrs = append(attrs, sc.HTTPMethodKey.String(http.MethodGet))
154-
}
155-
156150
// remove any username/password info that may be in the URL
157151
// before adding it to the attributes
158152
userinfo := request.URL.User
@@ -204,6 +198,12 @@ func (sc *SemanticConventions) httpBasicAttributesFromHTTPRequest(request *http.
204198
attrs = append(attrs, sc.HTTPFlavorKey.String(flavor))
205199
}
206200

201+
if request.Method != "" {
202+
attrs = append(attrs, sc.HTTPMethodKey.String(request.Method))
203+
} else {
204+
attrs = append(attrs, sc.HTTPMethodKey.String(http.MethodGet))
205+
}
206+
207207
return attrs
208208
}
209209

@@ -223,7 +223,6 @@ func (sc *SemanticConventions) HTTPServerMetricAttributesFromHTTPRequest(serverN
223223
// supported.
224224
func (sc *SemanticConventions) HTTPServerAttributesFromHTTPRequest(serverName, route string, request *http.Request) []attribute.KeyValue {
225225
attrs := []attribute.KeyValue{
226-
sc.HTTPMethodKey.String(request.Method),
227226
sc.HTTPTargetKey.String(request.RequestURI),
228227
}
229228

semconv/internal/http_test.go

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,3 +1236,288 @@ func TestHTTPClientAttributesFromHTTPRequest(t *testing.T) {
12361236
})
12371237
}
12381238
}
1239+
1240+
func TestHTTPServerMetricAttributesFromHTTPRequest(t *testing.T) {
1241+
type testcase struct {
1242+
name string
1243+
serverName string
1244+
method string
1245+
requestURI string
1246+
proto string
1247+
remoteAddr string
1248+
host string
1249+
url *url.URL
1250+
header http.Header
1251+
tls tlsOption
1252+
contentLength int64
1253+
expected []attribute.KeyValue
1254+
}
1255+
testcases := []testcase{
1256+
{
1257+
name: "stripped",
1258+
serverName: "",
1259+
method: "GET",
1260+
requestURI: "/user/123",
1261+
proto: "HTTP/1.0",
1262+
remoteAddr: "",
1263+
host: "",
1264+
url: &url.URL{
1265+
Path: "/user/123",
1266+
},
1267+
header: nil,
1268+
tls: noTLS,
1269+
expected: []attribute.KeyValue{
1270+
attribute.String("http.method", "GET"),
1271+
attribute.String("http.scheme", "http"),
1272+
attribute.String("http.flavor", "1.0"),
1273+
},
1274+
},
1275+
{
1276+
name: "with server name",
1277+
serverName: "my-server-name",
1278+
method: "GET",
1279+
requestURI: "/user/123",
1280+
proto: "HTTP/1.0",
1281+
remoteAddr: "",
1282+
host: "",
1283+
url: &url.URL{
1284+
Path: "/user/123",
1285+
},
1286+
header: nil,
1287+
tls: noTLS,
1288+
expected: []attribute.KeyValue{
1289+
attribute.String("http.method", "GET"),
1290+
attribute.String("http.scheme", "http"),
1291+
attribute.String("http.flavor", "1.0"),
1292+
attribute.String("http.server_name", "my-server-name"),
1293+
},
1294+
},
1295+
{
1296+
name: "with tls",
1297+
serverName: "my-server-name",
1298+
method: "GET",
1299+
requestURI: "/user/123",
1300+
proto: "HTTP/1.0",
1301+
remoteAddr: "",
1302+
host: "",
1303+
url: &url.URL{
1304+
Path: "/user/123",
1305+
},
1306+
header: nil,
1307+
tls: withTLS,
1308+
expected: []attribute.KeyValue{
1309+
attribute.String("http.method", "GET"),
1310+
attribute.String("http.scheme", "https"),
1311+
attribute.String("http.flavor", "1.0"),
1312+
attribute.String("http.server_name", "my-server-name"),
1313+
},
1314+
},
1315+
{
1316+
name: "with route",
1317+
serverName: "my-server-name",
1318+
method: "GET",
1319+
requestURI: "/user/123",
1320+
proto: "HTTP/1.0",
1321+
remoteAddr: "",
1322+
host: "",
1323+
url: &url.URL{
1324+
Path: "/user/123",
1325+
},
1326+
header: nil,
1327+
tls: withTLS,
1328+
expected: []attribute.KeyValue{
1329+
attribute.String("http.method", "GET"),
1330+
attribute.String("http.scheme", "https"),
1331+
attribute.String("http.flavor", "1.0"),
1332+
attribute.String("http.server_name", "my-server-name"),
1333+
},
1334+
},
1335+
{
1336+
name: "with host",
1337+
serverName: "my-server-name",
1338+
method: "GET",
1339+
requestURI: "/user/123",
1340+
proto: "HTTP/1.0",
1341+
remoteAddr: "",
1342+
host: "example.com",
1343+
url: &url.URL{
1344+
Path: "/user/123",
1345+
},
1346+
header: nil,
1347+
tls: withTLS,
1348+
expected: []attribute.KeyValue{
1349+
attribute.String("http.method", "GET"),
1350+
attribute.String("http.scheme", "https"),
1351+
attribute.String("http.flavor", "1.0"),
1352+
attribute.String("http.server_name", "my-server-name"),
1353+
attribute.String("http.host", "example.com"),
1354+
},
1355+
},
1356+
{
1357+
name: "with host fallback",
1358+
serverName: "my-server-name",
1359+
method: "GET",
1360+
requestURI: "/user/123",
1361+
proto: "HTTP/1.0",
1362+
remoteAddr: "",
1363+
host: "",
1364+
url: &url.URL{
1365+
Host: "example.com",
1366+
Path: "/user/123",
1367+
},
1368+
header: nil,
1369+
tls: withTLS,
1370+
expected: []attribute.KeyValue{
1371+
attribute.String("http.method", "GET"),
1372+
attribute.String("http.scheme", "https"),
1373+
attribute.String("http.flavor", "1.0"),
1374+
attribute.String("http.server_name", "my-server-name"),
1375+
attribute.String("http.host", "example.com"),
1376+
},
1377+
},
1378+
{
1379+
name: "with user agent",
1380+
serverName: "my-server-name",
1381+
method: "GET",
1382+
requestURI: "/user/123",
1383+
proto: "HTTP/1.0",
1384+
remoteAddr: "",
1385+
host: "example.com",
1386+
url: &url.URL{
1387+
Path: "/user/123",
1388+
},
1389+
header: http.Header{
1390+
"User-Agent": []string{"foodownloader"},
1391+
},
1392+
tls: withTLS,
1393+
expected: []attribute.KeyValue{
1394+
attribute.String("http.method", "GET"),
1395+
attribute.String("http.scheme", "https"),
1396+
attribute.String("http.flavor", "1.0"),
1397+
attribute.String("http.server_name", "my-server-name"),
1398+
attribute.String("http.host", "example.com"),
1399+
},
1400+
},
1401+
{
1402+
name: "with proxy info",
1403+
serverName: "my-server-name",
1404+
method: "GET",
1405+
requestURI: "/user/123",
1406+
proto: "HTTP/1.0",
1407+
remoteAddr: "",
1408+
host: "example.com",
1409+
url: &url.URL{
1410+
Path: "/user/123",
1411+
},
1412+
header: http.Header{
1413+
"User-Agent": []string{"foodownloader"},
1414+
"X-Forwarded-For": []string{"203.0.113.195, 70.41.3.18, 150.172.238.178"},
1415+
},
1416+
tls: withTLS,
1417+
expected: []attribute.KeyValue{
1418+
attribute.String("http.method", "GET"),
1419+
attribute.String("http.scheme", "https"),
1420+
attribute.String("http.flavor", "1.0"),
1421+
attribute.String("http.server_name", "my-server-name"),
1422+
attribute.String("http.host", "example.com"),
1423+
},
1424+
},
1425+
{
1426+
name: "with http 1.1",
1427+
serverName: "my-server-name",
1428+
method: "GET",
1429+
requestURI: "/user/123",
1430+
proto: "HTTP/1.1",
1431+
remoteAddr: "",
1432+
host: "example.com",
1433+
url: &url.URL{
1434+
Path: "/user/123",
1435+
},
1436+
header: http.Header{
1437+
"User-Agent": []string{"foodownloader"},
1438+
"X-Forwarded-For": []string{"1.2.3.4"},
1439+
},
1440+
tls: withTLS,
1441+
expected: []attribute.KeyValue{
1442+
attribute.String("http.method", "GET"),
1443+
attribute.String("http.scheme", "https"),
1444+
attribute.String("http.flavor", "1.1"),
1445+
attribute.String("http.server_name", "my-server-name"),
1446+
attribute.String("http.host", "example.com"),
1447+
},
1448+
},
1449+
{
1450+
name: "with http 2",
1451+
serverName: "my-server-name",
1452+
method: "GET",
1453+
requestURI: "/user/123",
1454+
proto: "HTTP/2.0",
1455+
remoteAddr: "",
1456+
host: "example.com",
1457+
url: &url.URL{
1458+
Path: "/user/123",
1459+
},
1460+
header: http.Header{
1461+
"User-Agent": []string{"foodownloader"},
1462+
"X-Forwarded-For": []string{"1.2.3.4"},
1463+
},
1464+
tls: withTLS,
1465+
expected: []attribute.KeyValue{
1466+
attribute.String("http.method", "GET"),
1467+
attribute.String("http.scheme", "https"),
1468+
attribute.String("http.flavor", "2"),
1469+
attribute.String("http.server_name", "my-server-name"),
1470+
attribute.String("http.host", "example.com"),
1471+
},
1472+
},
1473+
}
1474+
for idx, tc := range testcases {
1475+
r := testRequest(tc.method, tc.requestURI, tc.proto, tc.remoteAddr, tc.host, tc.url, tc.header, tc.tls)
1476+
r.ContentLength = tc.contentLength
1477+
got := sc.HTTPServerMetricAttributesFromHTTPRequest(tc.serverName, r)
1478+
assertElementsMatch(t, tc.expected, got, "testcase %d - %s", idx, tc.name)
1479+
}
1480+
}
1481+
1482+
func TestHttpBasicAttributesFromHTTPRequest(t *testing.T) {
1483+
type testcase struct {
1484+
name string
1485+
method string
1486+
requestURI string
1487+
proto string
1488+
remoteAddr string
1489+
host string
1490+
url *url.URL
1491+
header http.Header
1492+
tls tlsOption
1493+
contentLength int64
1494+
expected []attribute.KeyValue
1495+
}
1496+
testcases := []testcase{
1497+
{
1498+
name: "stripped",
1499+
method: "GET",
1500+
requestURI: "/user/123",
1501+
proto: "HTTP/1.0",
1502+
remoteAddr: "",
1503+
host: "example.com",
1504+
url: &url.URL{
1505+
Path: "/user/123",
1506+
},
1507+
header: nil,
1508+
tls: noTLS,
1509+
expected: []attribute.KeyValue{
1510+
attribute.String("http.method", "GET"),
1511+
attribute.String("http.scheme", "http"),
1512+
attribute.String("http.flavor", "1.0"),
1513+
attribute.String("http.host", "example.com"),
1514+
},
1515+
},
1516+
}
1517+
for idx, tc := range testcases {
1518+
r := testRequest(tc.method, tc.requestURI, tc.proto, tc.remoteAddr, tc.host, tc.url, tc.header, tc.tls)
1519+
r.ContentLength = tc.contentLength
1520+
got := sc.httpBasicAttributesFromHTTPRequest(r)
1521+
assertElementsMatch(t, tc.expected, got, "testcase %d - %s", idx, tc.name)
1522+
}
1523+
}

0 commit comments

Comments
 (0)