loguru: Rotating Error in multi-process (randomly happened)
Hi again 𤣠, got a new error from my multi-process project, which was designed with:
- ā²ļø https://github.com/Delgan/loguru/issues/899
- https://github.com/Delgan/loguru/issues/901
- https://github.com/Delgan/loguru/issues/902
- https://github.com/Delgan/loguru/issues/903
- ā https://github.com/Delgan/loguru/issues/912
The problem is, when I try to restart my project on 2023/07/07 with existed log files :
record.2023-07-06.log
record.log # contains logs of 2023/07/07
loguru would rename record.log to record.2023-07-07.log and put all the logs into it, then generate a new record.log:
record.2023-07-06.log
record.2023-07-07.log # contains logs from `record.log`
record.log
and I am not sure how to reprocude this error because I tried 3 times after the error occured, but loguru works well then.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 25 (8 by maintainers)
Hi @changchiyou.
The root cause of your problem (#894) has been fixed on
masterbranch. Starting with the next Loguru release, you should no longer face unexpected behavior when usingrotation.Iām closing this issue consequently, as it should be solved. If you need any further help, I remain available.
No worries. Thank you for your patience. I appreciate that you havenāt condemned Loguru and are trying to find a solution. I welcome your work and detailed reports about what you observe during the tests. Itās just that thereās a lot of information out there and itās sometimes difficult for me to understand and reproduce the problem youāre facing.
But I hope weāll find a solution. I donāt like the idea of you deprecating your own project on a platform because of Loguru⦠š
Regarding your comment here: https://github.com/Delgan/loguru/issues/916#issuecomment-1628365845
Those tests are failing because
enqueue=Trueimplies the logged messages are not processed synchronously. They are handled in a background thread, which means the main thread will execute the next instruction likely before the message is actually logged. This is incompatible with the current implementation oftest_daily_rotation_with_different_rotation(). Itās crucial in such situation to calllogger.complete()to make sure all messages have been processed, otherwise the test expectations canāt be guaranteed.Regarding your comment here: https://github.com/Delgan/loguru/issues/916#issuecomment-1629930638
Thanks for providing the tests. I could run them on my computer, but the failure reason was different than the one you reported.
Looking at
test_single_process_pure_renaming(), the expectations you listed do not seems appropriate to me.The test is started at the fake date of
"2020-01-01 12:00:00". When the first message is logged, the"record.log"file should be created, which is fine. However, you are then moving the clock forward by 24 hours. New date is"2020-01-02 12:00:00". Remember that thecompressioni.e.renamefunction is executed on rotation, which is triggered by the first logged message after therotation="00:00"threshold. That is, whenfrozen.tick(delta=datetime.timedelta(hours=24)), nothing happens within Loguru. However, after that, the firstlogger.debug()call will start the rotation process as Loguru will detect that the"00:00"limit is exceeded. This causes yourrename()function to be called, and your rename function is implemented usingtoday = datetime.datetime.now().strftime(r"%Y-%m-%d"). Therefore, the file is naturally renamed to"record.2020-01-02.log"and not"record.2020-01-01.log"as you seem to expect.Maybe you actually want to subtract
datetime.timedelta(days=1)as we previously discussed in #899?In addition, there are also missing calls to
logger.complete()as I explained above. It must be called after theforloop containing thelogger.debug()calls. Otherwise, the results will be indeterminate. This is very important.The case oftest_multi_process_pure_renaming()is even more tricky. Basically, youāre right thatfreeze_time()does not work well with"spawn"method. This is because Loguru rotation mechanism relies on file creation timestamp, but that means the filesystem needs to be faked during tests. Thefreeze_time()helper maintains a structure of file paths associated with fake timestamp. However, when"spawn"is used, the content of this structure is lost in the child process, and the timestamp canāt be faked. The"fork"method copies the structure, therefore itās fine. This explains why you face unexpected results during tests, but in production it shouldnāt be a problem.Edit: On further reflection, Iām no longer sure of this explanation. The message are handled in the main process, therefore
freeze_timeshould work correctly. I canāt explain the differences between"fork"and"spawn"for now.Regarding your comment here: https://github.com/Delgan/loguru/issues/916#issuecomment-1630075894
Sorry, this is a new argument which exists on
masterbranch but is not available in the most recent release (0.7.0). Iād forgotten about that.Itās not a requirement. It mainly useful to isolate each test cases instead of calling
multiprocessing.set_start_method()globally.Regarding your comment here: https://github.com/Delgan/loguru/issues/916#issuecomment-1630435064
With the explanations Iāve given above, I donāt think we can conclude that thereās a bug in Loguru for now.
I arranged the two unit tests you shared as follow:
logger.complete()is called adequatelytest_single_process_pure_renaming()freeze_time()with actualtime.sleep()intest_multi_process_pure_renaming()The test cases work fine now, regardless of
"spawn"or"fork"being used: