opentelemetry-python-contrib
opentelemetry-python-contrib copied to clipboard
Invalid type WSGIRequest for attribute 'request' value opentelemetry
Describe your environment
OS: (Alpine Docker) Python version: (Python 3.8) SDK version: (e.g., 1.22.0) API version: (e.g., 1.22.0)
What happened?
Invalid type WSGIRequest for attribute 'request' value. Expected one of ['bool', 'str', 'bytes', 'int', 'float'] or a sequence of those types
I'm getting this warning when I integrated opentelemetry in my Django application. I don't know if it's a bug or I'm doing something wrong. Has anyone encountered this previously?
Steps to Reproduce
Added these to my requirements
opentelemetry-distro==0.43b0
opentelemetry-exporter-otlp==1.22.0
Added the following to my Dockerfile
RUN opentelemetry-bootstrap --action=install
ENV DJANGO_SETTINGS_MODULE myapp.settings
CMD OTEL_RESOURCE_ATTRIBUTES=service.name=testing_app OTEL_EXPORTER_OTLP_ENDPOINT="http://<IP>:4317" OTEL_EXPORTER_OTLP_PROTOCOL=grpc opentelemetry-instrument gunicorn myapp.wsgi:application -c gunicorn.conf.py
Expected Result
I shouldn't get that warning? I'm not sure here!
Actual Result
I'm getting the warning Invalid type WSGIRequest for attribute 'request' value. Expected one of ['bool', 'str', 'bytes', 'int', 'float'] or a sequence of those types
Additional context
I raised the issue first in opentelemtry-python but was suggested that I raise it here.
Would you like to implement a fix?
None
I have not been able to reproduce this. Could you provide a greater list of dependency versions for the docker container. For instance: opentelemetry-instrumentation-django gunicorn
Consider providing a full repro (Dockerfile + dependencies)
The problem is reproducable if the opentelemetry Logger is used as the root logger in Django:
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"verbose": {
"format": (
f"%(levelname)s [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s] "
"%(asctime)s %(pathname)s %(process)d %(thread)d %(message)s"
)
},
"simple": {
"format": (f"%(levelname)s [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s]" "%(asctime)s %(message)s")
},
},
"handlers": {
# [...]
"opentelemetry": {
"class": "opentelemetry.sdk._logs.LoggingHandler"
},
},
"loggers": {
# [...]
},
"root": {
"handlers": [
#[...]
"opentelemetry",
],
"level": "INFO",
},
}
I fixed it by defining a subclass of the original LoggingHandler and use that class for the otlp handler instead:
from logging import LogRecord
from opentelemetry.sdk._logs import LoggingHandler as OpenTelemetryLoggingHandler
class LoggingHandler(OpenTelemetryLoggingHandler):
@staticmethod
def _get_attributes(record: LogRecord):
attributes = OpenTelemetryLoggingHandler._get_attributes(record)
if "request" in attributes:
attributes["request"] = f'{attributes["request"].method} {attributes["request"].path}'
return attributes
Same here:
deps:
gunicorn==23.0.0
opentelemetry-sdk==1.27.0
opentelemetry-exporter-otlp==1.27.0
opentelemetry-instrumentation-django==0.48b0
opentelemetry-instrumentation-logging==0.48b0
opentelemetry-instrumentation-httpx==0.48b0
Django==4.2.16
Instrumentation
from opentelemetry.instrumentation import django as django_otel
from opentelemetry.instrumentation import httpx as httpx_otel
from opentelemetry.instrumentation import logging as logging_otel
...
logging_otel.LoggingInstrumentor().instrument()
django_otel.DjangoInstrumentor().instrument()
httpx_otel.HTTPXClientInstrumentor().instrument()
...
I have not been able to reproduce this. Could you provide a greater list of dependency versions for the docker container. For instance: opentelemetry-instrumentation-django gunicorn
Consider providing a full repro (Dockerfile + dependencies)
I fixed it by defining a subclass of the original LoggingHandler and use that class for the otlp handler instead:
from logging import LogRecord from opentelemetry.sdk._logs import LoggingHandler as OpenTelemetryLoggingHandler class LoggingHandler(OpenTelemetryLoggingHandler): @staticmethod def _get_attributes(record: LogRecord): attributes = OpenTelemetryLoggingHandler._get_attributes(record) if "request" in attributes: attributes["request"] = f'{attributes["request"].method} {attributes["request"].path}' return attributes
Confirmed, I was able to fix the issue with this approach as well. Many thanks @Okan0
I've started to receive this error, too. Looking into possible solutions
It appears to only happen during exceptions at least for me.
The following attached (minimal) Django server illustrates the problem
To reproduce:
unzip uvlog.zipcd uvlog- run with
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true OTEL_RESOURCE_ATTRIBUTES="service.name=s1" DJANGO_SETTINGS_MODULE=core.settings OTEL_TRACES_EXPORTER=console OTEL_METRICS_EXPORTER=console OTEL_LOGS_EXPORTER=console uv run opentelemetry-instrument gunicorn core.wsgi
- send an HTTP request to base
http :8000- this logs correctly since the django request loggerdjango.requestonly logs errors - send an HTTP request to unhandled endpoint
http :8000/xxx- The offending line appears
...
"body": "Invalid type WSGIRequest for attribute 'request' value. Expected one of ['bool', 'str', 'bytes', 'int', 'float'] or a sequence of those types",
...
- run with FIX_LOG=1 to apply the work-around from @Okan0 above
The main issue seems to be that in django/utils/log.py Django adds request to the map of extras. Somehow, this needs to be filtered within the django instrumentor
I will be investigating this. Could I please be assigned this issue.