Skip to content

Commit a2914f3

Browse files
committed
fix(sdk): use sys.orig_argv for process.command to handle python -m invocations
ProcessResourceDetector populated process.command, process.command_line, and process.command_args from sys.argv. For applications launched via `python -m <module>`, the interpreter rewrites sys.argv[0] to the resolved module path, so the ``-m <module>`` portion of the original invocation is lost and the detector emits misleading telemetry. Python 3.10+ exposes sys.orig_argv which preserves the original arguments received by the interpreter. Since the SDK already requires Python >= 3.10, switch to sys.orig_argv (with a getattr fallback for safety). This also aligns with the OTel semantic conventions that reference /proc/<pid>/cmdline for these attributes. Fixes #4518 Signed-off-by: Ali <alliasgher123@gmail.com>
1 parent 7477b10 commit a2914f3

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020
([#4907](https://github.com/open-telemetry/opentelemetry-python/issues/4907))
2121
- Drop Python 3.9 support
2222
([#5076](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/5076))
23+
- `opentelemetry-sdk`: Fix `ProcessResourceDetector` to use `sys.orig_argv` when available so that `process.command`, `process.command_line`, and `process.command_args` reflect the original invocation for `python -m <module>` runs (where `sys.argv[0]` is rewritten to the module path)
24+
([#4518](https://github.com/open-telemetry/opentelemetry-python/issues/4518))
2325

2426

2527
## Version 1.41.0/0.62b0 (2026-04-09)

opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,16 @@ def detect(self) -> "Resource":
380380
_process_pid = os.getpid()
381381
_process_executable_name = sys.executable
382382
_process_executable_path = os.path.dirname(_process_executable_name)
383-
_process_command = sys.argv[0]
384-
_process_command_line = " ".join(sys.argv)
385-
_process_command_args = sys.argv
383+
# Prefer sys.orig_argv (Python 3.10+), which preserves the original
384+
# arguments received by the interpreter. This correctly captures
385+
# ``python -m <module>`` invocations where sys.argv is rewritten to
386+
# the resolved module path and the ``-m <module>`` information is
387+
# lost. sys.orig_argv also aligns with /proc/<pid>/cmdline, which
388+
# the OTel semantic conventions reference for these attributes.
389+
_process_argv = list(getattr(sys, "orig_argv", sys.argv))
390+
_process_command = _process_argv[0] if _process_argv else ""
391+
_process_command_line = " ".join(_process_argv)
392+
_process_command_args = _process_argv
386393
resource_info = {
387394
PROCESS_RUNTIME_DESCRIPTION: sys.version,
388395
PROCESS_RUNTIME_NAME: sys.implementation.name,

opentelemetry-sdk/tests/resources/test_resources.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,10 @@ def test_service_name_env_precedence(self):
564564
"sys.argv",
565565
["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"],
566566
)
567+
@patch(
568+
"sys.orig_argv",
569+
["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"],
570+
)
567571
def test_process_detector(self):
568572
initial_resource = Resource({"foo": "bar"})
569573
aggregated_resource = get_aggregated_resources(
@@ -618,6 +622,31 @@ def test_process_detector(self):
618622
tuple(sys.argv),
619623
)
620624

625+
@patch("sys.argv", ["/path/to/myapp/__main__.py"])
626+
@patch("sys.orig_argv", ["/usr/bin/python", "-m", "myapp"])
627+
def test_process_detector_uses_orig_argv_for_python_m(self):
628+
"""For ``python -m <module>`` invocations sys.argv[0] is rewritten to
629+
the resolved module path, losing the ``-m <module>`` information.
630+
sys.orig_argv preserves the original invocation and must be preferred.
631+
See https://github.com/open-telemetry/opentelemetry-python/issues/4518.
632+
"""
633+
aggregated_resource = get_aggregated_resources(
634+
[ProcessResourceDetector()], Resource({"foo": "bar"})
635+
)
636+
637+
self.assertEqual(
638+
aggregated_resource.attributes[PROCESS_COMMAND],
639+
"/usr/bin/python",
640+
)
641+
self.assertEqual(
642+
aggregated_resource.attributes[PROCESS_COMMAND_LINE],
643+
"/usr/bin/python -m myapp",
644+
)
645+
self.assertEqual(
646+
aggregated_resource.attributes[PROCESS_COMMAND_ARGS],
647+
("/usr/bin/python", "-m", "myapp"),
648+
)
649+
621650
def test_resource_detector_entry_points_default(self):
622651
resource = Resource({}).create()
623652

0 commit comments

Comments
 (0)