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

Add __repr__ to all classes #3662

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 8 additions & 6 deletions opentelemetry-api/src/opentelemetry/attributes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from collections.abc import MutableMapping
from typing import Optional, Sequence, Union

from opentelemetry.opentelemetry import OpenTelemetry
from opentelemetry.util import types

# bytes are accepted as a user supplied value for attributes but
Expand Down Expand Up @@ -126,7 +127,7 @@ def _clean_attribute_value(
return value


class BoundedAttributes(MutableMapping):
class BoundedAttributes(OpenTelemetry, MutableMapping):
"""An ordered dict with a fixed max capacity.

Oldest elements are dropped when the dict is full and a new element is
Expand All @@ -140,6 +141,12 @@ def __init__(
immutable: bool = True,
max_value_len: Optional[int] = None,
):
super().__init__(
maxlen=maxlen,
attributes=attributes,
immutable=immutable,
max_value_len=max_value_len,
)
if maxlen is not None:
if not isinstance(maxlen, int) or maxlen < 0:
raise ValueError(
Expand All @@ -155,11 +162,6 @@ def __init__(
self[key] = value
self._immutable = immutable

def __repr__(self):
return (
f"{type(self).__name__}({dict(self._dict)}, maxlen={self.maxlen})"
)

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@

from typing import Union

from opentelemetry.opentelemetry import OpenTelemetry
from opentelemetry.util.types import Attributes


class Observation:
class Observation(OpenTelemetry):
"""A measurement observed in an asynchronous instrument

Return/yield instances of this class from asynchronous instrument callbacks.
Expand Down Expand Up @@ -47,6 +48,3 @@ def __eq__(self, other: object) -> bool:
and self.value == other.value
and self.attributes == other.attributes
)

def __repr__(self) -> str:
return f"Observation(value={self.value}, attributes={self.attributes})"
67 changes: 67 additions & 0 deletions opentelemetry-api/src/opentelemetry/opentelemetry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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.

from inspect import signature


class OpenTelemetry:
def __init__(self, *args, **kwargs) -> None:

args = list(args)

object.__setattr__(self, "_repr", [])

parameters = signature(self.__init__).parameters.values()
ocelotl marked this conversation as resolved.
Show resolved Hide resolved

for index, parameter in enumerate(parameters):
if (
parameter.kind is parameter.POSITIONAL_ONLY
or parameter.kind is parameter.POSITIONAL_OR_KEYWORD
):
if args:
self._repr.append(repr(args.pop(0)))
else:
break
elif parameter.kind is parameter.VAR_POSITIONAL:
for _ in range(len(args)):
self._repr.append(repr(args.pop(0)))

for index, parameter in enumerate(parameters):
if parameter.kind is parameter.KEYWORD_ONLY:
if args:
value = args.pop(0)

if parameter.default != value:
self._repr.append(f"{parameter.name}={repr(value)}")
else:
break

for parameter in parameters:
if (
parameter.kind is parameter.KEYWORD_ONLY
or parameter.kind is parameter.POSITIONAL_OR_KEYWORD
) and parameter.name in kwargs.keys():
value = kwargs.pop(parameter.name)

if parameter.default != value:
self._repr.append(f"{parameter.name}={repr(value)}")

elif parameter.kind is parameter.VAR_KEYWORD:
for key, value in kwargs.items():
self._repr.append(f"{key}={repr(value)}")

self._repr = f"{self.__class__.__name__}({', '.join(self._repr)})"

def __repr__(self) -> str:
return self._repr
33 changes: 16 additions & 17 deletions opentelemetry-api/src/opentelemetry/trace/span.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import typing
from collections import OrderedDict

from opentelemetry.opentelemetry import OpenTelemetry
from opentelemetry.trace.status import Status, StatusCode
from opentelemetry.util import types

Expand Down Expand Up @@ -54,7 +55,7 @@ def _is_valid_pair(key: str, value: str) -> bool:
)


class Span(abc.ABC):
class Span(OpenTelemetry, abc.ABC):
"""A span represents a single operation within a trace."""

@abc.abstractmethod
Expand Down Expand Up @@ -201,7 +202,7 @@ def sampled(self) -> bool:
DEFAULT_TRACE_OPTIONS = TraceFlags.get_default()


class TraceState(typing.Mapping[str, str]):
class TraceState(OpenTelemetry, typing.Mapping[str, str]):
"""A list of key-value pairs representing vendor-specific trace info.

Keys and values are strings of up to 256 printable US-ASCII characters.
Expand All @@ -218,6 +219,7 @@ def __init__(
typing.Sequence[typing.Tuple[str, str]]
] = None,
) -> None:
super().__init__(entries=entries)
self._dict = OrderedDict() # type: OrderedDict[str, str]
if entries is None:
return
Expand Down Expand Up @@ -251,13 +253,6 @@ def __iter__(self) -> typing.Iterator[str]:
def __len__(self) -> int:
return len(self._dict)

def __repr__(self) -> str:
pairs = [
f"{{key={key}, value={value}}}"
for key, value in self._dict.items()
]
return str(pairs)

def add(self, key: str, value: str) -> "TraceState":
"""Adds a key-value pair to tracestate. The provided pair should
adhere to w3c tracestate identifiers format.
Expand Down Expand Up @@ -404,7 +399,8 @@ def values(self) -> typing.ValuesView[str]:


class SpanContext(
typing.Tuple[int, int, bool, "TraceFlags", "TraceState", bool]
OpenTelemetry,
typing.Tuple[int, int, bool, "TraceFlags", "TraceState", bool],
):
"""The state of a Span to propagate between processes.

Expand Down Expand Up @@ -437,10 +433,19 @@ def __new__(
and INVALID_SPAN_ID < span_id <= _SPAN_ID_MAX_VALUE
)

return tuple.__new__(
span_context = tuple.__new__(
cls,
(trace_id, span_id, is_remote, trace_flags, trace_state, is_valid),
)
cls.__init__(
span_context,
trace_id,
span_id,
is_remote,
trace_flags=trace_flags,
trace_state=trace_state,
)
return span_context

def __getnewargs__(
self,
Expand Down Expand Up @@ -487,9 +492,6 @@ def __delattr__(self, *args: str) -> None:
"Immutable type, ignoring call to set attribute", stack_info=True
)

def __repr__(self) -> str:
return f"{type(self).__name__}(trace_id=0x{format_trace_id(self.trace_id)}, span_id=0x{format_span_id(self.span_id)}, trace_flags=0x{self.trace_flags:02x}, trace_state={self.trace_state!r}, is_remote={self.is_remote})"


class NonRecordingSpan(Span):
"""The Span that is used when no Span implementation is available.
Expand Down Expand Up @@ -544,9 +546,6 @@ def record_exception(
) -> None:
pass

def __repr__(self) -> str:
return f"NonRecordingSpan({self._context!r})"


INVALID_SPAN_ID = 0x0000000000000000
INVALID_TRACE_ID = 0x00000000000000000000000000000000
Expand Down