Skip to content

Commit 8323c0f

Browse files
committed
gh-116267: Avoid formatting record twice in RotatingFileHandler.
1 parent b72c748 commit 8323c0f

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

Lib/logging/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,9 +1148,8 @@ def emit(self, record):
11481148
"""
11491149
try:
11501150
msg = self.format(record)
1151-
stream = self.stream
11521151
# issue 35046: merged two stream.writes into one.
1153-
stream.write(msg + self.terminator)
1152+
self.stream.write(msg + self.terminator)
11541153
self.flush()
11551154
except RecursionError: # See issue 36272
11561155
raise

Lib/logging/handlers.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def __init__(self, filename, mode, encoding=None, delay=False, errors=None):
6767
self.mode = mode
6868
self.encoding = encoding
6969
self.errors = errors
70+
self._msg = None # cache to avoid reformatting - see gh-116267
7071

7172
def emit(self, record):
7273
"""
@@ -78,7 +79,13 @@ def emit(self, record):
7879
try:
7980
if self.shouldRollover(record):
8081
self.doRollover()
81-
logging.FileHandler.emit(self, record)
82+
if self._msg:
83+
msg = self._msg
84+
self._msg = None
85+
else:
86+
msg = self.format(record)
87+
self.stream.write(msg + self.terminator)
88+
self.flush()
8289
except Exception:
8390
self.handleError(record)
8491

@@ -195,10 +202,11 @@ def shouldRollover(self, record):
195202
"""
196203
if self.stream is None: # delay was set...
197204
self.stream = self._open()
205+
pos = self.stream.tell()
198206
if self.maxBytes > 0: # are we rolling over?
199-
msg = "%s\n" % self.format(record)
207+
self._msg = msg = self.format(record)
200208
self.stream.seek(0, 2) #due to non-posix-compliant Windows feature
201-
if self.stream.tell() + len(msg) >= self.maxBytes:
209+
if self.stream.tell() + len(msg) + len(self.terminator) >= self.maxBytes:
202210
# See bpo-45401: Never rollover anything other than regular files
203211
if os.path.exists(self.baseFilename) and not os.path.isfile(self.baseFilename):
204212
return False

Lib/test/test_logging.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6258,6 +6258,24 @@ def rotator(self, source, dest):
62586258
self.assertFalse(os.path.exists(rh.namer(self.fn + ".1")))
62596259
rh.close()
62606260

6261+
def test_format_once(self):
6262+
class InstrumentedHandler(logging.handlers.RotatingFileHandler):
6263+
def __init__(self, *args, **kwargs):
6264+
super().__init__(*args, **kwargs)
6265+
self._format_count = 0
6266+
6267+
def format(self, record):
6268+
result = super().format(record)
6269+
self._format_count += 1
6270+
return result
6271+
rh = InstrumentedHandler(self.fn, encoding="utf-8",
6272+
backupCount=2, maxBytes=2)
6273+
rh.emit(self.next_rec())
6274+
self.assertLogFile(self.fn)
6275+
rh.emit(self.next_rec())
6276+
self.assertEqual(rh._format_count, 2) # once per emit() call
6277+
rh.close()
6278+
62616279
@support.requires_zlib()
62626280
def test_rotator(self):
62636281
def namer(name):

0 commit comments

Comments
 (0)