|
59 | 59 | import concurrent.futures |
60 | 60 | import logging |
61 | 61 | import os |
| 62 | +import platform |
62 | 63 | import sys |
63 | 64 | import typing |
64 | 65 | from json import dumps |
|
125 | 126 | KUBERNETES_JOB_NAME = ResourceAttributes.K8S_JOB_NAME |
126 | 127 | KUBERNETES_CRON_JOB_UID = ResourceAttributes.K8S_CRONJOB_UID |
127 | 128 | KUBERNETES_CRON_JOB_NAME = ResourceAttributes.K8S_CRONJOB_NAME |
128 | | -OS_TYPE = ResourceAttributes.OS_TYPE |
129 | 129 | OS_DESCRIPTION = ResourceAttributes.OS_DESCRIPTION |
| 130 | +OS_TYPE = ResourceAttributes.OS_TYPE |
| 131 | +OS_VERSION = ResourceAttributes.OS_VERSION |
130 | 132 | PROCESS_PID = ResourceAttributes.PROCESS_PID |
131 | 133 | PROCESS_PARENT_PID = ResourceAttributes.PROCESS_PARENT_PID |
132 | 134 | PROCESS_EXECUTABLE_NAME = ResourceAttributes.PROCESS_EXECUTABLE_NAME |
@@ -182,16 +184,17 @@ def create( |
182 | 184 | if not attributes: |
183 | 185 | attributes = {} |
184 | 186 |
|
185 | | - resource_detectors: List[ResourceDetector] = [] |
186 | | - |
187 | | - resource = _DEFAULT_RESOURCE |
188 | | - |
189 | | - otel_experimental_resource_detectors = environ.get( |
190 | | - OTEL_EXPERIMENTAL_RESOURCE_DETECTORS, "otel" |
191 | | - ).split(",") |
| 187 | + otel_experimental_resource_detectors = {"otel"}.union( |
| 188 | + { |
| 189 | + otel_experimental_resource_detector.strip() |
| 190 | + for otel_experimental_resource_detector in environ.get( |
| 191 | + OTEL_EXPERIMENTAL_RESOURCE_DETECTORS, "" |
| 192 | + ).split(",") |
| 193 | + if otel_experimental_resource_detector |
| 194 | + } |
| 195 | + ) |
192 | 196 |
|
193 | | - if "otel" not in otel_experimental_resource_detectors: |
194 | | - otel_experimental_resource_detectors.append("otel") |
| 197 | + resource_detectors: List[ResourceDetector] = [] |
195 | 198 |
|
196 | 199 | resource_detector: str |
197 | 200 | for resource_detector in otel_experimental_resource_detectors: |
@@ -384,6 +387,90 @@ def detect(self) -> "Resource": |
384 | 387 | return Resource(resource_info) # type: ignore |
385 | 388 |
|
386 | 389 |
|
| 390 | +class OsResourceDetector(ResourceDetector): |
| 391 | + """Detect os resources based on `Operating System conventions <https://opentelemetry.io/docs/specs/semconv/resource/os/>`_.""" |
| 392 | + |
| 393 | + def detect(self) -> "Resource": |
| 394 | + """Returns a resource with with ``os.type`` and ``os.version``. |
| 395 | +
|
| 396 | + Python's platform library |
| 397 | + ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 398 | +
|
| 399 | + To grab this information, Python's ``platform`` does not return what a |
| 400 | + user might expect it to. Below is a breakdown of its return values in |
| 401 | + different operating systems. |
| 402 | +
|
| 403 | + .. code-block:: python |
| 404 | + :caption: Linux |
| 405 | +
|
| 406 | + >>> platform.system() |
| 407 | + 'Linux' |
| 408 | + >>> platform.release() |
| 409 | + '6.5.0-35-generic' |
| 410 | + >>> platform.version() |
| 411 | + '#35~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue May 7 09:00:52 UTC 2' |
| 412 | +
|
| 413 | + .. code-block:: python |
| 414 | + :caption: MacOS |
| 415 | +
|
| 416 | + >>> platform.system() |
| 417 | + 'Darwin' |
| 418 | + >>> platform.release() |
| 419 | + '23.0.0' |
| 420 | + >>> platform.version() |
| 421 | + 'Darwin Kernel Version 23.0.0: Fri Sep 15 14:42:57 PDT 2023; root:xnu-10002.1.13~1/RELEASE_ARM64_T8112' |
| 422 | +
|
| 423 | + .. code-block:: python |
| 424 | + :caption: Windows |
| 425 | +
|
| 426 | + >>> platform.system() |
| 427 | + 'Windows' |
| 428 | + >>> platform.release() |
| 429 | + '2022Server' |
| 430 | + >>> platform.version() |
| 431 | + '10.0.20348' |
| 432 | +
|
| 433 | + .. code-block:: python |
| 434 | + :caption: FreeBSD |
| 435 | +
|
| 436 | + >>> platform.system() |
| 437 | + 'FreeBSD' |
| 438 | + >>> platform.release() |
| 439 | + '14.1-RELEASE' |
| 440 | + >>> platform.version() |
| 441 | + 'FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC' |
| 442 | +
|
| 443 | + .. code-block:: python |
| 444 | + :caption: Solaris |
| 445 | +
|
| 446 | + >>> platform.system() |
| 447 | + 'SunOS' |
| 448 | + >>> platform.release() |
| 449 | + '5.11' |
| 450 | + >>> platform.version() |
| 451 | + '11.4.0.15.0' |
| 452 | +
|
| 453 | + """ |
| 454 | + |
| 455 | + os_type = platform.system().lower() |
| 456 | + os_version = platform.release() |
| 457 | + |
| 458 | + # See docstring |
| 459 | + if os_type == "windows": |
| 460 | + os_version = platform.version() |
| 461 | + # Align SunOS with conventions |
| 462 | + elif os_type == "sunos": |
| 463 | + os_type = "solaris" |
| 464 | + os_version = platform.version() |
| 465 | + |
| 466 | + return Resource( |
| 467 | + { |
| 468 | + OS_TYPE: os_type, |
| 469 | + OS_VERSION: os_version, |
| 470 | + } |
| 471 | + ) |
| 472 | + |
| 473 | + |
387 | 474 | def get_aggregated_resources( |
388 | 475 | detectors: typing.List["ResourceDetector"], |
389 | 476 | initial_resource: typing.Optional[Resource] = None, |
|
0 commit comments