Skip to content

Commit

Permalink
opentelemetry-sdk-extension-aws: make ec2 resource detector silent wh…
Browse files Browse the repository at this point in the history
…en loaded outside AWS (open-telemetry#3120)

* opentelemetry-sdk-extension-aws: make ec2 resource detector silent when loaded outside AWS

Assume that if we fail to get the token quickly we are not on AWS.
  • Loading branch information
xrmx committed Jan 24, 2025
1 parent 409efa0 commit 1b8ef6f
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 7 deletions.
2 changes: 2 additions & 0 deletions sdk-extension/opentelemetry-sdk-extension-aws/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Make ec2 resource detector silent when loaded outside AWS
([#3120](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3120))
- Make ecs and beanstalk resource detector silent when loaded outside AWS
([#3076](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3076))
- Make EKS resource detector don't warn when not running in EKS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import json
import logging
from urllib.error import URLError
from urllib.request import Request, urlopen

from opentelemetry.sdk.resources import Resource, ResourceDetector
Expand All @@ -27,39 +28,47 @@

_AWS_METADATA_TOKEN_HEADER = "X-aws-ec2-metadata-token"
_GET_METHOD = "GET"
_AWS_METADATA_HOST = "169.254.169.254"


def _aws_http_request(method, path, headers):
def _aws_http_request(method, path, headers, timeout=None):
if timeout is None:
timeout = 5
with urlopen(
Request(
"http://169.254.169.254" + path, headers=headers, method=method
"http://" + _AWS_METADATA_HOST + path,
headers=headers,
method=method,
),
timeout=5,
timeout=timeout,
) as response:
return response.read().decode("utf-8")


def _get_token():
def _get_token(timeout=None):
return _aws_http_request(
"PUT",
"/latest/api/token",
{"X-aws-ec2-metadata-token-ttl-seconds": "60"},
timeout,
)


def _get_identity(token):
def _get_identity(token, timeout=None):
return _aws_http_request(
_GET_METHOD,
"/latest/dynamic/instance-identity/document",
{_AWS_METADATA_TOKEN_HEADER: token},
timeout,
)


def _get_host(token):
def _get_host(token, timeout=None):
return _aws_http_request(
_GET_METHOD,
"/latest/meta-data/hostname",
{_AWS_METADATA_TOKEN_HEADER: token},
timeout,
)


Expand All @@ -72,7 +81,17 @@ class AwsEc2ResourceDetector(ResourceDetector):

def detect(self) -> "Resource":
try:
token = _get_token()
# If can't get a token quick assume we are not on ec2
try:
token = _get_token(timeout=1)
except URLError as exception:
logger.debug(
"%s failed to get token: %s",
self.__class__.__name__,
exception,
)
return Resource.get_empty()

identity_dict = json.loads(_get_identity(token))
hostname = _get_host(token)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import unittest
from collections import OrderedDict
from unittest.mock import patch
from urllib.error import URLError

from opentelemetry.sdk.extension.aws.resource.ec2 import ( # pylint: disable=no-name-in-module
AwsEc2ResourceDetector,
Expand Down Expand Up @@ -73,3 +74,22 @@ def test_simple_create(
self.assertDictEqual(
actual.attributes.copy(), OrderedDict(MockEc2ResourceAttributes)
)

@patch(
"opentelemetry.sdk.extension.aws.resource.ec2._get_token",
side_effect=URLError("Something went wrong"),
)
def test_empty_resource_if_token_returns_an_url_error(
self, mock_get_token
):
with self.assertLogs(
"opentelemetry.sdk.extension.aws.resource.ec2", level="DEBUG"
) as logger:
actual = AwsEc2ResourceDetector().detect()
self.assertEqual(
logger.output,
[
"DEBUG:opentelemetry.sdk.extension.aws.resource.ec2:AwsEc2ResourceDetector failed to get token: <urlopen error Something went wrong>"
],
)
self.assertDictEqual(actual.attributes.copy(), OrderedDict())

0 comments on commit 1b8ef6f

Please sign in to comment.