Repository: open-telemetry/opentelemetry-python

Issue:
Python runtime version and other metadata not reported in the Resource Attributes
**Describe your environment**
* Python 3.8.10
* opentelemetry-sdk version 1.11.1

**Steps to reproduce**
Take the code from https://opentelemetry.io/docs/instrumentation/python/getting-started/, run it, search in the resource attributes for `process.runtime.version`

**What is the expected behavior?**
I expect the resource attributes to contain various `process.runtime.*` keys, including:
* [`process.runtime.name`](https://github.com/open-telemetry/opentelemetry-python/blob/8006a496791bef5a342e0510930050e59a6543f0/opentelemetry-semantic-conventions/src/opentelemetry/semconv/resource/__init__.py#L394)
* [`process.runtime.version`](https://github.com/open-telemetry/opentelemetry-python/blob/8006a496791bef5a342e0510930050e59a6543f0/opentelemetry-semantic-conventions/src/opentelemetry/semconv/resource/__init__.py#L399)

**What is the actual behavior?**
```json
{
    ...
    "resource": {
        "telemetry.sdk.language": "python",
        "telemetry.sdk.name": "opentelemetry",
        "telemetry.sdk.version": "1.11.1",
        "service.name": "unknown_service"
    }
}
```

**Additional context**
N/A



Discussion:
It turns out there is even a well-defined spec: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/process.md#python-runtimes

BRB :D

Resolving patch:
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
--- a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
@@ -59,6 +59,7 @@
 import concurrent.futures
 import logging
 import os
+import sys
 import typing
 from json import dumps
 
@@ -286,6 +287,28 @@ def detect(self) -> "Resource":
         return Resource(env_resource_map)
 
 
+class ProcessResourceDetector(ResourceDetector):
+    # pylint: disable=no-self-use
+    def detect(self) -> "Resource":
+        _runtime_version = ".".join(
+            map(
+                str,
+                sys.version_info[:3]
+                if sys.version_info.releaselevel == "final"
+                and not sys.version_info.serial
+                else sys.version_info,
+            )
+        )
+
+        return Resource(
+            {
+                PROCESS_RUNTIME_DESCRIPTION: sys.version,
+                PROCESS_RUNTIME_NAME: sys.implementation.name,
+                PROCESS_RUNTIME_VERSION: _runtime_version,
+            }
+        )
+
+
 def get_aggregated_resources(
     detectors: typing.List["ResourceDetector"],
     initial_resource: typing.Optional[Resource] = None,


Test patch:
diff --git a/opentelemetry-sdk/tests/resources/test_resources.py b/opentelemetry-sdk/tests/resources/test_resources.py
--- a/opentelemetry-sdk/tests/resources/test_resources.py
+++ b/opentelemetry-sdk/tests/resources/test_resources.py
@@ -516,3 +516,22 @@ def test_service_name_env_precedence(self):
             detector.detect(),
             resources.Resource({"service.name": "from-service-name"}),
         )
+
+    def test_process_detector(self):
+        initial_resource = resources.Resource({"foo": "bar"})
+        aggregated_resource = resources.get_aggregated_resources(
+            [resources.ProcessResourceDetector()], initial_resource
+        )
+
+        self.assertIn(
+            resources.PROCESS_RUNTIME_NAME,
+            aggregated_resource.attributes.keys(),
+        )
+        self.assertIn(
+            resources.PROCESS_RUNTIME_DESCRIPTION,
+            aggregated_resource.attributes.keys(),
+        )
+        self.assertIn(
+            resources.PROCESS_RUNTIME_VERSION,
+            aggregated_resource.attributes.keys(),
+        )