Skip to content

Commit f8e4255

Browse files
authored
OpenTelemetry Exporter use Resources API to retrieve cloud role props (Azure#15816)
* OpenTelemetry Exporter use Resources API to retrieve cloud role properties * lint * Adding changelog
1 parent 7368ddf commit f8e4255

File tree

4 files changed

+61
-6
lines changed

4 files changed

+61
-6
lines changed

sdk/monitor/microsoft-opentelemetry-exporter-azuremonitor/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
- Rename Azure Trace exporter class, only allow connection string configuration
77
([#15349](https://github.com/Azure/azure-sdk-for-python/pull/15349))
88

9+
- OpenTelemetry Exporter use Resources API to retrieve cloud role props
10+
([#15816](https://github.com/Azure/azure-sdk-for-python/pull/15816))
11+
912
- Change span to envelope conversion to adhere to common schema and other languages
1013
([#15344](https://github.com/Azure/azure-sdk-for-python/pull/15344))
1114

sdk/monitor/microsoft-opentelemetry-exporter-azuremonitor/microsoft/opentelemetry/exporter/azuremonitor/_utils.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
33
import locale
4-
import os
54
import platform
6-
import sys
75
import threading
86
import time
97

@@ -18,8 +16,6 @@
1816
).version
1917

2018
azure_monitor_context = {
21-
"ai.cloud.role": os.path.basename(sys.argv[0]) or "Python Application",
22-
"ai.cloud.roleInstance": platform.node(),
2319
"ai.device.id": platform.node(),
2420
"ai.device.locale": locale.getdefaultlocale()[0],
2521
"ai.device.osVersion": platform.version(),

sdk/monitor/microsoft-opentelemetry-exporter-azuremonitor/microsoft/opentelemetry/exporter/azuremonitor/export/trace/_exporter.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,20 @@ def convert_span_to_envelope(span: Span) -> TelemetryItem:
7777
tags=dict(_utils.azure_monitor_context),
7878
time=ns_to_iso_str(span.start_time),
7979
)
80+
if span.resource and span.resource.attributes:
81+
# TODO: Get Resource attributes from OpenTelemetry SDK when available
82+
service_name = span.resource.attributes.get("service.name")
83+
service_namespace = span.resource.attributes.get("service.namespace")
84+
service_instance_id = span.resource.attributes.get("service.instance.id")
85+
if service_name:
86+
if service_namespace:
87+
envelope.tags["ai.cloud.role"] = service_namespace + \
88+
"." + service_name
89+
else:
90+
envelope.tags["ai.cloud.role"] = service_name
91+
if service_instance_id:
92+
envelope.tags["ai.cloud.roleInstance"] = service_instance_id
93+
8094
envelope.tags["ai.operation.id"] = "{:032x}".format(span.context.trace_id)
8195
parent = span.parent
8296
if parent:

sdk/monitor/microsoft-opentelemetry-exporter-azuremonitor/tests/trace/test_trace.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from unittest import mock
1010

1111
# pylint: disable=import-error
12-
from opentelemetry.sdk import trace
12+
from opentelemetry.sdk import trace, resources
1313
from opentelemetry.sdk.trace.export import SpanExportResult
1414
from opentelemetry.trace import Link, SpanContext, SpanKind
1515
from opentelemetry.trace.status import Status, StatusCode
@@ -143,9 +143,51 @@ def test_export_not_retryable(self):
143143

144144
def test_span_to_envelope_none(self):
145145
exporter = self._exporter
146-
self.assertIsNone(exporter._span_to_envelope(None))
146+
test_span = trace._Span(
147+
name="test",
148+
context=SpanContext(
149+
trace_id=36873507687745823477771305566750195431,
150+
span_id=12030755672171557338,
151+
is_remote=False,
152+
),
153+
)
154+
test_span.start()
155+
test_span.end()
156+
157+
def test_span_to_envelope_tags(self):
158+
exporter = self._exporter
159+
test_span = trace._Span(
160+
name="test",
161+
context=SpanContext(
162+
trace_id=36873507687745823477771305566750195431,
163+
span_id=12030755672171557338,
164+
is_remote=False,
165+
),
166+
)
167+
test_span.start()
168+
test_span.end()
169+
envelope = exporter._span_to_envelope(test_span)
170+
171+
self.assertIsNotNone(envelope.tags)
172+
self.assertIsNone(envelope.tags.get("ai.cloud.role"))
173+
self.assertIsNone(envelope.tags.get("ai.cloud.roleInstance"))
174+
self.assertIsNotNone(envelope.tags.get("ai.device.id"))
175+
self.assertIsNotNone(envelope.tags.get("ai.device.locale"))
176+
self.assertIsNotNone(envelope.tags.get("ai.device.osVersion"))
177+
self.assertIsNotNone(envelope.tags.get("ai.device.type"))
178+
self.assertIsNotNone(envelope.tags.get("ai.internal.sdkVersion"))
179+
180+
test_span.resource = resources.Resource(
181+
{"service.name": "testServiceName",
182+
"service.namespace": "testServiceNamespace",
183+
"service.instance.id": "testServiceInstanceId"})
184+
envelope = exporter._span_to_envelope(test_span)
185+
self.assertEqual(envelope.tags.get("ai.cloud.role"), "testServiceNamespace.testServiceName")
186+
self.assertEqual(envelope.tags.get(
187+
"ai.cloud.roleInstance"), "testServiceInstanceId")
147188

148189
# pylint: disable=too-many-statements
190+
149191
def test_span_to_envelope(self):
150192
exporter = AzureMonitorTraceExporter(
151193
connection_string="InstrumentationKey=12345678-1234-5678-abcd-12345678abcd",

0 commit comments

Comments
 (0)