Open hp685 opened 4 years ago
Why ist that a problem to you? The class that replaces it is a subclass of Logger and should be fully compatible. The behavior is also documented:
Sets a custom logger using logging.setLoggerClass() so variables in log format are expanded properly.
Hey @hynek,
It causes class name change for downstream applications' logger that run within a host app, which can be perplexing for maintainers of downstream apps.
In my scnenario, the application supports dynamic updates and based on some config value, we set the logger type to logging.Logger
, structlog
or a custom logger
. Each logger also logs the class name and it's difficult to differentiate if every logger returns structlog.stdlib._FixedFindCallerLogger
after structlog
is used at least once.
This is causing issues with opentelemetry:
Invalid type _FixedFindCallerLogger for attribute '_logger' value. Expected one of ['bool', 'str', 'bytes', 'int', 'float'] or a sequence of those types [opentelemetry.attributes] _from_structlog=False _record=<LogRecord: opentelemetry.attributes, 30, /Users/giorgio/.local/share/virtualenvs/releasebot-_HUS3iaX/lib/python3.11/site-packages/opentelemetry/attributes/__init__.py, 101, "Invalid type %s for attribute '%s' value. Expected one of %s or a sequence of those types">
This is causing issues with opentelemetry:
Invalid type _FixedFindCallerLogger for attribute '_logger' value. Expected one of ['bool', 'str', 'bytes', 'int', 'float'] or a sequence of those types [opentelemetry.attributes] _from_structlog=False _record=<LogRecord: opentelemetry.attributes, 30, /Users/giorgio/.local/share/virtualenvs/releasebot-_HUS3iaX/lib/python3.11/site-packages/opentelemetry/attributes/__init__.py, 101, "Invalid type %s for attribute '%s' value. Expected one of %s or a sequence of those types">
I'm sorry, but I don't know what to make of this and I don't have the time to go spelunking through the whole OTEL code base.
Could you provide an Short, Self Contained, Correct, Example?
I have the same problem, structlog is causing an error in the logs.
@giorgiodig @folt
My current fix to get this working with OpenTelemetry (and Websockets):
from opentelemetry.sdk._logs import LoggingHandler
from opentelemetry.util.types import Attributes
class AttrFilteredLoggingHandler(LoggingHandler):
DROP_ATTRIBUTES = ["_logger", "websocket"]
@staticmethod
def _get_attributes(record: logging.LogRecord) -> Attributes:
attributes = LoggingHandler._get_attributes(record)
for attr in AttrFilteredLoggingHandler.DROP_ATTRIBUTES:
if attr in attributes:
del attributes[attr]
return attributes
OTEL's LoggingHandler doesn't call the super().emit
nor does it call self.format()
, so the processors are never run. This means the Record still has a the _logger
attribute stored from structlog.stdlib.ProcessorFormatter.wrap_for_formatter
which can't be serialized.
I believe the only way to fix this is a PR to the Python OpenTelemetry SDK
I'm using structlog package 19.2.0 but I've validated the behavior to be the same in version 19.1.0. Instantiating LoggerFactory causes all subsequent calls to logging.getLogger to be of type
structlog.stdlib._FixedFindCallerLogger
.prints
A minimal example (May not be appropriate usage. Only to illustrate)
prints
This is a rather unexpected side-effect and causes client's code to return an unexpected type for logging.getLogger calls if structlog LoggerFactory is ever instantiated in a parent application. Is this something that can be addressed?