Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/process resource detector #3472

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fbddd63
implement a resource detector for process
bourbonkk Oct 10, 2023
d9f9598
remove process owner
bourbonkk Oct 10, 2023
837049d
modify lint
bourbonkk Oct 10, 2023
04b723a
modify test_resources
bourbonkk Oct 11, 2023
a1bd93d
modify lint
bourbonkk Oct 11, 2023
81a50c6
modify CHANGELOG.md
bourbonkk Oct 11, 2023
81e4805
Merge branch 'main' into feature/process-resource-detector
bourbonkk Oct 12, 2023
f2c96b0
Merge branch 'main' into feature/process-resource-detector
bourbonkk Oct 16, 2023
ac0cbce
Remove unnecessary comments
bourbonkk Oct 25, 2023
1c2abbf
Merge remote-tracking branch 'origin/feature/process-resource-detecto…
bourbonkk Oct 25, 2023
66af286
Merge branch 'main' into feature/process-resource-detector
lzchen Nov 6, 2023
ad22715
Merge branch 'main' into feature/process-resource-detector
lzchen Nov 7, 2023
cfd1c0f
add get parent pid
bourbonkk Nov 8, 2023
db3ce75
add get parent pid
bourbonkk Nov 8, 2023
a218703
add get parent pid
bourbonkk Nov 8, 2023
5e61f7e
add get parent pid
bourbonkk Nov 8, 2023
ccc9024
Merge branch 'main' into feature/process-resource-detector
bourbonkk Nov 17, 2023
139ca34
add get process username
bourbonkk Nov 22, 2023
c66df72
Merge remote-tracking branch 'origin/feature/process-resource-detecto…
bourbonkk Nov 22, 2023
1a67ee4
Merge branch 'main' into feature/process-resource-detector
bourbonkk Nov 22, 2023
e15bce0
Merge branch 'main' into feature/process-resource-detector
lzchen Nov 22, 2023
d7b1a45
Merge branch 'main' into feature/process-resource-detector
lzchen Nov 22, 2023
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#3251](https://github.com/open-telemetry/opentelemetry-python/pull/3251))
- Prometheus exporter support for auto instrumentation
([#3413](https://github.com/open-telemetry/opentelemetry-python/pull/3413))
- Implement Process Resource detector
([#3472](https://github.com/open-telemetry/opentelemetry-python/pull/3472))


## Version 1.20.0/0.41b0 (2023-09-04)

Expand Down
44 changes: 33 additions & 11 deletions opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import abc
import concurrent.futures
import logging
import os
import sys
import typing
from json import dumps
Expand All @@ -74,11 +75,15 @@
from opentelemetry.util._importlib_metadata import entry_points, version
from opentelemetry.util.types import AttributeValue

try:
import psutil
except ImportError:
psutil = None

LabelValue = AttributeValue
Attributes = typing.Dict[str, LabelValue]
logger = logging.getLogger(__name__)


CLOUD_PROVIDER = ResourceAttributes.CLOUD_PROVIDER
CLOUD_ACCOUNT_ID = ResourceAttributes.CLOUD_ACCOUNT_ID
CLOUD_REGION = ResourceAttributes.CLOUD_REGION
Expand Down Expand Up @@ -117,6 +122,7 @@
OS_TYPE = ResourceAttributes.OS_TYPE
OS_DESCRIPTION = ResourceAttributes.OS_DESCRIPTION
PROCESS_PID = ResourceAttributes.PROCESS_PID
PROCESS_PARENT_PID = ResourceAttributes.PROCESS_PARENT_PID
PROCESS_EXECUTABLE_NAME = ResourceAttributes.PROCESS_EXECUTABLE_NAME
PROCESS_EXECUTABLE_PATH = ResourceAttributes.PROCESS_EXECUTABLE_PATH
PROCESS_COMMAND = ResourceAttributes.PROCESS_COMMAND
Expand All @@ -135,7 +141,6 @@
TELEMETRY_AUTO_VERSION = ResourceAttributes.TELEMETRY_AUTO_VERSION
TELEMETRY_SDK_LANGUAGE = ResourceAttributes.TELEMETRY_SDK_LANGUAGE


_OPENTELEMETRY_SDK_VERSION = version("opentelemetry-sdk")


Expand Down Expand Up @@ -180,7 +185,6 @@ def create(
otel_experimental_resource_detectors.append("otel")

for resource_detector in otel_experimental_resource_detectors:

resource_detectors.append(
next(
iter(
Expand Down Expand Up @@ -337,14 +341,32 @@ def detect(self) -> "Resource":
else sys.version_info,
)
)

return Resource(
{
PROCESS_RUNTIME_DESCRIPTION: sys.version,
PROCESS_RUNTIME_NAME: sys.implementation.name,
PROCESS_RUNTIME_VERSION: _runtime_version,
}
)
_process_pid = os.getpid()
_process_executable_name = sys.executable
bourbonkk marked this conversation as resolved.
Show resolved Hide resolved
_process_executable_path = os.path.dirname(_process_executable_name)
bourbonkk marked this conversation as resolved.
Show resolved Hide resolved
_process_command = sys.argv[0]
_process_command_line = " ".join(sys.argv)
_process_command_args = sys.argv[1:]
resource_info = {
PROCESS_RUNTIME_DESCRIPTION: sys.version,
PROCESS_RUNTIME_NAME: sys.implementation.name,
PROCESS_RUNTIME_VERSION: _runtime_version,
PROCESS_PID: _process_pid,
PROCESS_EXECUTABLE_NAME: _process_executable_name,
PROCESS_EXECUTABLE_PATH: _process_executable_path,
PROCESS_COMMAND: _process_command,
PROCESS_COMMAND_LINE: _process_command_line,
PROCESS_COMMAND_ARGS: _process_command_args,
}
if hasattr(os, "getppid"):
# pypy3 does not have getppid()
resource_info[PROCESS_PARENT_PID] = os.getppid()

if psutil is not None:
process = psutil.Process()
resource_info[PROCESS_OWNER] = process.username()

return Resource(resource_info)


def get_aggregated_resources(
Expand Down
61 changes: 56 additions & 5 deletions opentelemetry-sdk/tests/resources/test_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# pylint: disable=protected-access

import os
import sys
import unittest
import uuid
from logging import ERROR, WARNING
Expand All @@ -30,7 +29,14 @@
_OPENTELEMETRY_SDK_VERSION,
OTEL_RESOURCE_ATTRIBUTES,
OTEL_SERVICE_NAME,
PROCESS_COMMAND,
PROCESS_COMMAND_ARGS,
PROCESS_COMMAND_LINE,
PROCESS_EXECUTABLE_NAME,
PROCESS_EXECUTABLE_PATH,
PROCESS_OWNER,
PROCESS_PARENT_PID,
PROCESS_PID,
PROCESS_RUNTIME_DESCRIPTION,
PROCESS_RUNTIME_NAME,
PROCESS_RUNTIME_VERSION,
Expand All @@ -45,6 +51,11 @@
get_aggregated_resources,
)

try:
import psutil
except ImportError:
psutil = None


class TestResources(unittest.TestCase):
def setUp(self) -> None:
Expand Down Expand Up @@ -524,6 +535,10 @@ def test_service_name_env_precedence(self):
Resource({"service.name": "from-service-name"}),
)

@patch(
"sys.argv",
["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"],
bourbonkk marked this conversation as resolved.
Show resolved Hide resolved
)
def test_process_detector(self):
initial_resource = Resource({"foo": "bar"})
aggregated_resource = get_aggregated_resources(
Expand All @@ -543,8 +558,42 @@ def test_process_detector(self):
aggregated_resource.attributes.keys(),
)

def test_resource_detector_entry_points_default(self):
self.assertEqual(
aggregated_resource.attributes[PROCESS_PID], os.getpid()
)
if hasattr(os, "getppid"):
self.assertEqual(
aggregated_resource.attributes[PROCESS_PARENT_PID],
os.getppid(),
)

if psutil is not None:
self.assertEqual(
aggregated_resource.attributes[PROCESS_OWNER],
psutil.Process().username(),
)

self.assertEqual(
aggregated_resource.attributes[PROCESS_EXECUTABLE_NAME],
sys.executable,
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_EXECUTABLE_PATH],
os.path.dirname(sys.executable),
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND], sys.argv[0]
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND_LINE],
" ".join(sys.argv),
)
self.assertEqual(
aggregated_resource.attributes[PROCESS_COMMAND_ARGS],
tuple(sys.argv[1:]),
)

def test_resource_detector_entry_points_default(self):
resource = Resource({}).create()

self.assertEqual(
Expand Down Expand Up @@ -644,7 +693,9 @@ def test_resource_detector_entry_points_otel(self):
resource.attributes["telemetry.sdk.name"], "opentelemetry"
)
self.assertEqual(
resource.attributes["service.name"], "unknown_service"
resource.attributes["service.name"],
"unknown_service:"
+ resource.attributes["process.executable.name"],
)
self.assertEqual(resource.attributes["a"], "b")
self.assertEqual(resource.attributes["c"], "d")
Expand Down
Loading