We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
EC2 resource detector hangs for a long time outside of an EC2 instance
**Describe your environment** Describe any aspect of your environment relevant to the problem, including your Python version, [platform](https://docs.python.org/3/library/platform.html), version numbers of installed dependencies, information about your cloud hosting provider, etc. If you're reporting a problem with a specific version of a library in this repo, please check whether the problem has been fixed on main.

The environment I initially saw this in was a container running in Docker compose on an AWS EC2 instance but I've been able to reproduce it on my laptop as well. I think it will show up in anything not directly running in AWS.

**Steps to reproduce**
Describe exactly how to reproduce the error. Include a code sample if applicable.

The following code reproduced the issue on my laptop:

```python
from opentelemetry.sdk.extension.aws.resource.ec2 import AwsEc2ResourceDetector
from opentelemetry.sdk.resources import get_aggregated_resources

resource = get_aggregated_resources(
    detectors=[AwsEc2ResourceDetector()]
)
```

**What is the expected behavior?**

It should complete quickly (this is the behavior I see running on an EC2 instance).

**What is the actual behavior?**

What did you see instead?

On my laptop, it will hand ~indefinitely.

Note: one solution is just to remove the resource detector but we'd like to be able to include it and just have it fail silently, which is the behavior we've seen in other resource detectors.

**Additional context**

I think the problem is here: https://github.com/open-telemetry/opentelemetry-python-contrib/blob/80969a06da77d1e616124de178d12a1ebe3ffe7f/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py#L37

It looks like the request is using a 1000 _second_ timeout which I suspect is intended to be a 1000 _millisecond_ timeout. At least with the server program I've been working on that will block the startup of the program until the request completes.

You can verify by running:

```
curl http://169.254.169.254/latest/api/token
```

Which is one of the requests that the resource detector makes -- it should hang indefinitely as well.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py`
Content:
```
1 # Copyright The OpenTelemetry Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import json
16 import logging
17 from urllib.request import Request, urlopen
18 
19 from opentelemetry.sdk.resources import Resource, ResourceDetector
20 from opentelemetry.semconv.resource import (
21     CloudPlatformValues,
22     CloudProviderValues,
23     ResourceAttributes,
24 )
25 
26 logger = logging.getLogger(__name__)
27 
28 _AWS_METADATA_TOKEN_HEADER = "X-aws-ec2-metadata-token"
29 _GET_METHOD = "GET"
30 
31 
32 def _aws_http_request(method, path, headers):
33     with urlopen(
34         Request(
35             "http://169.254.169.254" + path, headers=headers, method=method
36         ),
37         timeout=1000,
38     ) as response:
39         return response.read().decode("utf-8")
40 
41 
42 def _get_token():
43     return _aws_http_request(
44         "PUT",
45         "/latest/api/token",
46         {"X-aws-ec2-metadata-token-ttl-seconds": "60"},
47     )
48 
49 
50 def _get_identity(token):
51     return _aws_http_request(
52         _GET_METHOD,
53         "/latest/dynamic/instance-identity/document",
54         {_AWS_METADATA_TOKEN_HEADER: token},
55     )
56 
57 
58 def _get_host(token):
59     return _aws_http_request(
60         _GET_METHOD,
61         "/latest/meta-data/hostname",
62         {_AWS_METADATA_TOKEN_HEADER: token},
63     )
64 
65 
66 class AwsEc2ResourceDetector(ResourceDetector):
67     """Detects attribute values only available when the app is running on AWS
68     Elastic Compute Cloud (EC2) and returns them in a Resource.
69 
70     Uses a special URI to get instance meta-data. See more: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
71     """
72 
73     def detect(self) -> "Resource":
74         try:
75             token = _get_token()
76             identity_dict = json.loads(_get_identity(token))
77             hostname = _get_host(token)
78 
79             return Resource(
80                 {
81                     ResourceAttributes.CLOUD_PROVIDER: CloudProviderValues.AWS.value,
82                     ResourceAttributes.CLOUD_PLATFORM: CloudPlatformValues.AWS_EC2.value,
83                     ResourceAttributes.CLOUD_ACCOUNT_ID: identity_dict[
84                         "accountId"
85                     ],
86                     ResourceAttributes.CLOUD_REGION: identity_dict["region"],
87                     ResourceAttributes.CLOUD_AVAILABILITY_ZONE: identity_dict[
88                         "availabilityZone"
89                     ],
90                     ResourceAttributes.HOST_ID: identity_dict["instanceId"],
91                     ResourceAttributes.HOST_TYPE: identity_dict[
92                         "instanceType"
93                     ],
94                     ResourceAttributes.HOST_NAME: hostname,
95                 }
96             )
97         # pylint: disable=broad-except
98         except Exception as exception:
99             if self.raise_on_error:
100                 raise exception
101 
102             logger.warning("%s failed: %s", self.__class__.__name__, exception)
103             return Resource.get_empty()
104
```

Path: `sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py`
Content:
```
1 # Copyright The OpenTelemetry Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import json
16 import logging
17 import ssl
18 from urllib.request import Request, urlopen
19 
20 from opentelemetry.sdk.resources import Resource, ResourceDetector
21 from opentelemetry.semconv.resource import (
22     CloudPlatformValues,
23     CloudProviderValues,
24     ResourceAttributes,
25 )
26 
27 logger = logging.getLogger(__name__)
28 
29 _CONTAINER_ID_LENGTH = 64
30 _GET_METHOD = "GET"
31 
32 
33 def _aws_http_request(method, path, cred_value):
34     with urlopen(
35         Request(
36             "https://kubernetes.default.svc" + path,
37             headers={"Authorization": cred_value},
38             method=method,
39         ),
40         timeout=2000,
41         context=ssl.create_default_context(
42             cafile="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
43         ),
44     ) as response:
45         return response.read().decode("utf-8")
46 
47 
48 def _get_k8s_cred_value():
49     try:
50         with open(
51             "/var/run/secrets/kubernetes.io/serviceaccount/token",
52             encoding="utf8",
53         ) as token_file:
54             return "Bearer " + token_file.read()
55     # pylint: disable=broad-except
56     except Exception as exception:
57         logger.error("Failed to get k8s token: %s", exception)
58         raise exception
59 
60 
61 def _is_eks(cred_value):
62     return _aws_http_request(
63         _GET_METHOD,
64         "/api/v1/namespaces/kube-system/configmaps/aws-auth",
65         cred_value,
66     )
67 
68 
69 def _get_cluster_info(cred_value):
70     return _aws_http_request(
71         _GET_METHOD,
72         "/api/v1/namespaces/amazon-cloudwatch/configmaps/cluster-info",
73         cred_value,
74     )
75 
76 
77 def _get_cluster_name(cred_value) -> str:
78     cluster_info = json.loads(_get_cluster_info(cred_value))
79     cluster_name = ""
80     try:
81         cluster_name = cluster_info["data"]["cluster.name"]
82     except KeyError as exception:
83         logger.warning("Cannot get cluster name on EKS: %s", exception)
84 
85     return cluster_name
86 
87 
88 def _get_container_id():
89     container_id = ""
90     with open("/proc/self/cgroup", encoding="utf8") as container_info_file:
91         for raw_line in container_info_file.readlines():
92             line = raw_line.strip()
93             # Subsequent IDs should be the same, exit if found one
94             if len(line) > _CONTAINER_ID_LENGTH:
95                 container_id = line[-_CONTAINER_ID_LENGTH:]
96                 break
97     return container_id
98 
99 
100 class AwsEksResourceDetector(ResourceDetector):
101     """Detects attribute values only available when the app is running on AWS
102     Elastic Kubernetes Service (EKS) and returns them in a Resource.
103 
104     NOTE: Uses a `cluster-info` configmap in the `amazon-cloudwatch` namespace. See more here: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-quickstart.html#Container-Insights-setup-EKS-quickstart-Fluentd
105     """
106 
107     def detect(self) -> "Resource":
108         try:
109             cred_value = _get_k8s_cred_value()
110 
111             if not _is_eks(cred_value):
112                 raise RuntimeError(
113                     "Could not confirm process is running on EKS."
114                 )
115 
116             cluster_name = _get_cluster_name(cred_value)
117             container_id = _get_container_id()
118 
119             if not container_id and not cluster_name:
120                 raise RuntimeError(
121                     "Neither cluster name nor container ID found on EKS process."
122                 )
123 
124             return Resource(
125                 {
126                     ResourceAttributes.CLOUD_PROVIDER: CloudProviderValues.AWS.value,
127                     ResourceAttributes.CLOUD_PLATFORM: CloudPlatformValues.AWS_EKS.value,
128                     ResourceAttributes.K8S_CLUSTER_NAME: cluster_name,
129                     ResourceAttributes.CONTAINER_ID: container_id,
130                 }
131             )
132         # pylint: disable=broad-except
133         except Exception as exception:
134             if self.raise_on_error:
135                 raise exception
136 
137             logger.warning("%s failed: %s", self.__class__.__name__, exception)
138             return Resource.get_empty()
139
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py
--- a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py
+++ b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py
@@ -34,7 +34,7 @@
         Request(
             "http://169.254.169.254" + path, headers=headers, method=method
         ),
-        timeout=1000,
+        timeout=5,
     ) as response:
         return response.read().decode("utf-8")
 
diff --git a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py
--- a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py
+++ b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py
@@ -37,7 +37,7 @@
             headers={"Authorization": cred_value},
             method=method,
         ),
-        timeout=2000,
+        timeout=5,
         context=ssl.create_default_context(
             cafile="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
         ),

{"golden_diff": "diff --git a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py\n--- a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py\n+++ b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py\n@@ -34,7 +34,7 @@\n         Request(\n             \"http://169.254.169.254\" + path, headers=headers, method=method\n         ),\n-        timeout=1000,\n+        timeout=5,\n     ) as response:\n         return response.read().decode(\"utf-8\")\n \ndiff --git a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py\n--- a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py\n+++ b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py\n@@ -37,7 +37,7 @@\n             headers={\"Authorization\": cred_value},\n             method=method,\n         ),\n-        timeout=2000,\n+        timeout=5,\n         context=ssl.create_default_context(\n             cafile=\"/var/run/secrets/kubernetes.io/serviceaccount/ca.crt\"\n         ),\n", "issue": "EC2 resource detector hangs for a long time outside of an EC2 instance\n**Describe your environment** Describe any aspect of your environment relevant to the problem, including your Python version, [platform](https://docs.python.org/3/library/platform.html), version numbers of installed dependencies, information about your cloud hosting provider, etc. If you're reporting a problem with a specific version of a library in this repo, please check whether the problem has been fixed on main.\r\n\r\nThe environment I initially saw this in was a container running in Docker compose on an AWS EC2 instance but I've been able to reproduce it on my laptop as well. I think it will show up in anything not directly running in AWS.\r\n\r\n**Steps to reproduce**\r\nDescribe exactly how to reproduce the error. Include a code sample if applicable.\r\n\r\nThe following code reproduced the issue on my laptop:\r\n\r\n```python\r\nfrom opentelemetry.sdk.extension.aws.resource.ec2 import AwsEc2ResourceDetector\r\nfrom opentelemetry.sdk.resources import get_aggregated_resources\r\n\r\nresource = get_aggregated_resources(\r\n    detectors=[AwsEc2ResourceDetector()]\r\n)\r\n```\r\n\r\n**What is the expected behavior?**\r\n\r\nIt should complete quickly (this is the behavior I see running on an EC2 instance).\r\n\r\n**What is the actual behavior?**\r\n\r\nWhat did you see instead?\r\n\r\nOn my laptop, it will hand ~indefinitely.\r\n\r\nNote: one solution is just to remove the resource detector but we'd like to be able to include it and just have it fail silently, which is the behavior we've seen in other resource detectors.\r\n\r\n**Additional context**\r\n\r\nI think the problem is here: https://github.com/open-telemetry/opentelemetry-python-contrib/blob/80969a06da77d1e616124de178d12a1ebe3ffe7f/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py#L37\r\n\r\nIt looks like the request is using a 1000 _second_ timeout which I suspect is intended to be a 1000 _millisecond_ timeout. At least with the server program I've been working on that will block the startup of the program until the request completes.\r\n\r\nYou can verify by running:\r\n\r\n```\r\ncurl http://169.254.169.254/latest/api/token\r\n```\r\n\r\nWhich is one of the requests that the resource detector makes -- it should hang indefinitely as well.\r\n\n", "before_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport json\nimport logging\nfrom urllib.request import Request, urlopen\n\nfrom opentelemetry.sdk.resources import Resource, ResourceDetector\nfrom opentelemetry.semconv.resource import (\n    CloudPlatformValues,\n    CloudProviderValues,\n    ResourceAttributes,\n)\n\nlogger = logging.getLogger(__name__)\n\n_AWS_METADATA_TOKEN_HEADER = \"X-aws-ec2-metadata-token\"\n_GET_METHOD = \"GET\"\n\n\ndef _aws_http_request(method, path, headers):\n    with urlopen(\n        Request(\n            \"http://169.254.169.254\" + path, headers=headers, method=method\n        ),\n        timeout=1000,\n    ) as response:\n        return response.read().decode(\"utf-8\")\n\n\ndef _get_token():\n    return _aws_http_request(\n        \"PUT\",\n        \"/latest/api/token\",\n        {\"X-aws-ec2-metadata-token-ttl-seconds\": \"60\"},\n    )\n\n\ndef _get_identity(token):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/latest/dynamic/instance-identity/document\",\n        {_AWS_METADATA_TOKEN_HEADER: token},\n    )\n\n\ndef _get_host(token):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/latest/meta-data/hostname\",\n        {_AWS_METADATA_TOKEN_HEADER: token},\n    )\n\n\nclass AwsEc2ResourceDetector(ResourceDetector):\n    \"\"\"Detects attribute values only available when the app is running on AWS\n    Elastic Compute Cloud (EC2) and returns them in a Resource.\n\n    Uses a special URI to get instance meta-data. See more: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html\n    \"\"\"\n\n    def detect(self) -> \"Resource\":\n        try:\n            token = _get_token()\n            identity_dict = json.loads(_get_identity(token))\n            hostname = _get_host(token)\n\n            return Resource(\n                {\n                    ResourceAttributes.CLOUD_PROVIDER: CloudProviderValues.AWS.value,\n                    ResourceAttributes.CLOUD_PLATFORM: CloudPlatformValues.AWS_EC2.value,\n                    ResourceAttributes.CLOUD_ACCOUNT_ID: identity_dict[\n                        \"accountId\"\n                    ],\n                    ResourceAttributes.CLOUD_REGION: identity_dict[\"region\"],\n                    ResourceAttributes.CLOUD_AVAILABILITY_ZONE: identity_dict[\n                        \"availabilityZone\"\n                    ],\n                    ResourceAttributes.HOST_ID: identity_dict[\"instanceId\"],\n                    ResourceAttributes.HOST_TYPE: identity_dict[\n                        \"instanceType\"\n                    ],\n                    ResourceAttributes.HOST_NAME: hostname,\n                }\n            )\n        # pylint: disable=broad-except\n        except Exception as exception:\n            if self.raise_on_error:\n                raise exception\n\n            logger.warning(\"%s failed: %s\", self.__class__.__name__, exception)\n            return Resource.get_empty()\n", "path": "sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py"}, {"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport json\nimport logging\nimport ssl\nfrom urllib.request import Request, urlopen\n\nfrom opentelemetry.sdk.resources import Resource, ResourceDetector\nfrom opentelemetry.semconv.resource import (\n    CloudPlatformValues,\n    CloudProviderValues,\n    ResourceAttributes,\n)\n\nlogger = logging.getLogger(__name__)\n\n_CONTAINER_ID_LENGTH = 64\n_GET_METHOD = \"GET\"\n\n\ndef _aws_http_request(method, path, cred_value):\n    with urlopen(\n        Request(\n            \"https://kubernetes.default.svc\" + path,\n            headers={\"Authorization\": cred_value},\n            method=method,\n        ),\n        timeout=2000,\n        context=ssl.create_default_context(\n            cafile=\"/var/run/secrets/kubernetes.io/serviceaccount/ca.crt\"\n        ),\n    ) as response:\n        return response.read().decode(\"utf-8\")\n\n\ndef _get_k8s_cred_value():\n    try:\n        with open(\n            \"/var/run/secrets/kubernetes.io/serviceaccount/token\",\n            encoding=\"utf8\",\n        ) as token_file:\n            return \"Bearer \" + token_file.read()\n    # pylint: disable=broad-except\n    except Exception as exception:\n        logger.error(\"Failed to get k8s token: %s\", exception)\n        raise exception\n\n\ndef _is_eks(cred_value):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/api/v1/namespaces/kube-system/configmaps/aws-auth\",\n        cred_value,\n    )\n\n\ndef _get_cluster_info(cred_value):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/api/v1/namespaces/amazon-cloudwatch/configmaps/cluster-info\",\n        cred_value,\n    )\n\n\ndef _get_cluster_name(cred_value) -> str:\n    cluster_info = json.loads(_get_cluster_info(cred_value))\n    cluster_name = \"\"\n    try:\n        cluster_name = cluster_info[\"data\"][\"cluster.name\"]\n    except KeyError as exception:\n        logger.warning(\"Cannot get cluster name on EKS: %s\", exception)\n\n    return cluster_name\n\n\ndef _get_container_id():\n    container_id = \"\"\n    with open(\"/proc/self/cgroup\", encoding=\"utf8\") as container_info_file:\n        for raw_line in container_info_file.readlines():\n            line = raw_line.strip()\n            # Subsequent IDs should be the same, exit if found one\n            if len(line) > _CONTAINER_ID_LENGTH:\n                container_id = line[-_CONTAINER_ID_LENGTH:]\n                break\n    return container_id\n\n\nclass AwsEksResourceDetector(ResourceDetector):\n    \"\"\"Detects attribute values only available when the app is running on AWS\n    Elastic Kubernetes Service (EKS) and returns them in a Resource.\n\n    NOTE: Uses a `cluster-info` configmap in the `amazon-cloudwatch` namespace. See more here: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-quickstart.html#Container-Insights-setup-EKS-quickstart-Fluentd\n    \"\"\"\n\n    def detect(self) -> \"Resource\":\n        try:\n            cred_value = _get_k8s_cred_value()\n\n            if not _is_eks(cred_value):\n                raise RuntimeError(\n                    \"Could not confirm process is running on EKS.\"\n                )\n\n            cluster_name = _get_cluster_name(cred_value)\n            container_id = _get_container_id()\n\n            if not container_id and not cluster_name:\n                raise RuntimeError(\n                    \"Neither cluster name nor container ID found on EKS process.\"\n                )\n\n            return Resource(\n                {\n                    ResourceAttributes.CLOUD_PROVIDER: CloudProviderValues.AWS.value,\n                    ResourceAttributes.CLOUD_PLATFORM: CloudPlatformValues.AWS_EKS.value,\n                    ResourceAttributes.K8S_CLUSTER_NAME: cluster_name,\n                    ResourceAttributes.CONTAINER_ID: container_id,\n                }\n            )\n        # pylint: disable=broad-except\n        except Exception as exception:\n            if self.raise_on_error:\n                raise exception\n\n            logger.warning(\"%s failed: %s\", self.__class__.__name__, exception)\n            return Resource.get_empty()\n", "path": "sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py"}], "after_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport json\nimport logging\nfrom urllib.request import Request, urlopen\n\nfrom opentelemetry.sdk.resources import Resource, ResourceDetector\nfrom opentelemetry.semconv.resource import (\n    CloudPlatformValues,\n    CloudProviderValues,\n    ResourceAttributes,\n)\n\nlogger = logging.getLogger(__name__)\n\n_AWS_METADATA_TOKEN_HEADER = \"X-aws-ec2-metadata-token\"\n_GET_METHOD = \"GET\"\n\n\ndef _aws_http_request(method, path, headers):\n    with urlopen(\n        Request(\n            \"http://169.254.169.254\" + path, headers=headers, method=method\n        ),\n        timeout=5,\n    ) as response:\n        return response.read().decode(\"utf-8\")\n\n\ndef _get_token():\n    return _aws_http_request(\n        \"PUT\",\n        \"/latest/api/token\",\n        {\"X-aws-ec2-metadata-token-ttl-seconds\": \"60\"},\n    )\n\n\ndef _get_identity(token):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/latest/dynamic/instance-identity/document\",\n        {_AWS_METADATA_TOKEN_HEADER: token},\n    )\n\n\ndef _get_host(token):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/latest/meta-data/hostname\",\n        {_AWS_METADATA_TOKEN_HEADER: token},\n    )\n\n\nclass AwsEc2ResourceDetector(ResourceDetector):\n    \"\"\"Detects attribute values only available when the app is running on AWS\n    Elastic Compute Cloud (EC2) and returns them in a Resource.\n\n    Uses a special URI to get instance meta-data. See more: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html\n    \"\"\"\n\n    def detect(self) -> \"Resource\":\n        try:\n            token = _get_token()\n            identity_dict = json.loads(_get_identity(token))\n            hostname = _get_host(token)\n\n            return Resource(\n                {\n                    ResourceAttributes.CLOUD_PROVIDER: CloudProviderValues.AWS.value,\n                    ResourceAttributes.CLOUD_PLATFORM: CloudPlatformValues.AWS_EC2.value,\n                    ResourceAttributes.CLOUD_ACCOUNT_ID: identity_dict[\n                        \"accountId\"\n                    ],\n                    ResourceAttributes.CLOUD_REGION: identity_dict[\"region\"],\n                    ResourceAttributes.CLOUD_AVAILABILITY_ZONE: identity_dict[\n                        \"availabilityZone\"\n                    ],\n                    ResourceAttributes.HOST_ID: identity_dict[\"instanceId\"],\n                    ResourceAttributes.HOST_TYPE: identity_dict[\n                        \"instanceType\"\n                    ],\n                    ResourceAttributes.HOST_NAME: hostname,\n                }\n            )\n        # pylint: disable=broad-except\n        except Exception as exception:\n            if self.raise_on_error:\n                raise exception\n\n            logger.warning(\"%s failed: %s\", self.__class__.__name__, exception)\n            return Resource.get_empty()\n", "path": "sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ec2.py"}, {"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport json\nimport logging\nimport ssl\nfrom urllib.request import Request, urlopen\n\nfrom opentelemetry.sdk.resources import Resource, ResourceDetector\nfrom opentelemetry.semconv.resource import (\n    CloudPlatformValues,\n    CloudProviderValues,\n    ResourceAttributes,\n)\n\nlogger = logging.getLogger(__name__)\n\n_CONTAINER_ID_LENGTH = 64\n_GET_METHOD = \"GET\"\n\n\ndef _aws_http_request(method, path, cred_value):\n    with urlopen(\n        Request(\n            \"https://kubernetes.default.svc\" + path,\n            headers={\"Authorization\": cred_value},\n            method=method,\n        ),\n        timeout=5,\n        context=ssl.create_default_context(\n            cafile=\"/var/run/secrets/kubernetes.io/serviceaccount/ca.crt\"\n        ),\n    ) as response:\n        return response.read().decode(\"utf-8\")\n\n\ndef _get_k8s_cred_value():\n    try:\n        with open(\n            \"/var/run/secrets/kubernetes.io/serviceaccount/token\",\n            encoding=\"utf8\",\n        ) as token_file:\n            return \"Bearer \" + token_file.read()\n    # pylint: disable=broad-except\n    except Exception as exception:\n        logger.error(\"Failed to get k8s token: %s\", exception)\n        raise exception\n\n\ndef _is_eks(cred_value):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/api/v1/namespaces/kube-system/configmaps/aws-auth\",\n        cred_value,\n    )\n\n\ndef _get_cluster_info(cred_value):\n    return _aws_http_request(\n        _GET_METHOD,\n        \"/api/v1/namespaces/amazon-cloudwatch/configmaps/cluster-info\",\n        cred_value,\n    )\n\n\ndef _get_cluster_name(cred_value) -> str:\n    cluster_info = json.loads(_get_cluster_info(cred_value))\n    cluster_name = \"\"\n    try:\n        cluster_name = cluster_info[\"data\"][\"cluster.name\"]\n    except KeyError as exception:\n        logger.warning(\"Cannot get cluster name on EKS: %s\", exception)\n\n    return cluster_name\n\n\ndef _get_container_id():\n    container_id = \"\"\n    with open(\"/proc/self/cgroup\", encoding=\"utf8\") as container_info_file:\n        for raw_line in container_info_file.readlines():\n            line = raw_line.strip()\n            # Subsequent IDs should be the same, exit if found one\n            if len(line) > _CONTAINER_ID_LENGTH:\n                container_id = line[-_CONTAINER_ID_LENGTH:]\n                break\n    return container_id\n\n\nclass AwsEksResourceDetector(ResourceDetector):\n    \"\"\"Detects attribute values only available when the app is running on AWS\n    Elastic Kubernetes Service (EKS) and returns them in a Resource.\n\n    NOTE: Uses a `cluster-info` configmap in the `amazon-cloudwatch` namespace. See more here: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-quickstart.html#Container-Insights-setup-EKS-quickstart-Fluentd\n    \"\"\"\n\n    def detect(self) -> \"Resource\":\n        try:\n            cred_value = _get_k8s_cred_value()\n\n            if not _is_eks(cred_value):\n                raise RuntimeError(\n                    \"Could not confirm process is running on EKS.\"\n                )\n\n            cluster_name = _get_cluster_name(cred_value)\n            container_id = _get_container_id()\n\n            if not container_id and not cluster_name:\n                raise RuntimeError(\n                    \"Neither cluster name nor container ID found on EKS process.\"\n                )\n\n            return Resource(\n                {\n                    ResourceAttributes.CLOUD_PROVIDER: CloudProviderValues.AWS.value,\n                    ResourceAttributes.CLOUD_PLATFORM: CloudPlatformValues.AWS_EKS.value,\n                    ResourceAttributes.K8S_CLUSTER_NAME: cluster_name,\n                    ResourceAttributes.CONTAINER_ID: container_id,\n                }\n            )\n        # pylint: disable=broad-except\n        except Exception as exception:\n            if self.raise_on_error:\n                raise exception\n\n            logger.warning(\"%s failed: %s\", self.__class__.__name__, exception)\n            return Resource.get_empty()\n", "path": "sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/eks.py"}]}