Skip to content

Commit

Permalink
OpenTelemetry Exporter use Resources API to retrieve cloud role props (
Browse files Browse the repository at this point in the history
…#15816)

* OpenTelemetry Exporter use Resources API to retrieve cloud role properties

* lint

* Adding changelog
  • Loading branch information
hectorhdzg authored Dec 17, 2020
1 parent 7368ddf commit f8e4255
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
- Rename Azure Trace exporter class, only allow connection string configuration
([#15349](https://github.com/Azure/azure-sdk-for-python/pull/15349))

- OpenTelemetry Exporter use Resources API to retrieve cloud role props
([#15816](https://github.com/Azure/azure-sdk-for-python/pull/15816))

- Change span to envelope conversion to adhere to common schema and other languages
([#15344](https://github.com/Azure/azure-sdk-for-python/pull/15344))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import locale
import os
import platform
import sys
import threading
import time

Expand All @@ -18,8 +16,6 @@
).version

azure_monitor_context = {
"ai.cloud.role": os.path.basename(sys.argv[0]) or "Python Application",
"ai.cloud.roleInstance": platform.node(),
"ai.device.id": platform.node(),
"ai.device.locale": locale.getdefaultlocale()[0],
"ai.device.osVersion": platform.version(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ def convert_span_to_envelope(span: Span) -> TelemetryItem:
tags=dict(_utils.azure_monitor_context),
time=ns_to_iso_str(span.start_time),
)
if span.resource and span.resource.attributes:
# TODO: Get Resource attributes from OpenTelemetry SDK when available
service_name = span.resource.attributes.get("service.name")
service_namespace = span.resource.attributes.get("service.namespace")
service_instance_id = span.resource.attributes.get("service.instance.id")
if service_name:
if service_namespace:
envelope.tags["ai.cloud.role"] = service_namespace + \
"." + service_name
else:
envelope.tags["ai.cloud.role"] = service_name
if service_instance_id:
envelope.tags["ai.cloud.roleInstance"] = service_instance_id

envelope.tags["ai.operation.id"] = "{:032x}".format(span.context.trace_id)
parent = span.parent
if parent:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from unittest import mock

# pylint: disable=import-error
from opentelemetry.sdk import trace
from opentelemetry.sdk import trace, resources
from opentelemetry.sdk.trace.export import SpanExportResult
from opentelemetry.trace import Link, SpanContext, SpanKind
from opentelemetry.trace.status import Status, StatusCode
Expand Down Expand Up @@ -143,9 +143,51 @@ def test_export_not_retryable(self):

def test_span_to_envelope_none(self):
exporter = self._exporter
self.assertIsNone(exporter._span_to_envelope(None))
test_span = trace._Span(
name="test",
context=SpanContext(
trace_id=36873507687745823477771305566750195431,
span_id=12030755672171557338,
is_remote=False,
),
)
test_span.start()
test_span.end()

def test_span_to_envelope_tags(self):
exporter = self._exporter
test_span = trace._Span(
name="test",
context=SpanContext(
trace_id=36873507687745823477771305566750195431,
span_id=12030755672171557338,
is_remote=False,
),
)
test_span.start()
test_span.end()
envelope = exporter._span_to_envelope(test_span)

self.assertIsNotNone(envelope.tags)
self.assertIsNone(envelope.tags.get("ai.cloud.role"))
self.assertIsNone(envelope.tags.get("ai.cloud.roleInstance"))
self.assertIsNotNone(envelope.tags.get("ai.device.id"))
self.assertIsNotNone(envelope.tags.get("ai.device.locale"))
self.assertIsNotNone(envelope.tags.get("ai.device.osVersion"))
self.assertIsNotNone(envelope.tags.get("ai.device.type"))
self.assertIsNotNone(envelope.tags.get("ai.internal.sdkVersion"))

test_span.resource = resources.Resource(
{"service.name": "testServiceName",
"service.namespace": "testServiceNamespace",
"service.instance.id": "testServiceInstanceId"})
envelope = exporter._span_to_envelope(test_span)
self.assertEqual(envelope.tags.get("ai.cloud.role"), "testServiceNamespace.testServiceName")
self.assertEqual(envelope.tags.get(
"ai.cloud.roleInstance"), "testServiceInstanceId")

# pylint: disable=too-many-statements

def test_span_to_envelope(self):
exporter = AzureMonitorTraceExporter(
connection_string="InstrumentationKey=12345678-1234-5678-abcd-12345678abcd",
Expand Down

0 comments on commit f8e4255

Please sign in to comment.