]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-120683: Fix an error in logging.LogRecord timestamp (GH-120709) (GH-120933)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 24 Jun 2024 07:14:26 +0000 (09:14 +0200)
committerGitHub <noreply@github.com>
Mon, 24 Jun 2024 07:14:26 +0000 (07:14 +0000)
The integer part of the timestamp can be rounded up, while the millisecond
calculation truncates, causing the log timestamp to be wrong by up to 999 ms
(affected roughly 1 in 8 million timestamps).
(cherry picked from commit 1500a23f33f5a6d052ff1ef6383d9839928b8ff1)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/logging/__init__.py
Lib/test/test_logging.py
Misc/NEWS.d/next/Library/2024-06-18-19-18-10.gh-issue-120683.xmRez7.rst [new file with mode: 0644]

index 174b37c0ab305b75e4ea928fbf7dc1b878fadb03..3f4144226b40ec5aeaff14f5b42bf4b3e320e184 100644 (file)
@@ -340,11 +340,14 @@ class LogRecord(object):
         self.lineno = lineno
         self.funcName = func
         self.created = ct / 1e9  # ns to float seconds
-
         # Get the number of whole milliseconds (0-999) in the fractional part of seconds.
         # Eg: 1_677_903_920_999_998_503 ns --> 999_998_503 ns--> 999 ms
         # Convert to float by adding 0.0 for historical reasons. See gh-89047
         self.msecs = (ct % 1_000_000_000) // 1_000_000 + 0.0
+        if self.msecs == 999.0 and int(self.created) != ct // 1_000_000_000:
+            # ns -> sec conversion can round up, e.g:
+            # 1_677_903_920_999_999_900 ns --> 1_677_903_921.0 sec
+            self.msecs = 0.0
 
         self.relativeCreated = (ct - _startTime) / 1e6
         if logThreads:
index 504862ad53395e6cdcac641b55110eaf9d1ea5b8..c78e76d16ae5cfd635dfc88837db61755e1a5c94 100644 (file)
@@ -4648,13 +4648,18 @@ class FormatterTest(unittest.TestCase, AssertErrorMessage):
             (1_677_902_297_100_000_000, 100.0),  # exactly 100ms
             (1_677_903_920_999_998_503, 999.0),  # check truncating doesn't round
             (1_677_903_920_000_998_503, 0.0),  # check truncating doesn't round
+            (1_677_903_920_999_999_900, 0.0), # check rounding up
         )
         for ns, want in tests:
             with patch('time.time_ns') as patched_ns:
                 patched_ns.return_value = ns
                 record = logging.makeLogRecord({'msg': 'test'})
-            self.assertEqual(record.msecs, want)
-            self.assertEqual(record.created, ns / 1e9)
+            with self.subTest(ns):
+                self.assertEqual(record.msecs, want)
+                self.assertEqual(record.created, ns / 1e9)
+                self.assertAlmostEqual(record.created - int(record.created),
+                                       record.msecs / 1e3,
+                                       delta=1e-3)
 
     def test_relativeCreated_has_higher_precision(self):
         # See issue gh-102402.
diff --git a/Misc/NEWS.d/next/Library/2024-06-18-19-18-10.gh-issue-120683.xmRez7.rst b/Misc/NEWS.d/next/Library/2024-06-18-19-18-10.gh-issue-120683.xmRez7.rst
new file mode 100644 (file)
index 0000000..50fc927
--- /dev/null
@@ -0,0 +1,4 @@
+Fix an error in :class:`logging.LogRecord`, when the integer part of the
+timestamp is rounded up, while the millisecond calculation truncates,
+causing the log timestamp to be wrong by up to 999 ms (affected roughly 1 in
+8 million timestamps).