Skip to content

Commit 82a7f76

Browse files
authored
Add tests for live metrics types + support stable http semconv (Azure#39555)
1 parent b6f9860 commit 82a7f76

File tree

7 files changed

+310
-74
lines changed

7 files changed

+310
-74
lines changed

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
_WEBSITE_HOME_STAMPNAME = "WEBSITE_HOME_STAMPNAME"
1919
_WEBSITE_HOSTNAME = "WEBSITE_HOSTNAME"
2020
_FUNCTIONS_WORKER_RUNTIME = "FUNCTIONS_WORKER_RUNTIME"
21-
_PYTHON_ENABLE_OPENTELEMETRY = "PYTHON_ENABLE_OPENTELEMETRY"
21+
_PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY = "PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY"
2222
_AKS_ARM_NAMESPACE_ID = "AKS_ARM_NAMESPACE_ID"
2323

2424
# Network

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_quickpulse/_types.py

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
from opentelemetry.sdk._logs import LogRecord
88
from opentelemetry.sdk.trace import Event, ReadableSpan
9+
from opentelemetry.semconv._incubating.attributes import gen_ai_attributes
10+
from opentelemetry.semconv.attributes.http_attributes import (
11+
HTTP_REQUEST_METHOD,
12+
HTTP_RESPONSE_STATUS_CODE,
13+
)
914
from opentelemetry.semconv.trace import SpanAttributes
1015
from opentelemetry.trace import SpanKind
1116

@@ -54,7 +59,8 @@ def _from_span(span: ReadableSpan):
5459
if span.attributes:
5560
attributes = span.attributes
5661
url = trace_utils._get_url_for_http_request(attributes)
57-
status_code = attributes.get(SpanAttributes.HTTP_STATUS_CODE)
62+
status_code = attributes.get(HTTP_RESPONSE_STATUS_CODE) or \
63+
attributes.get(SpanAttributes.HTTP_STATUS_CODE)
5864
if status_code:
5965
try:
6066
status_code = int(status_code)
@@ -94,44 +100,47 @@ def _from_span(span: ReadableSpan):
94100
attributes = {}
95101
dependency_type = "InProc"
96102
data = ""
103+
target = ""
97104
if span.end_time and span.start_time:
98105
duration_ms = (span.end_time - span.start_time) / 1e9
99106
if span.attributes:
100107
attributes = span.attributes
101108
target = trace_utils._get_target_for_dependency_from_peer(attributes)
102-
if SpanAttributes.HTTP_METHOD in attributes:
103-
dependency_type = "HTTP"
104-
url = trace_utils._get_url_for_http_dependency(attributes)
105-
target, _ = trace_utils._get_target_and_path_for_http_dependency(
106-
attributes,
107-
target,
108-
url,
109-
)
110-
data = url
111-
elif SpanAttributes.DB_SYSTEM in attributes:
112-
db_system = attributes[SpanAttributes.DB_SYSTEM]
113-
dependency_type = db_system
114-
target = trace_utils._get_target_for_db_dependency(
115-
target,
116-
db_system,
117-
attributes,
118-
)
119-
if SpanAttributes.DB_STATEMENT in attributes:
120-
data = attributes[SpanAttributes.DB_STATEMENT]
121-
elif SpanAttributes.DB_OPERATION in attributes:
122-
data = attributes[SpanAttributes.DB_OPERATION]
123-
elif SpanAttributes.MESSAGING_SYSTEM in attributes:
124-
dependency_type = attributes[SpanAttributes.MESSAGING_SYSTEM]
125-
target = trace_utils._get_target_for_messaging_dependency(
126-
target,
127-
attributes,
128-
)
129-
elif SpanAttributes.RPC_SYSTEM in attributes:
130-
dependency_type = attributes[SpanAttributes.RPC_SYSTEM]
131-
target = trace_utils._get_target_for_rpc_dependency(
132-
target,
133-
attributes,
134-
)
109+
if span.kind is SpanKind.CLIENT:
110+
if HTTP_REQUEST_METHOD in attributes or SpanAttributes.HTTP_METHOD in attributes:
111+
dependency_type = "HTTP"
112+
url = trace_utils._get_url_for_http_dependency(attributes)
113+
target, _ = trace_utils._get_target_and_path_for_http_dependency(
114+
attributes,
115+
url,
116+
)
117+
data = url
118+
elif SpanAttributes.DB_SYSTEM in attributes:
119+
db_system = attributes[SpanAttributes.DB_SYSTEM]
120+
dependency_type = db_system
121+
target = trace_utils._get_target_for_db_dependency(
122+
target,
123+
db_system,
124+
attributes,
125+
)
126+
if SpanAttributes.DB_STATEMENT in attributes:
127+
data = attributes[SpanAttributes.DB_STATEMENT]
128+
elif SpanAttributes.DB_OPERATION in attributes:
129+
data = attributes[SpanAttributes.DB_OPERATION]
130+
elif SpanAttributes.MESSAGING_SYSTEM in attributes:
131+
dependency_type = attributes[SpanAttributes.MESSAGING_SYSTEM]
132+
target = trace_utils._get_target_for_messaging_dependency(
133+
target,
134+
attributes,
135+
)
136+
elif SpanAttributes.RPC_SYSTEM in attributes:
137+
dependency_type = attributes[SpanAttributes.RPC_SYSTEM]
138+
target = trace_utils._get_target_for_rpc_dependency(
139+
target,
140+
attributes,
141+
)
142+
elif gen_ai_attributes.GEN_AI_SYSTEM in span.attributes:
143+
dependency_type = attributes[gen_ai_attributes.GEN_AI_SYSTEM]
135144
elif span.kind is SpanKind.PRODUCER:
136145
dependency_type = "Queue Message"
137146
msg_system = attributes.get(SpanAttributes.MESSAGING_SYSTEM)

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
from azure.monitor.opentelemetry.exporter._constants import (
2424
_AKS_ARM_NAMESPACE_ID,
2525
_DEFAULT_AAD_SCOPE,
26-
_PYTHON_ENABLE_OPENTELEMETRY,
2726
_INSTRUMENTATIONS_BIT_MAP,
2827
_FUNCTIONS_WORKER_RUNTIME,
28+
_PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY,
2929
_WEBSITE_SITE_NAME,
3030
)
3131

@@ -73,7 +73,7 @@ def _is_attach_enabled():
7373
if _is_on_app_service():
7474
return isdir("/agents/python/")
7575
if _is_on_functions():
76-
return environ.get(_PYTHON_ENABLE_OPENTELEMETRY) == "true"
76+
return environ.get(_PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY) == "true"
7777
return False
7878

7979

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/trace/_exporter.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ def _convert_span_to_envelope(span: ReadableSpan) -> TelemetryItem:
348348
data.data = url
349349
target, path = trace_utils._get_target_and_path_for_http_dependency(
350350
span.attributes,
351-
target, # type: ignore
352351
url,
353352
)
354353
# http specific logic for name

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/trace/_utils.py

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ def _get_target_for_dependency_from_peer(attributes: Attributes) -> Optional[str
152152
@no_type_check
153153
def _get_target_and_path_for_http_dependency(
154154
attributes: Attributes,
155-
target: Optional[str] = "",
156155
url: Optional[str] = "", # Usually populated by _get_url_for_http_dependency()
157156
) -> Tuple[Optional[str], str]:
158157
parsed_url = None
@@ -174,29 +173,33 @@ def _get_target_and_path_for_http_dependency(
174173
# if not default port, include port in target
175174
if server_port != default_port:
176175
target = "{}:{}".format(target, server_port)
177-
# We only use these values for target if not already populated by peer.service
178-
elif not SpanAttributes.PEER_SERVICE in attributes:
179-
# Target from http.host
180-
if SpanAttributes.HTTP_HOST in attributes:
181-
host = attributes[SpanAttributes.HTTP_HOST]
182-
try:
183-
# urlparse insists on absolute URLs starting with "//"
184-
# This logic assumes host does not include a "//"
185-
host_name = urlparse("//" + str(host))
186-
# Ignore port from target if default port
187-
if host_name.port == default_port:
188-
target = host_name.hostname
189-
else:
190-
# Else include the whole host as the target
191-
target = str(host)
192-
except Exception: # pylint: disable=broad-except
193-
pass
194-
elif parsed_url:
195-
# Target from httpUrl
196-
if parsed_url.port and parsed_url.port == default_port:
197-
target = parsed_url.hostname
176+
# Target from peer.service
177+
elif SpanAttributes.PEER_SERVICE in attributes:
178+
target = attributes[SpanAttributes.PEER_SERVICE]
179+
# Target from http.host
180+
elif SpanAttributes.HTTP_HOST in attributes:
181+
host = attributes[SpanAttributes.HTTP_HOST]
182+
try:
183+
# urlparse insists on absolute URLs starting with "//"
184+
# This logic assumes host does not include a "//"
185+
host_name = urlparse("//" + str(host))
186+
# Ignore port from target if default port
187+
if host_name.port == default_port:
188+
target = host_name.hostname
198189
else:
199-
target = parsed_url.netloc
190+
# Else include the whole host as the target
191+
target = str(host)
192+
except Exception: # pylint: disable=broad-except
193+
pass
194+
elif parsed_url:
195+
# Target from httpUrl
196+
if parsed_url.port and parsed_url.port == default_port:
197+
target = parsed_url.hostname
198+
else:
199+
target = parsed_url.netloc
200+
else:
201+
# Get target from peer.* attributes that are NOT peer.service
202+
target = _get_target_for_dependency_from_peer(attributes)
200203
return (target, path)
201204

202205

@@ -268,24 +271,24 @@ def _get_url_for_http_request(attributes: Attributes) -> Optional[str]:
268271
http_target = ""
269272
if url_attributes.URL_PATH in attributes:
270273
http_target = attributes.get(url_attributes.URL_PATH, "")
271-
if url_attributes.URL_QUERY in attributes:
272-
http_target = "{}?{}".format(
273-
http_target,
274-
attributes.get(url_attributes.URL_QUERY, "")
275-
)
276-
if not http_target:
274+
if http_target and url_attributes.URL_QUERY in attributes:
275+
http_target = "{}?{}".format(
276+
http_target,
277+
attributes.get(url_attributes.URL_QUERY, "")
278+
)
279+
elif SpanAttributes.HTTP_TARGET in attributes:
277280
http_target = attributes.get(SpanAttributes.HTTP_TARGET)
278281
if scheme and http_target:
279282
# Host
280283
http_host = ""
281284
if server_attributes.SERVER_ADDRESS in attributes:
282285
http_host = attributes.get(server_attributes.SERVER_ADDRESS, "")
283-
if server_attributes.SERVER_PORT in attributes:
284-
http_host = "{}:{}".format(
285-
http_host,
286-
attributes.get(server_attributes.SERVER_PORT, "")
287-
)
288-
if not http_host:
286+
if http_host and server_attributes.SERVER_PORT in attributes:
287+
http_host = "{}:{}".format(
288+
http_host,
289+
attributes.get(server_attributes.SERVER_PORT, "")
290+
)
291+
elif SpanAttributes.HTTP_HOST in attributes:
289292
http_host = attributes.get(SpanAttributes.HTTP_HOST, "")
290293
if http_host:
291294
url = "{}://{}{}".format(

0 commit comments

Comments
 (0)