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

Encounter Invalid type <class 'NoneType'> of value None issue. #4392

Open
DennySORA opened this issue Jan 22, 2025 · 6 comments
Open

Encounter Invalid type <class 'NoneType'> of value None issue. #4392

DennySORA opened this issue Jan 22, 2025 · 6 comments
Labels
bug Something isn't working

Comments

@DennySORA
Copy link

DennySORA commented Jan 22, 2025

Describe your environment

OS: AWS Ubuntu
telemetry.auto.version: 0.50b0
telemetry.sdk.language: python
telemetry.sdk.name: opentelemetry
telemetry.sdk.version: 1.29.0

What happened?

When I was developing a backend using Python FastAPI, an internal error occurred, throwing an exception. Normally, I should be able to find the error logs in Loki, but for some unknown reason, an OpenTelemetry error was triggered instead, making it impossible for me to trace the application's errors.

My exception should have contained data, but OpenTelemetry displayed it as None, which is very strange. However, even in such cases, it should still be able to display the information correctly. It seems I need to ensure that the body can function properly even if it is None.

Steps to Reproduce

  try:
      1/0
  except Exception as e
      logging.error({"error": None})

Actual Result

{
  "body": "Exception while exporting logs.",
  "severity": "ERROR",
  "attributes": {
    "code.filepath": "/otel-auto-instrumentation-python/opentelemetry/sdk/_logs/_internal/export/__init__.py",
    "code.function": "_export_batch",
    "code.lineno": 313,
    "exception.message": "Invalid type <class 'NoneType'> of value None",
    "exception.stacktrace": "Traceback (most recent call last):\n  File \"/otel-auto-instrumentation-python/opentelemetry/sdk/_logs/_internal/export/__init__.py\", line 311, in _export_batch\n    self._exporter.export(self._log_records[:idx])  # type: ignore\n    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py\", line 138, in export\n    serialized_data = encode_logs(batch).SerializeToString()\n                      ^^^^^^^^^^^^^^^^^^\n  File \"/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py\", line 38, in encode_logs\n    return ExportLogsServiceRequest(resource_logs=_encode_resource_logs(batch))\n                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py\", line 62, in _encode_resource_logs\n    pb2_log = _encode_log(sdk_log)\n              ^^^^^^^^^^^^^^^^^^^^\n  File \"/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py\", line 48, in _encode_log\n    body=_encode_value(log_data.log_record.body),\n         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py\", line 85, in _encode_value\n    values=[_encode_key_value(str(k), v) for k, v in value.items()]\n            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py\", line 92, in _encode_key_value\n    return PB2KeyValue(key=key, value=_encode_value(value))\n                                      ^^^^^^^^^^^^^^^^^^^^\n  File \"/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py\", line 88, in _encode_value\n    raise Exception(f\"Invalid type {type(value)} of value {value}\")\nException: Invalid type <class 'NoneType'> of value None\n",
    "exception.type": "Exception",
    "otelServiceName": "aladdin-internal-pii-ai-proxy",
    "otelSpanID": "0",
    "otelTraceID": "0",
    "otelTraceSampled": false
  },
  "resources": {
    "telemetry.auto.version": "0.50b0",
    "telemetry.sdk.language": "python",
    "telemetry.sdk.name": "opentelemetry",
    "telemetry.sdk.version": "1.25.0"
  },
  "instrumentation_scope": {
    "name": "opentelemetry.sdk._logs._internal"
  }
}

Additional context

No response

Would you like to implement a fix?

Yes

@DennySORA DennySORA added the bug Something isn't working label Jan 22, 2025
@xrmx
Copy link
Contributor

xrmx commented Jan 22, 2025

Would be nice to understand what is the value that is None. Does this reproduce with a simpler snippet like below?

    try:
        1/0
    except Exception as e
        log.logger.error({"foo": "bar"})

@DennySORA
Copy link
Author

@xrmx
I reproduced the issue with a simpler snippet as shown below.

  try:
      1/0
  except Exception as e
      logging.error({"error": None})

@DennySORA
Copy link
Author

This issue happened in the following code:

Maybe I can update the following to filter out None values and then convert them to another type, such as an empty string:

def _encode_value(value: Any) -> PB2AnyValue:
if isinstance(value, bool):
return PB2AnyValue(bool_value=value)
if isinstance(value, str):
return PB2AnyValue(string_value=value)
if isinstance(value, int):
return PB2AnyValue(int_value=value)
if isinstance(value, float):
return PB2AnyValue(double_value=value)
if isinstance(value, bytes):
return PB2AnyValue(bytes_value=value)
if isinstance(value, Sequence):
return PB2AnyValue(
array_value=PB2ArrayValue(values=[_encode_value(v) for v in value])
)
elif isinstance(value, Mapping):
return PB2AnyValue(
kvlist_value=PB2KeyValueList(
values=[_encode_key_value(str(k), v) for k, v in value.items()]
)
)
raise Exception(f"Invalid type {type(value)} of value {value}")

I found that PB2AnyValue imported from opentelemetry.proto.common.v1.common_pb2 does not have a type of None.

DennySORA pushed a commit to DennySORA/opentelemetry-python that referenced this issue Jan 23, 2025
DennySORA pushed a commit to DennySORA/opentelemetry-python that referenced this issue Jan 23, 2025
@DennySORA
Copy link
Author

I checked the unit test code:

def test_encode_attributes_error_logs_key(self):
with self.assertLogs(level=ERROR) as error:
result = _encode_attributes({"a": 1, "bad_key": None, "b": 2})

Originally, if the dictionary contains a None key, it throws an exception. Should it support None as a value in the future?

@xrmx
Copy link
Contributor

xrmx commented Jan 23, 2025

_encode_value is the right place to change, this was already filed as #4279

@DennySORA
Copy link
Author

@xrmx OK, Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants