Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2522ace
This PR is based on #3995.
asasvari Jul 13, 2024
c81cb51
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
asasvari Jul 14, 2024
d1d97f4
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
asasvari Jul 14, 2024
12702cf
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
asasvari Jul 14, 2024
26ad2c9
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
asasvari Jul 14, 2024
4b1a16a
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
asasvari Jul 14, 2024
33e35c2
address review comments
asasvari Jul 14, 2024
102328b
address review comments
asasvari Jul 14, 2024
d283fa5
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
xrmx Jul 14, 2024
684d392
Merge branch 'main' into pr3995
asasvari Jul 19, 2024
f89d8a9
improve type hints based on review comments
asasvari Jul 19, 2024
b08ef70
black
asasvari Jul 19, 2024
9c0b119
flake8
asasvari Jul 19, 2024
3e36b69
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
xrmx Jul 19, 2024
55ce61d
Adjust typehinting
asasvari Jul 19, 2024
16beda2
revert py3.10 style typehinting
asasvari Jul 19, 2024
127464b
Address review comments
asasvari Jul 22, 2024
d88c11b
Merge branch 'main' into pr3995
asasvari Jul 22, 2024
2d0fcc9
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
asasvari Jul 23, 2024
071653a
fix mypy
asasvari Jul 23, 2024
70e2302
Merge branch 'main' into pr3995
emdneto Jul 23, 2024
c42e3e6
Update opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
asasvari Jul 23, 2024
fb47e31
fix mypy
asasvari Jul 23, 2024
bbbb7aa
fix linting issues
asasvari Jul 23, 2024
acf6ece
Merge branch 'main' into pr3995
xrmx Jul 24, 2024
d8575f1
Revert annotation as per review comment
asasvari Jul 24, 2024
779a707
use Tuple for tzpe hinting
asasvari Jul 25, 2024
9a3b3a4
Update CHANGELOG.md
asasvari Jul 25, 2024
090e4ba
revert type hinting in more files to fix mypy
asasvari Jul 25, 2024
0524a54
Merge branch 'main' into pr3995
asasvari Jul 25, 2024
3414c2c
Merge branch 'main' into pr3995
asasvari Jul 26, 2024
a917d31
Merge branch 'main' into pr3995
asasvari Jul 26, 2024
626ddd5
Merge branch 'main' into pr3995
asasvari Jul 30, 2024
d467cc8
Update CHANGELOG.md
xrmx Jul 30, 2024
aea5392
Merge branch 'main' into pr3995
lzchen Jul 30, 2024
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
59 changes: 30 additions & 29 deletions opentelemetry-api/src/opentelemetry/attributes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
# 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.
# type: ignore

import logging
import threading
Expand Down Expand Up @@ -59,7 +58,7 @@ def _clean_attribute(
cleaned_seq = []

for element in value:
element = _clean_attribute_value(element, max_len)
element = _clean_attribute_value(element, max_len) # type: ignore
if element is None:
cleaned_seq.append(element)
continue
Expand Down Expand Up @@ -96,7 +95,7 @@ def _clean_attribute(
cleaned_seq.append(element)

# Freeze mutable sequences defensively
return tuple(cleaned_seq)
return tuple(cleaned_seq) # type: ignore

_logger.warning(
"Invalid type %s for attribute '%s' value. Expected one of %s or a "
Expand Down Expand Up @@ -126,7 +125,7 @@ def _clean_attribute_value(
return value


class BoundedAttributes(MutableMapping):
class BoundedAttributes(MutableMapping): # type: ignore
"""An ordered dict with a fixed max capacity.

Oldest elements are dropped when the dict is full and a new element is
Expand All @@ -149,53 +148,55 @@ def __init__(
self.dropped = 0
self.max_value_len = max_value_len
# OrderedDict is not used until the maxlen is reached for efficiency.
self._dict = {} # type: dict | OrderedDict
self._lock = threading.RLock() # type: threading.RLock
# self._dict type: dict | OrderedDict

self._dict = {} # type: ignore
self._lock = threading.RLock()
if attributes:
for key, value in attributes.items():
self[key] = value
self._immutable = immutable

def __repr__(self):
return f"{dict(self._dict)}"
def __repr__(self) -> str:
return f"{dict(self._dict)}" # type: ignore

def __getitem__(self, key):
return self._dict[key]
def __getitem__(self, key): # type: ignore
return self._dict[key] # type: ignore

def __setitem__(self, key, value):
if getattr(self, "_immutable", False):
def __setitem__(self, key, value): # type: ignore
if getattr(self, "_immutable", False): # type: ignore
raise TypeError
with self._lock:
if self.maxlen is not None and self.maxlen == 0:
self.dropped += 1
return

value = _clean_attribute(key, value, self.max_value_len)
if value is not None:
if key in self._dict:
del self._dict[key]
value = _clean_attribute(key, value, self.max_value_len) # type: ignore
if value is not None: # type: ignore
if key in self._dict: # type: ignore
del self._dict[key] # type: ignore
elif (
self.maxlen is not None and len(self._dict) == self.maxlen
self.maxlen is not None and len(self._dict) == self.maxlen # type: ignore
):
if not isinstance(self._dict, OrderedDict):
self._dict = OrderedDict(self._dict)
if not isinstance(self._dict, OrderedDict): # type: ignore
self._dict = OrderedDict(self._dict) # type: ignore
self._dict.popitem(last=False)
self.dropped += 1

self._dict[key] = value
self._dict[key] = value # type: ignore

def __delitem__(self, key):
if getattr(self, "_immutable", False):
def __delitem__(self, key): # type: ignore
if getattr(self, "_immutable", False): # type: ignore
raise TypeError
with self._lock:
del self._dict[key]
del self._dict[key] # type: ignore

def __iter__(self):
def __iter__(self): # type: ignore
with self._lock:
return iter(self._dict.copy())
return iter(self._dict.copy()) # type: ignore

def __len__(self):
return len(self._dict)
def __len__(self): # type: ignore
return len(self._dict) # type: ignore

def copy(self):
return self._dict.copy()
def copy(self): # type: ignore
return self._dict.copy() # type: ignore
52 changes: 32 additions & 20 deletions opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
import typing
from json import dumps
from os import environ
from types import ModuleType
from typing import List, Optional
from urllib import parse

from opentelemetry.attributes import BoundedAttributes
Expand All @@ -75,10 +77,14 @@
from opentelemetry.util._importlib_metadata import entry_points, version
from opentelemetry.util.types import AttributeValue

psutil: Optional[ModuleType] = None

try:
import psutil
import psutil as pustil_module

pustil = pustil_module
except ImportError:
psutil = None
pass

LabelValue = AttributeValue
Attributes = typing.Mapping[str, LabelValue]
Expand Down Expand Up @@ -141,12 +147,15 @@
TELEMETRY_AUTO_VERSION = ResourceAttributes.TELEMETRY_AUTO_VERSION
TELEMETRY_SDK_LANGUAGE = ResourceAttributes.TELEMETRY_SDK_LANGUAGE

_OPENTELEMETRY_SDK_VERSION = version("opentelemetry-sdk")
_OPENTELEMETRY_SDK_VERSION: str = version("opentelemetry-sdk")


class Resource:
"""A Resource is an immutable representation of the entity producing telemetry as Attributes."""

_attributes: BoundedAttributes
_schema_url: str

def __init__(
self, attributes: Attributes, schema_url: typing.Optional[str] = None
):
Expand All @@ -173,7 +182,7 @@ def create(
if not attributes:
attributes = {}

resource_detectors = []
resource_detectors: List[ResourceDetector] = []

resource = _DEFAULT_RESOURCE

Expand All @@ -182,20 +191,21 @@ def create(
).split(",")

if "otel" not in otel_experimental_resource_detectors:

otel_experimental_resource_detectors.append("otel")

resource_detector: str
for resource_detector in otel_experimental_resource_detectors:
resource_detectors.append(
next(
iter(
entry_points(
group="opentelemetry_resource_detector",
name=resource_detector.strip(),
)
) # type: ignore
)
).load()()
)

resource = get_aggregated_resources(
resource_detectors, _DEFAULT_RESOURCE
).merge(Resource(attributes, schema_url))
Expand All @@ -206,7 +216,7 @@ def create(
PROCESS_EXECUTABLE_NAME, None
)
if process_executable_name:
default_service_name += ":" + process_executable_name
default_service_name += ":" + str(process_executable_name)
resource = resource.merge(
Resource({SERVICE_NAME: default_service_name}, schema_url)
)
Expand All @@ -218,6 +228,8 @@ def get_empty() -> "Resource":

@property
def attributes(self) -> Attributes:
if self._attributes is None:
raise ValueError("Attributes are not set.")
return self._attributes

@property
Expand All @@ -241,7 +253,7 @@ def merge(self, other: "Resource") -> "Resource":
Returns:
The newly-created Resource.
"""
merged_attributes = self.attributes.copy()
merged_attributes = dict(self.attributes)
merged_attributes.update(other.attributes)

if self.schema_url == "":
Expand All @@ -257,7 +269,6 @@ def merge(self, other: "Resource") -> "Resource":
other.schema_url,
)
return self

return Resource(merged_attributes, schema_url)

def __eq__(self, other: object) -> bool:
Expand All @@ -268,15 +279,15 @@ def __eq__(self, other: object) -> bool:
and self._schema_url == other._schema_url
)

def __hash__(self):
return hash(
f"{dumps(self._attributes.copy(), sort_keys=True)}|{self._schema_url}"
)
def __hash__(self) -> int:
attributes_json = dumps(self._attributes.copy(), sort_keys=True) # type: ignore
return hash(f"{attributes_json}|{self._schema_url}")

def to_json(self, indent=4) -> str:
def to_json(self, indent: int = 4) -> str:
attributes = dict(self._attributes) # type: ignore
return dumps(
{
"attributes": dict(self._attributes),
"attributes": attributes, # type: ignore
"schema_url": self._schema_url,
},
indent=indent,
Expand All @@ -294,7 +305,7 @@ def to_json(self, indent=4) -> str:


class ResourceDetector(abc.ABC):
def __init__(self, raise_on_error=False):
def __init__(self, raise_on_error: bool = False) -> None:
self.raise_on_error = raise_on_error

@abc.abstractmethod
Expand Down Expand Up @@ -365,16 +376,17 @@ def detect(self) -> "Resource":
resource_info[PROCESS_PARENT_PID] = os.getppid()

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

return Resource(resource_info)
return Resource(resource_info) # type: ignore


def get_aggregated_resources(
detectors: typing.List["ResourceDetector"],
initial_resource: typing.Optional[Resource] = None,
timeout=5,
timeout: int = 5,
) -> "Resource":
"""Retrieves resources from detectors in the order that they were passed

Expand Down
4 changes: 3 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ setenv =
; i.e: CONTRIB_REPO_SHA=dde62cebffe519c35875af6d06fae053b3be65ec tox -e <env to test>
CONTRIB_REPO_SHA={env:CONTRIB_REPO_SHA:main}
CONTRIB_REPO=git+https://github.com/open-telemetry/opentelemetry-python-contrib.git@{env:CONTRIB_REPO_SHA}
mypy: MYPYPATH={toxinidir}/opentelemetry-api/src/:{toxinidir}/tests/opentelemetry-test-utils/src/
mypy: MYPYPATH={toxinidir}/opentelemetry-api/src/:{toxinidir}/opentelemetry-semantic-conventions/src/:{toxinidir}/opentelemetry-sdk/src/:{toxinidir}/tests/opentelemetry-test-utils/src/

commands_pre =

Expand Down Expand Up @@ -331,7 +331,9 @@ commands =

coverage: {toxinidir}/scripts/coverage.sh

mypy: mypy --version
mypy: mypy --install-types --non-interactive --namespace-packages --explicit-package-bases opentelemetry-api/src/opentelemetry/
mypy: mypy --install-types --non-interactive --namespace-packages --explicit-package-bases opentelemetry-sdk/src/opentelemetry/sdk/resources
mypy: mypy --install-types --non-interactive --namespace-packages --explicit-package-bases opentelemetry-semantic-conventions/src/opentelemetry/semconv/

; For test code, we don't want to enforce the full mypy strictness
Expand Down