Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#5076](https://github.com/open-telemetry/opentelemetry-python/pull/5076))
- `opentelemetry-semantic-conventions`: use `X | Y` union annotation
([#5096](https://github.com/open-telemetry/opentelemetry-python/pull/5096))
- `opentelemetry-sdk`: Fix `ProcessResourceDetector` to use `sys.orig_argv` 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)
Comment thread
alliasgher marked this conversation as resolved.
([#5083](https://github.com/open-telemetry/opentelemetry-python/pull/5083))


## Version 1.41.0/0.62b0 (2026-04-09)
Expand Down
13 changes: 10 additions & 3 deletions opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,16 @@ def detect(self) -> "Resource":
_process_pid = os.getpid()
_process_executable_name = sys.executable
_process_executable_path = os.path.dirname(_process_executable_name)
_process_command = sys.argv[0]
_process_command_line = " ".join(sys.argv)
_process_command_args = sys.argv
# Use sys.orig_argv, which preserves the original arguments received
# by the interpreter. This correctly captures ``python -m <module>``
# invocations where sys.argv is rewritten to the resolved module path
# and the ``-m <module>`` information is lost. sys.orig_argv also
# aligns with /proc/<pid>/cmdline, which the OTel semantic
# conventions reference for these attributes.
_process_argv = list(sys.orig_argv)
_process_command = _process_argv[0] if _process_argv else ""
_process_command_line = " ".join(_process_argv)
_process_command_args = _process_argv
resource_info = {
PROCESS_RUNTIME_DESCRIPTION: sys.version,
PROCESS_RUNTIME_NAME: sys.implementation.name,
Expand Down
35 changes: 32 additions & 3 deletions opentelemetry-sdk/tests/resources/test_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,10 @@ def test_service_name_env_precedence(self):
"sys.argv",
["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"],
)
@patch(
"sys.orig_argv",
["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"],
)
def test_process_detector(self):
initial_resource = Resource({"foo": "bar"})
aggregated_resource = get_aggregated_resources(
Expand Down Expand Up @@ -607,15 +611,40 @@ def test_process_detector(self):
os.path.dirname(sys.executable),
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND], sys.argv[0]
aggregated_resource.attributes[PROCESS_COMMAND], sys.orig_argv[0]
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND_LINE],
" ".join(sys.orig_argv),
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND_ARGS],
tuple(sys.orig_argv),
)

@patch("sys.argv", ["/path/to/myapp/__main__.py"])
Comment thread
alliasgher marked this conversation as resolved.
Comment thread
alliasgher marked this conversation as resolved.
@patch("sys.orig_argv", ["/usr/bin/python", "-m", "myapp"])
def test_process_detector_uses_orig_argv_for_python_m(self):
"""For ``python -m <module>`` invocations sys.argv[0] is rewritten to
the resolved module path, losing the ``-m <module>`` information.
sys.orig_argv preserves the original invocation and must be preferred.
See https://github.com/open-telemetry/opentelemetry-python/issues/4518.
"""
aggregated_resource = get_aggregated_resources(
[ProcessResourceDetector()], Resource({"foo": "bar"})
)

self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND],
"/usr/bin/python",
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND_LINE],
" ".join(sys.argv),
"/usr/bin/python -m myapp",
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND_ARGS],
tuple(sys.argv),
("/usr/bin/python", "-m", "myapp"),
)

def test_resource_detector_entry_points_default(self):
Expand Down