You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A TypeError: not all arguments converted during string formatting exception occurred in the DDTelemetryLogHandler.emit() method when attempting to format log messages using the % operator with record.msg and record.args:
This issue happened when I updated the following libraries:
Python 3.9.13 -> 3.12.0
Django 4.1.9 -> 5.2
ddtrace 2.12.2 -> 3.4.1
Root Cause Analysis
The error occurs because of a mismatch between format specifiers in record.msg and the arguments in record.args. This mismatch can happen in several scenarios:
Tuple Handling: When record.args is already a tuple, direct application using % can cause errors because the tuple is not unpacked correctly.
Format Specifier Mismatch: If there are more or fewer format specifiers (%s, %d, etc.) in the message than there are arguments provided.
Missing Arguments: When a format specifier exists in the message, but no corresponding argument is provided.
Non-Iterable Value: If record.args is a non-iterable value when multiple format specifiers exist in record.msg
Arguments Mismatch: If there's a mismatch between the number of specifiers and provided arguments
Unexpected type: If record.args is an unexpected type that causes issues with the formatting mechanism
Solution Implemented
The issue was resolved by replacing the direct formatting with the LogRecord.getMessage() method:
defgetMessage(self):
""" Return the message for this LogRecord. Return the message for this LogRecord after merging any user-supplied arguments with the message. """msg=str(self.msg)
ifself.args:
msg=msg%self.argsreturnmsg
This method internally manages all string formatting edge cases and safely returns a properly formatted log message. If using Python 3.12, the getMessage method is already available in the standard logging package. However, a more robust solution should ensure consistent handling of these edge cases across different Python versions. I believe we can approach it with something like this:
Tracer Version(s)
3.4.1
Python Version(s)
Python 3.12.0
Pip Version(s)
pip 23.2.1
Bug Report
String Formatting Issue in DDTelemetryLogHandler
Issue Summary
A
TypeError: not all arguments converted during string formatting
exception occurred in theDDTelemetryLogHandler.emit()
method when attempting to format log messages using the%
operator withrecord.msg
andrecord.args
:This issue happened when I updated the following libraries:
Root Cause Analysis
The error occurs because of a mismatch between format specifiers in
record.msg
and the arguments inrecord.args
. This mismatch can happen in several scenarios:Tuple Handling: When
record.args
is already a tuple, direct application using%
can cause errors because the tuple is not unpacked correctly.Format Specifier Mismatch: If there are more or fewer format specifiers (
%s
,%d
, etc.) in the message than there are arguments provided.Missing Arguments: When a format specifier exists in the message, but no corresponding argument is provided.
Non-Iterable Value: If
record.args
is a non-iterable value when multiple format specifiers exist inrecord.msg
Arguments Mismatch: If there's a mismatch between the number of specifiers and provided arguments
Unexpected type: If
record.args
is an unexpected type that causes issues with the formatting mechanismSolution Implemented
The issue was resolved by replacing the direct formatting with the
LogRecord.getMessage()
method:This method internally manages all string formatting edge cases and safely returns a properly formatted log message. If using Python 3.12, the
getMessage
method is already available in the standard logging package. However, a more robust solution should ensure consistent handling of these edge cases across different Python versions. I believe we can approach it with something like this:Or could we implement a solution to maintain multiple versions for compatibility?
Reproduction Code
No response
Error Logs
local-gameserver | Traceback (most recent call last):
local-gameserver | File "/usr/local/lib/python3.12/threading.py", line 1052, in _bootstrap_inner
local-gameserver | self.run()
local-gameserver | File "/usr/local/lib/python3.12/threading.py", line 989, in run
local-gameserver | self._target(*self._args, **self._kwargs)
local-gameserver | File "/usr/local/lib/python3.12/site-packages/concurrent_log_handler/queue.py", line 54, in _monitor
local-gameserver | super()._monitor() # type: ignore[misc]
local-gameserver | ^^^^^^^^^^^^^^^^^^
local-gameserver | File "/usr/local/lib/python3.12/logging/handlers.py", line 1585, in _monitor
local-gameserver | self.handle(record)
local-gameserver | File "/usr/local/lib/python3.12/logging/handlers.py", line 1566, in handle
local-gameserver | handler.handle(record)
local-gameserver | File "/usr/local/lib/python3.12/logging/init.py", line 1028, in handle
local-gameserver | self.emit(record)
local-gameserver | File "/usr/local/lib/python3.12/site-packages/ddtrace/internal/telemetry/logging.py", line 24, in emit
local-gameserver | self.telemetry_writer.add_error(1, record.msg % record.args, full_file_name, record.lineno)
local-gameserver | ~~~~~~~~~~~^~~~~~~~~~~~~
local-gameserver | TypeError: not all arguments converted during string formatting
Libraries in Use
aiohappyeyeballs==2.6.1
aiohttp==3.11.16
aiosignal==1.3.2
amqp==5.3.1
anyio==4.9.0
asgiref==3.8.1
attrs==25.3.0
bcrypt==4.3.0
billiard==4.2.1
boto3==1.37.34
botocore==1.37.34
bytecode==0.16.2
cachetools==5.5.2
cbor2==5.6.5
celery==5.5.1
celery-redbeat==2.3.2
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
click-didyoumean==0.3.1
click-plugins==1.1.1
click-repl==0.3.0
concurrent-log-handler==0.9.25
cookies==2.2.1
cryptography==44.0.2
datadog==0.51.0
ddtrace==3.4.1
decorator==5.2.1
defusedxml==0.7.1
Deprecated==1.2.18
distlib==0.3.9
Django==5.2
django-annoying==0.10.8
django-datetime-widget==0.9.3
django-extensions==4.1
django-ipware==7.0.1
django-jenkins==0.110.0
django-ratelimit3==1.0.1
django-redis==5.4.0
django-suit==0.2.28
django-tables2==2.7.5
django-uuidfield==0.5.0
envier==0.6.1
filelock==3.18.0
flatbuffers==25.2.10
flower==2.0.1
frozenlist==1.5.0
gevent==24.11.1
google-api-core==2.24.2
google-api-python-client==2.167.0
google-auth==2.39.0
google-auth-httplib2==0.2.0
google-cloud-core==2.4.3
google-cloud-storage==3.1.0
google-crc32c==1.7.1
google-resumable-media==2.7.2
googleapis-common-protos==1.70.0
greenlet==3.2.0
h11==0.14.0
h2==4.2.0
hiredis==3.1.0
hpack==4.1.0
httpcore==1.0.8
httplib2==0.22.0
httpx==0.28.1
humanize==4.12.2
hyperframe==6.1.0
idna==3.10
importlib_metadata==8.6.1
ipaddress==1.0.23
jmespath==1.0.1
kombu==5.5.2
lazy-object-proxy==1.10.0
leaderboard==3.7.3
lxml==5.3.2
maxminddb==2.6.3
mock==5.2.0
multidict==6.4.3
ndg-httpsclient==0.5.1
numpy==2.2.4
oauth2client==4.1.3
oauthlib==3.2.2
opentelemetry-api==1.32.1
pandas==2.2.3
platformdirs==4.3.7
portalocker==3.1.1
prometheus_client==0.21.1
prompt_toolkit==3.0.51
propcache==0.3.1
proto-plus==1.26.1
protobuf==6.30.2
pubnub==10.3.0
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycparser==2.22
pycryptodome==3.22.0
pycryptodomex==3.22.0
PyJWT==2.10.1
pylibmc==1.6.3
pynamodb==6.0.2
pyOpenSSL==25.0.0
pyparsing==3.2.3
python-dateutil==2.9.0.post0
python-ipware==3.0.0
python-oauth2==1.1.1
python-redis-lock==4.0.0
python-social-auth==0.3.6
python3-openid==3.2.0
pytz==2025.2
qless-py==0.11.4
redis==5.2.1
requests==2.32.3
requests-oauthlib==2.0.0
responses==0.4.0
rsa==4.9
s3transfer==0.11.4
setproctitle==1.3.5
setuptools==29.0.1
simplejson==3.20.1
six==1.17.0
sniffio==1.3.1
social-auth-app-django==5.4.3
social-auth-core==4.5.6
South==1.0.2
sqlparse==0.5.3
tenacity==9.1.2
theine==0.5.0
theine_core==0.4.5
titan-sdk==3.0.9
tornado==6.4.2
typing_extensions==4.13.2
tzdata==2025.2
tzlocal==5.3.1
unittest-xml-reporting==3.2.0
uritemplate==4.1.1
urllib3==2.4.0
uwsgidecorators==1.1.0
vine==5.1.0
virtualenv==20.30.0
wcwidth==0.2.13
wheel==0.42.0
wrapt==1.17.2
xmltodict==0.14.2
yarl==1.19.0
zipp==3.21.0
zope.event==5.0
zope.interface==7.2
Operating System
Linux 6c8efc41b480 6.9.8-orbstack-00170-g7b4100b7ced4 #1 SMP Thu Jul 11 03:32:20 UTC 2024 aarch64 GNU/Linux
The text was updated successfully, but these errors were encountered: