Skip to content

Commit 328993d

Browse files
committed
Adding server address and port to both spans and metrics
1 parent 8ce86fc commit 328993d

File tree

2 files changed

+107
-20
lines changed

2 files changed

+107
-20
lines changed

instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ def response_hook(span: Span, params: typing.Union[
9292
import typing
9393
from timeit import default_timer
9494
from typing import Collection
95+
from urllib.parse import urlparse
9596

9697
import aiohttp
9798
import wrapt
@@ -110,7 +111,10 @@ def response_hook(span: Span, params: typing.Union[
110111
_OpenTelemetryStabilitySignalType,
111112
_report_new,
112113
_report_old,
114+
_set_http_host_client,
113115
_set_http_method,
116+
_set_http_net_peer_name_client,
117+
_set_http_peer_port_client,
114118
_set_http_url,
115119
_set_status,
116120
_StabilityMode,
@@ -327,6 +331,36 @@ async def on_request_start(
327331
)
328332
_set_http_url(span_attributes, request_url, sem_conv_opt_in_mode)
329333

334+
try:
335+
parsed_url = urlparse(request_url)
336+
if parsed_url.hostname:
337+
_set_http_host_client(
338+
metric_attributes,
339+
parsed_url.hostname,
340+
sem_conv_opt_in_mode,
341+
)
342+
_set_http_net_peer_name_client(
343+
metric_attributes,
344+
parsed_url.hostname,
345+
sem_conv_opt_in_mode,
346+
)
347+
if _report_new(sem_conv_opt_in_mode):
348+
_set_http_host_client(
349+
span_attributes,
350+
parsed_url.hostname,
351+
sem_conv_opt_in_mode,
352+
)
353+
if parsed_url.port:
354+
_set_http_peer_port_client(
355+
metric_attributes, parsed_url.port, sem_conv_opt_in_mode
356+
)
357+
if _report_new(sem_conv_opt_in_mode):
358+
_set_http_peer_port_client(
359+
span_attributes, parsed_url.port, sem_conv_opt_in_mode
360+
)
361+
except ValueError:
362+
pass
363+
330364
trace_config_ctx.span = trace_config_ctx.tracer.start_span(
331365
request_span_name, kind=SpanKind.CLIENT, attributes=span_attributes
332366
)

instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,19 @@
4141
)
4242
from opentelemetry.instrumentation.utils import suppress_instrumentation
4343
from opentelemetry.semconv._incubating.attributes.http_attributes import (
44+
HTTP_HOST,
4445
HTTP_METHOD,
4546
HTTP_STATUS_CODE,
4647
HTTP_URL,
4748
)
49+
from opentelemetry.semconv._incubating.attributes.net_attributes import (
50+
NET_PEER_NAME,
51+
NET_PEER_PORT,
52+
)
53+
from opentelemetry.semconv._incubating.attributes.server_attributes import (
54+
SERVER_ADDRESS,
55+
SERVER_PORT,
56+
)
4857
from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
4958
from opentelemetry.semconv.attributes.http_attributes import (
5059
HTTP_REQUEST_METHOD,
@@ -154,6 +163,7 @@ def test_status_codes(self):
154163
HTTP_URL: url,
155164
HTTP_STATUS_CODE: status_code,
156165
}
166+
157167
spans = [("GET", (span_status, None), attributes)]
158168
self._assert_spans(spans)
159169
self.memory_exporter.clear()
@@ -164,6 +174,9 @@ def test_status_codes(self):
164174
{
165175
HTTP_STATUS_CODE: status_code,
166176
HTTP_METHOD: "GET",
177+
HTTP_HOST: host,
178+
NET_PEER_NAME: host,
179+
NET_PEER_PORT: port,
167180
},
168181
)
169182
self.assertEqual(
@@ -189,6 +202,8 @@ def test_status_codes_new_semconv(self):
189202
HTTP_REQUEST_METHOD: "GET",
190203
URL_FULL: url,
191204
HTTP_RESPONSE_STATUS_CODE: status_code,
205+
SERVER_ADDRESS: host,
206+
SERVER_PORT: port,
192207
}
193208
if status_code >= 400:
194209
attributes[ERROR_TYPE] = str(status_code.value)
@@ -234,11 +249,16 @@ def test_status_codes_both_semconv(self):
234249
attributes = {
235250
HTTP_REQUEST_METHOD: "GET",
236251
HTTP_METHOD: "GET",
252+
HTTP_HOST: host,
237253
URL_FULL: url,
238254
HTTP_URL: url,
239255
HTTP_RESPONSE_STATUS_CODE: status_code,
240256
HTTP_STATUS_CODE: status_code,
257+
SERVER_ADDRESS: host,
258+
SERVER_PORT: port,
259+
NET_PEER_PORT: port,
241260
}
261+
242262
if status_code >= 400:
243263
attributes[ERROR_TYPE] = str(status_code.value)
244264

@@ -279,26 +299,25 @@ def test_status_codes_both_semconv(self):
279299

280300
def test_metrics(self):
281301
with self.subTest(status_code=200):
282-
# Run multiple requests to test metrics
283-
number_of_requests = 3
284-
for _ in range(number_of_requests):
285-
self._http_request(
286-
trace_config=aiohttp_client.create_trace_config(),
287-
url="/test-path?query=param#foobar",
288-
status_code=200,
289-
)
290-
302+
host, port = self._http_request(
303+
trace_config=aiohttp_client.create_trace_config(),
304+
url="/test-path?query=param#foobar",
305+
status_code=200,
306+
)
291307
metrics = self._assert_metrics(1)
292308
self.assertEqual(len(metrics[0].data.data_points), 1)
293309
duration_data_point = metrics[0].data.data_points[0]
294310
self.assertEqual(
295-
dict(duration_data_point.attributes),
311+
dict(metrics[0].data.data_points[0].attributes),
296312
{
297313
HTTP_STATUS_CODE: 200,
298314
HTTP_METHOD: "GET",
315+
HTTP_HOST: host,
316+
NET_PEER_NAME: host,
317+
NET_PEER_PORT: port,
299318
},
300319
)
301-
self.assertEqual(duration_data_point.count, number_of_requests)
320+
self.assertEqual(duration_data_point.count, 1)
302321
self.assertTrue(duration_data_point.min > 0)
303322
self.assertTrue(duration_data_point.max > 0)
304323
self.assertTrue(duration_data_point.sum > 0)
@@ -502,6 +521,9 @@ async def request_handler(request):
502521
dict(duration_data_point.attributes),
503522
{
504523
HTTP_METHOD: "GET",
524+
HTTP_HOST: host,
525+
NET_PEER_NAME: host,
526+
NET_PEER_PORT: port,
505527
},
506528
)
507529

@@ -528,6 +550,8 @@ async def request_handler(request):
528550
HTTP_REQUEST_METHOD: "GET",
529551
URL_FULL: f"http://{host}:{port}/test",
530552
ERROR_TYPE: "ServerDisconnectedError",
553+
SERVER_ADDRESS: host,
554+
SERVER_PORT: port,
531555
},
532556
)
533557
]
@@ -539,6 +563,8 @@ async def request_handler(request):
539563
{
540564
HTTP_REQUEST_METHOD: "GET",
541565
ERROR_TYPE: "ServerDisconnectedError",
566+
SERVER_ADDRESS: host,
567+
SERVER_PORT: port,
542568
},
543569
)
544570

@@ -567,6 +593,10 @@ async def request_handler(request):
567593
ERROR_TYPE: "ServerDisconnectedError",
568594
HTTP_METHOD: "GET",
569595
HTTP_URL: f"http://{host}:{port}/test",
596+
HTTP_HOST: host,
597+
SERVER_ADDRESS: host,
598+
SERVER_PORT: port,
599+
NET_PEER_PORT: port,
570600
},
571601
)
572602
]
@@ -577,6 +607,9 @@ async def request_handler(request):
577607
dict(duration_data_point.attributes),
578608
{
579609
HTTP_METHOD: "GET",
610+
HTTP_HOST: host,
611+
NET_PEER_NAME: host,
612+
NET_PEER_PORT: port,
580613
},
581614
)
582615
duration_data_point = metrics[1].data.data_points[0]
@@ -585,6 +618,8 @@ async def request_handler(request):
585618
{
586619
HTTP_REQUEST_METHOD: "GET",
587620
ERROR_TYPE: "ServerDisconnectedError",
621+
SERVER_ADDRESS: host,
622+
SERVER_PORT: port,
588623
},
589624
)
590625

@@ -719,6 +754,8 @@ async def do_request(url):
719754
),
720755
HTTP_REQUEST_METHOD_ORIGINAL: "NONSTANDARD",
721756
ERROR_TYPE: "405",
757+
SERVER_ADDRESS: "localhost",
758+
SERVER_PORT: 5000,
722759
},
723760
)
724761
]
@@ -822,8 +859,11 @@ def test_instrument(self):
822859
self.assertEqual(
823860
dict(duration_data_point.attributes),
824861
{
862+
HTTP_HOST: host,
825863
HTTP_STATUS_CODE: 200,
826864
HTTP_METHOD: "GET",
865+
NET_PEER_NAME: host,
866+
NET_PEER_PORT: port,
827867
},
828868
)
829869

@@ -852,6 +892,8 @@ def test_instrument_new_semconv(self):
852892
{
853893
HTTP_RESPONSE_STATUS_CODE: 200,
854894
HTTP_REQUEST_METHOD: "GET",
895+
SERVER_ADDRESS: host,
896+
SERVER_PORT: port,
855897
},
856898
)
857899

@@ -865,17 +907,23 @@ def test_instrument_both_semconv(self):
865907
self.get_default_request(), self.URL, self.default_handler
866908
)
867909
url = f"http://{host}:{port}/test-path"
868-
attributes = {
869-
HTTP_REQUEST_METHOD: "GET",
870-
HTTP_METHOD: "GET",
871-
URL_FULL: url,
872-
HTTP_URL: url,
873-
HTTP_RESPONSE_STATUS_CODE: 200,
874-
HTTP_STATUS_CODE: 200,
875-
}
876910
span = self._assert_spans(1)
877911
self.assertEqual("GET", span.name)
878-
self.assertEqual(span.attributes, attributes)
912+
self.assertEqual(
913+
dict(span.attributes),
914+
{
915+
HTTP_REQUEST_METHOD: "GET",
916+
HTTP_METHOD: "GET",
917+
HTTP_HOST: host,
918+
URL_FULL: url,
919+
HTTP_URL: url,
920+
HTTP_RESPONSE_STATUS_CODE: 200,
921+
HTTP_STATUS_CODE: 200,
922+
SERVER_ADDRESS: host,
923+
SERVER_PORT: port,
924+
NET_PEER_PORT: port,
925+
},
926+
)
879927
metrics = self._assert_metrics(2)
880928
duration_data_point = metrics[0].data.data_points[0]
881929
self.assertEqual(duration_data_point.count, 1)
@@ -884,6 +932,9 @@ def test_instrument_both_semconv(self):
884932
{
885933
HTTP_STATUS_CODE: 200,
886934
HTTP_METHOD: "GET",
935+
HTTP_HOST: host,
936+
NET_PEER_NAME: host,
937+
NET_PEER_PORT: port,
887938
},
888939
)
889940
duration_data_point = metrics[1].data.data_points[0]
@@ -893,6 +944,8 @@ def test_instrument_both_semconv(self):
893944
{
894945
HTTP_RESPONSE_STATUS_CODE: 200,
895946
HTTP_REQUEST_METHOD: "GET",
947+
SERVER_ADDRESS: host,
948+
SERVER_PORT: port,
896949
},
897950
)
898951

0 commit comments

Comments
 (0)