Open alexmojaki opened 1 month ago
Hello, if this issue is not yet assigned to someone could I have a go at it?
Please feel free. The contributing guide is here. If you are making progress towards submitting a PR, please report back and we can assign it to you as well.
I tried reproducing the error but I got this: TypeError: Cannot set opentelemetry.proto.trace.v1.Span.name to 123: 123 has type <class 'int'>, but expected one of: (<class 'bytes'>, <class 'str'>) for field Span.name with a stack trace and I think that covers the first 2 points of the expected behavior in the issue. Please correct me if I am wrong.
Could you please guide me as to what I should work on if this is the case?
Can you show the stack trace? It should come from a different thread so I can't see how it could point to the span = tracer.start_span(123)
line.
Does this only happen when using unreleased code?
It does not point to the exact line, just says that the issue is with the span name. Sorry wasn't more clear. Here is the stack trace:
Exception while exporting Span batch.
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/python_message.py", line 702, in field_setter
new_value = type_checker.CheckValue(new_value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/type_checkers.py", line 211, in CheckValue
raise TypeError(message)
TypeError: 123 has type <class 'int'>, but expected one of: (<class 'bytes'>, <class 'str'>)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/python_message.py", line 558, in init
setattr(self, field_name, field_value)
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/python_message.py", line 704, in field_setter
raise TypeError(
TypeError: Cannot set opentelemetry.proto.trace.v1.Span.name to 123: 123 has type <class 'int'>, but expected one of: (<class 'bytes'>, <class 'str'>)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/soumyadeepmahapatra/Documents/Test/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py", line 367, in _export_batch
self.span_exporter.export(self.spans_list[:idx]) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soumyadeepmahapatra/Documents/Test/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/trace_exporter/__init__.py", line 167, in export
serialized_data = self._serialize_spans(spans)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soumyadeepmahapatra/Documents/Test/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/trace_exporter/__init__.py", line 130, in _serialize_spans
return encode_spans(spans).SerializePartialToString()
^^^^^^^^^^^^^^^^^^^
File "/Users/soumyadeepmahapatra/Documents/Test/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py", line 56, in encode_spans
resource_spans=_encode_resource_spans(sdk_spans)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soumyadeepmahapatra/Documents/Test/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py", line 79, in _encode_resource_spans
pb2_span = _encode_span(sdk_span)
^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soumyadeepmahapatra/Documents/Test/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py", line 114, in _encode_span
return PB2SPan(
^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/python_message.py", line 560, in init
_ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/python_message.py", line 477, in _ReraiseTypeErrorWithFieldName
raise exc.with_traceback(sys.exc_info()[2])
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/python_message.py", line 558, in init
setattr(self, field_name, field_value)
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/google/protobuf/internal/python_message.py", line 704, in field_setter
raise TypeError(
TypeError: Cannot set opentelemetry.proto.trace.v1.Span.name to 123: 123 has type <class 'int'>, but expected one of: (<class 'bytes'>, <class 'str'>) for field Span.name
That doesn't really cover point 2. It's trying to serialize a batch of spans, there's no way to track down which code the faulty span came from.
The reason you're getting an error message seems to come down to this code in protobuf:
# api_implementation.py
_implementation_type = None
try:
# pylint: disable=g-import-not-at-top
from google.protobuf.internal import _api_implementation
# The compile-time constants in the _api_implementation module can be used to
# switch to a certain implementation of the Python API at build time.
_implementation_type = _ApiVersionToImplementationType(
_api_implementation.api_version)
except ImportError:
pass # Unspecified by compiler flags.
def _CanImport(mod_name):
try:
mod = importlib.import_module(mod_name)
# Work around a known issue in the classic bootstrap .par import hook.
if not mod:
raise ImportError(mod_name + ' import succeeded but was None')
return True
except ImportError:
return False
if _implementation_type is None:
if _CanImport('google._upb._message'):
_implementation_type = 'upb'
elif _CanImport('google.protobuf.pyext._message'):
_implementation_type = 'cpp'
else:
_implementation_type = 'python'
...
def Type():
return _implementation_type
# message_factory.py
if api_implementation.Type() == 'python':
from google.protobuf.internal import python_message as message_impl
else:
from google.protobuf.pyext import cpp_message as message_impl # pylint: disable=g-import-not-at-top
hence the lines pointing to google/protobuf/internal/python_message.py
.
For me, api_implementation.Type()
is upb
because import google._upb._message
works, which I'm guessing it doesn't for you. So it depends on how protobuf was built/installed in your environment.
Steps to reproduce
Create a span with a non-string name, then try to encode it, e.g. with the HTTP
OTLPSpanExporter
. For example:What is the actual behavior?
It logs:
What is the expected behavior?
tracer.start_span(123)
line.Overall I suggest that the concrete
opentelemetry.sdk.trace.Tracer.start_span
method and/orReadableSpan.__init__
should emit a warning if the span name is not a string and then convert the object to a string, catching any exceptions that raises. Setting an appropriate warning stacklevel is easier inTracer.start_span
, butReadableSpan.__init__
should cover more possible code paths.Context
While setting a non-string span name seems unusual and difficult to do accidentally, it happened in https://github.com/pydantic/logfire/issues/176 when a user called
logger.exception(exc)
(which is normal and OK) wherelogger
is a standard librarylogging.Logger
hooked up to an OTEL tracer.