Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.3k
gh-102402: Fix floating point math issue by usingtime.time_ns() inlogging.LogRecord#102412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
ghost commentedMar 4, 2023 • edited by ghost
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by ghost
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Lib/test/test_logging.py Outdated
| finally: | ||
| time.time_ns=og_time_ns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Question: Is there a more preferred way to accomplish this other than monkeypatchingtime.time_ns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You can useunittest.mock.patch as in this example:
importtimefromunittest.mockimportpatchfortin (123,456,789):withpatch('time.time_ns')aspatched_ns:patched_ns.return_value=tvalue=time.time_ns()print(f'patched:{value}')print(f'OG:{time.time_ns()}')
which should, when run, print something like this:
patched: 123OG: 1681278183002693921patched: 456OG: 1681278183003199141patched: 789OG: 1681278183003610801There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ah, my assumption was that we probably didn't want to add imports (I don't know why I assumed that...).
Updated to patch withmock instead of manual patching.
I was able to come up with a math approach that is pretty easy to understand. It's also faster. String manipulation:Math:This version is a little faster: |
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Thanks for the PR - minor changes requested.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Lib/test/test_logging.py Outdated
| finally: | ||
| time.time_ns=og_time_ns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You can useunittest.mock.patch as in this example:
importtimefromunittest.mockimportpatchfortin (123,456,789):withpatch('time.time_ns')aspatched_ns:patched_ns.return_value=tvalue=time.time_ns()print(f'patched:{value}')print(f'OG:{time.time_ns()}')
which should, when run, print something like this:
patched: 123OG: 1681278183002693921patched: 456OG: 1681278183003199141patched: 789OG: 1681278183003610801bedevere-bot commentedApr 12, 2023
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I have made the requested changes; please review again
Uh oh!
There was an error while loading.Please reload this page.
Lib/test/test_logging.py Outdated
| finally: | ||
| time.time_ns=og_time_ns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ah, my assumption was that we probably didn't want to add imports (I don't know why I assumed that...).
Updated to patch withmock instead of manual patching.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Thanks@serhiy-storchaka! I've addressed most items but would like more information on the request for additional testing.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
LGTM. I left only one minor suggestion, which can be ignored if you have other reasons.
Thank you for your contribution,@dougthor42. For a first time contributor, this PR has surprisingly high quality, you did not even make common errors. And I did not expect such good responsibility after months of inactivity. I will be glad to see your other PRs.
Lib/test/test_logging.py Outdated
| withpatch("time.time_ns")aspatched_ns: | ||
| orig_modules=import_helper._save_and_remove_modules(['logging']) | ||
| try: | ||
| # mock for module import | ||
| patched_ns.return_value=ns | ||
| importlogging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I think that it can be out of the loop. You only need the following code in the loop:
new_ns=ns+offset_nspatched_ns.return_value=new_nsrecord=logging.makeLogRecord({'msg':'test'})self.assertAlmostEqual(record.created,new_ns/1e9,places=6)self.assertAlmostEqual(record.relativeCreated,offset_ns/1e6,places=7)
It is just an optimization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Agreed. It may be "just an optimization" but I wouldn't consider it apremature optimization. Updated.
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
For a first time contributor, this PR has surprisingly high quality, you did not even make common errors. And I did not expect such good responsibility after months of inactivity. I will be glad to see your other PRs.
Thanks! I do hope to find more PRs that I can help with (and have thetime to help with...)
Lib/test/test_logging.py Outdated
| withpatch("time.time_ns")aspatched_ns: | ||
| orig_modules=import_helper._save_and_remove_modules(['logging']) | ||
| try: | ||
| # mock for module import | ||
| patched_ns.return_value=ns | ||
| importlogging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Agreed. It may be "just an optimization" but I wouldn't consider it apremature optimization. Updated.
Closing and reopening, as there seems to have been a spurious error. |
Thank you@dougthor42 for your patience - sorry it dropped off my radar for so long. |
…()` in `logging.LogRecord` (pythonGH-102412)
This change introduced reference leaks: |
I suggest to not reimport the logging module in the test: deftest_relativeCreated_has_higher_precision(self):# See issue gh-102402ns=1_677_903_920_000_998_503# approx. 2023-03-04 04:25:20 UTCoffsets_ns= (200,500,12_354,99_999,1_677_903_456_999_123_456)with (patch("time.time_ns")astime_ns_mock,support.swap_attr(logging,'_startTime',ns)):foroffset_nsinoffsets_ns:# mock for log record creationnew_ns=ns+offset_nstime_ns_mock.return_value=new_nsrecord=logging.makeLogRecord({'msg':'test'})self.assertAlmostEqual(record.created,new_ns/1e9,places=6)# After PR gh-102412, precision (places) increases from 3 to 7self.assertAlmostEqual(record.relativeCreated,offset_ns/1e6,places=7) |
vstinner commentedApr 17, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I'm happy that myPEP 564 – Add new time functions with nanosecond resolution is used to fix very concrete time rounding issues ;-) |
Could you please open a new issue for the leak? I tried to find the cause, and still have not found it. It is a puzzle. |
I proposed a fix:#117985 |
Oh no! Sorry that my change caused more work for people 😞. TIL about |
Buildbots were broken for 1 day. I merged my fix since no better fix was proposed:8f25cc9 |
Uh oh!
There was an error while loading.Please reload this page.
gh-102402: Fix floating point math issue by using
time.time_ns()inlogging.LogRecord.logging.LogRecordto usetime.time_ns()instead oftime.time().LogRecord.msecsto be robust against floating point / binary representation arithmetic errorsNotes / Open Questions:
LogRecord.msecsis a float so I kept it that way. Why is it a float even though it always has.0?LogRecord.createdas a float in seconds.logging.__init__so I didn't add any for the new code. Would you like me to add some annotations?I opted to use string manipulation to grab themsecs. I have an integer math-based approach, but it's, IMO, more verbose and harder to read/understand. LMK if you want me to switch back to that (there are still some minor fixes to apply to it).msecs-related bug.Fixes#102402.