-
Notifications
You must be signed in to change notification settings - Fork 704
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does the compression task block the main thread? #243
Comments
Yes, compression takes place in the same thread as the messages are logged. If you configure your sink with |
I will give it a try. |
Unfortunately it didn't work. I will put more invesitgation on my code. The engine already runs in a separate thread... |
Hum... I regards to a few tests and it seems to work as expected, according to what I said about from loguru import logger
import sys
import time
def compression(filepath):
time.sleep(5)
def rotation(message, file):
return message.record["extra"].get("rotate", False)
logger.add("test.log", compression=compression, rotation=rotation, enqueue=False)
logger.info("Before")
logger.bind(rotate=True).info("...")
logger.info("After") If 2020-04-14 19:09:44.863 | INFO | __main__:<module>:14 - Before
2020-04-14 19:09:44.863 | INFO | __main__:<module>:15 - ...
2020-04-14 19:09:49.868 | INFO | __main__:<module>:16 - After If 2020-04-14 19:10:06.004 | INFO | __main__:<module>:14 - Before
2020-04-14 19:10:06.004 | INFO | __main__:<module>:15 - ...
2020-04-14 19:10:06.005 | INFO | __main__:<module>:16 - After However, one thing to note that may explain your problem, is that if you call |
I am still digging... A blocking of the main thread should actually not be a problem because the engine is also running in a separate thread. I dont understand how the network stuff is related to the compression in this case... |
Is your program using What you describe looks like what would happen if the others threads were blocked while one thread execute compression. This would be totally possible, because each sink is protected by a Lines 169 to 180 in e2a337a
|
Multiproceasing is not used, only threads. I am still wondering how this can happen. I can't work on this again around the weekend. I will try to instrument the code to get more insights. |
One question: Do i need to put logger.add(sys.stdout,
level="INFO",
format=LOG_FORMAT)
logger.add(logfile_path,
level="INFO",
format=LOG_FORMAT,
rotation=rotator.should_rotate,
# compression="bz2",
enqueue=True) |
You don't really need to. The main purpose of |
I just observed the behaviour "live": During the compression everything seems to be very very slow. But my threads dont totally stop. Some of them seem to get scheduled pretty delayed and i am getting timeout errors for some of the network requests. After the compression everything seems to be normal again. As python doesn't have thread priorization, i could imagine that the compression threads eats up the major part of the CPU power assigned to my python process. |
Yeah, that's a possibility. Maybe you can work around that by using a custom |
Yes, i also tought of something like that... I will let you know my solution when it is implemented. |
Tried the following: def compress_in_subprocess(filepath):
subprocess.Popen(f"bzip2 -c {filepath} > {filepath}.bz2", shell=True)
logger.add(logfile_path,
level="INFO",
format=LOG_FORMAT,
rotation=rotator.should_rotate,
compression=compress_in_subprocess,
enqueue=True # should actually not be necessary anymore
) What i now experience is, that due to the async process call it can happen that the rotation takes place before the actual execution of the compression, so i will get a very small compressed file and a rotated file with the original to be rotated file size... |
I guess i need to setup a separate compression process (perhaps a crontab) only for the already rotated files. |
Thanks for the report. I hadn't thought of that problem. In this case, I consider that |
I slightly refactored the handling compression. It should be safe to run any custom If you have any other problem, feel free to reopen this issue. :) |
Tried it and it worked :) Thanks a lot for your efforts! |
Unfortunately i already observed 3 times that the main program hangs up upon start of the compression and could be only ended by kill -9. In contrast to that i was also running a test for 72 h w/o any problem... The warning seems not to be issued as it is not present in the log file. This is my current code def compress_in_subprocess(filepath):
logger.warning(f"Compression takes place on '{filepath}'")
# need to run in separate subprocess as it otherwise would block the current python process' ressources
subprocess.Popen(f"bzip2 {filepath}", shell=True)
# ....
logger.add(logfile_path,
level="INFO",
format=LOG_FORMAT,
rotation=rotator.should_rotate,
compression=compress_in_subprocess,
enqueue=True)` |
@Delgan: I guess the issue needs to be reopened |
@mahadi It looks like a deadlock due to the usage of Here is a small snippet to easily reproduce the problem: import time
from loguru import logger
def compress(f):
logger.warning("Compression")
logger.add("foo.log", rotation=lambda _, __: True, compression=compress, enqueue=True)
for i in range(100000):
logger.info("Not hanging yet... {}", i)
time.sleep(0.001) What happens is that each handler uses a The bug happens systematically if This is the same problem as if someone tries to use the logger inside a sink. One has to be careful not to do that. |
Ok, understood. Didnt think about this. |
Yes, there is a warning about using the logger inside a sink but I didn't think it could happen with compression / rotatation / retention either. Ideally, it shouldn't hang, because we'll often tend to forget this detail, but I haven't found a solution. |
I've added a warning to the docs at the end of the paragraph about file sinks. 👍 |
Hi, i have a program running with several threads. Each of them is using queues to buffer its work load while another thread is running. In the main thread my main engine runs and uses the queues to distribute and forward work. Also in the main module the logger is configured with a custom log rotation function. (See #241).
I am monitoring the queue loads and i can see that during the time when log compression happens (after 1 GiB with bz2 - takes ~ 2.5 minutes) my queues only fill up but can not be worked on in my main thread during that time.
So i thought about putting my engine also in a separate thread. But actually logging should be the part which runs in a separate thread.
Can you tell me how this is managed in loguru?
Does the log processing run in a separate thread?
I guess the problem is related to the compression itself. It is running synchronosly...
The text was updated successfully, but these errors were encountered: