Skip to content

Commit

Permalink
Added try catch, logging, and dependency for azure resource detector
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydvoss committed Nov 27, 2023
1 parent 9afaf26 commit ed40983
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 25 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `opentelemetry-instrumentation-urllib`/`opentelemetry-instrumentation-urllib3` Fix metric descriptions to match semantic conventions
([#1959]((https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1959))
- `opentelemetry-resource-detector-azure` Added dependency for Cloud Resource ID attribute and clearer logging for Azure Resource Detectors
([#XXX](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/XXXX))

## Version 1.21.0/0.42b0 (2023-11-01)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ classifiers = [
]
dependencies = [
"opentelemetry-sdk ~= 1.19",
"opentelemetry-semantic-conventions ~= 0.42b0",
]

[project.optional-dependencies]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from logging import getLogger
from os import environ

from opentelemetry.sdk.resources import ResourceDetector, Resource
Expand All @@ -26,6 +27,7 @@
_WEBSITE_RESOURCE_GROUP = "WEBSITE_RESOURCE_GROUP"
_WEBSITE_SITE_NAME = "WEBSITE_SITE_NAME"
_WEBSITE_SLOT_NAME = "WEBSITE_SLOT_NAME"
_logger = getLogger(__name__)


_APP_SERVICE_ATTRIBUTE_ENV_VARS = {
Expand All @@ -39,20 +41,22 @@
class AzureAppServiceResourceDetector(ResourceDetector):
def detect(self) -> Resource:
attributes = {}
website_site_name = environ.get(_WEBSITE_SITE_NAME)
if website_site_name:
attributes[ResourceAttributes.SERVICE_NAME] = website_site_name
attributes[ResourceAttributes.CLOUD_PROVIDER] = CloudProviderValues.AZURE.value
attributes[ResourceAttributes.CLOUD_PLATFORM] = CloudPlatformValues.AZURE_APP_SERVICE.value

azure_resource_uri = _get_azure_resource_uri(website_site_name)
if azure_resource_uri:
attributes[ResourceAttributes.CLOUD_RESOURCE_ID] = azure_resource_uri
for (key, env_var) in _APP_SERVICE_ATTRIBUTE_ENV_VARS.items():
value = environ.get(env_var)
if value:
attributes[key] = value
try:
website_site_name = environ.get(_WEBSITE_SITE_NAME)
if website_site_name:
attributes[ResourceAttributes.SERVICE_NAME] = website_site_name
attributes[ResourceAttributes.CLOUD_PROVIDER] = CloudProviderValues.AZURE.value
attributes[ResourceAttributes.CLOUD_PLATFORM] = CloudPlatformValues.AZURE_APP_SERVICE.value

azure_resource_uri = _get_azure_resource_uri(website_site_name)
if azure_resource_uri:
attributes[ResourceAttributes.CLOUD_RESOURCE_ID] = azure_resource_uri
for (key, env_var) in _APP_SERVICE_ATTRIBUTE_ENV_VARS.items():
value = environ.get(env_var)
if value:
attributes[key] = value
except Exception as e:
_logger.info("Could not detect Azure App Service metadata: %s", e)
return Resource(attributes)

def _get_azure_resource_uri(website_site_name):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

from json import loads
from logging import getLogger
from os import environ
from urllib.request import Request, urlopen
from urllib.error import URLError

Expand All @@ -26,7 +25,6 @@
)


# TODO: Remove when cloud resource id is no longer missing in Resource Attributes
_AZURE_VM_METADATA_ENDPOINT = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json"
_AZURE_VM_SCALE_SET_NAME_ATTRIBUTE = "azure.vm.scaleset.name"
_AZURE_VM_SKU_ATTRIBUTE = "azure.vm.sku"
Expand All @@ -52,17 +50,20 @@ class AzureVMResourceDetector(ResourceDetector):
# pylint: disable=no-self-use
def detect(self) -> "Resource":
attributes = {}
metadata_json = (
_AzureVMMetadataServiceRequestor().get_azure_vm_metadata()
)
if not metadata_json:
return Resource(attributes)
for attribute_key in EXPECTED_AZURE_AMS_ATTRIBUTES:
attributes[
attribute_key
] = _AzureVMMetadataServiceRequestor().get_attribute_from_metadata(
metadata_json, attribute_key
try:
metadata_json = (
_AzureVMMetadataServiceRequestor().get_azure_vm_metadata()
)
if not metadata_json:
return Resource(attributes)
for attribute_key in EXPECTED_AZURE_AMS_ATTRIBUTES:
attributes[
attribute_key
] = _AzureVMMetadataServiceRequestor().get_attribute_from_metadata(
metadata_json, attribute_key
)
except Exception as e:
_logger.info("Could not detect Azure VM metadata: %s", e)
return Resource(attributes)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,11 @@ def test_on_app_service_no_owner(self):
def test_off_app_service(self):
resource = AzureAppServiceResourceDetector().detect()
self.assertEqual(resource.attributes, {})

@patch("opentelemetry.resource.detector.azure.app_service._logger")
@patch("opentelemetry.resource.detector.azure.app_service.environ")
def test_off_app_service(self, mock_environ, mock_logger):
mock_environ.get.side_effect = Exception("Test Exception")
resource = AzureAppServiceResourceDetector().detect()
mock_logger.info.assert_called_once()
self.assertEqual(resource.attributes, {})
15 changes: 15 additions & 0 deletions resource/opentelemetry-resource-detector-azure/tests/test_vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,11 @@
"zone": "1"
}
"""
INCOMPLETE_JSON = """
{
"vmId": "02aab8a4-74ef-476e-8182-f6d2ba4166a6"
}
"""
LINUX_ATTRIBUTES = {
"azure.vm.scaleset.name": "crpteste9vflji9",
"azure.vm.sku": "20_04-lts-gen2",
Expand Down Expand Up @@ -384,3 +389,13 @@ def test_windows(self, mock_urlopen):
self.assertEqual(
attributes[attribute_key], WINDOWS_ATTRIBUTES[attribute_key]
)

@patch("opentelemetry.resource.detector.azure.vm._logger")
@patch("opentelemetry.resource.detector.azure.vm.urlopen")
def test_incomplete_exception(self, mock_urlopen, mock_logger):
mock_open = Mock()
mock_urlopen.return_value = mock_open
mock_open.read.return_value = INCOMPLETE_JSON
attributes = AzureVMResourceDetector().detect().attributes
mock_logger.info.assert_called_once()
self.assertEqual(attributes, {})

0 comments on commit ed40983

Please sign in to comment.