Gunicorn+UvicornWorker,access log not working after logrotate access log file.
See original GitHub issueChecklist
- [ YES ] The bug is reproducible against the latest release and/or
master
. - [ YES ] There are no similar issues or pull requests to fix it yet.
Describe the bug
Use FastAPI+Uvicorn+Gunicorn to deploy the production environment, When use logrotate to compressed log, access.log file will be reopen, but UvicornWorker not write access log to access.log.
To reproduce
- start server with gunicorn+UvicornWorker
(venv) [root@localhost task_registry_center]# gunicorn -w 2 -b 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker --access-logfile log/access.log main:app
[2020-12-16 17:09:41 +0800] [3330] [INFO] Starting gunicorn 20.0.4
[2020-12-16 17:09:41 +0800] [3330] [INFO] Listening at: http://0.0.0.0:8000 (3330)
[2020-12-16 17:09:41 +0800] [3330] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2020-12-16 17:09:41 +0800] [3332] [INFO] Booting worker with pid: 3332
[2020-12-16 17:09:41 +0800] [3333] [INFO] Booting worker with pid: 3333
- now access log file is empty
[root@localhost log]# pwd
/data/task_registry_center/log
[root@localhost log]# ll
total 20
-rw-r--r--. 1 root root 0 Dec 16 16:56 access.log
-rw-r--r--. 1 root root 0 Dec 16 16:41 client.log
-rw-r--r--. 1 root root 0 Dec 16 16:56 debug.log
-rw-r--r--. 1 root root 0 Dec 16 16:41 elk_client.log
-rw-r--r--. 1 root root 5402 Dec 16 17:08 error.log
-rw-r--r--. 1 root root 0 Dec 16 16:41 id_server.log
-rw-r--r--. 1 root root 4029 Dec 16 17:09 main.log
-rw-r--r--. 1 root root 4480 Dec 16 17:10 tasks.log
- call one api 10 times, now log path is :
[root@localhost log]# ll
total 24
-rw-r--r--. 1 root root 720 Dec 16 17:11 access.log
access.log context is
192.168.11.1:60477 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60478 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60479 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60480 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60481 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60482 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60483 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60484 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60485 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60486 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
- manual call logrotate
[root@localhost ~]# /usr/sbin/logrotate -f /etc/logrotate.d/task_registry_center
logrotate config is :
[root@localhost ~]# cat /etc/logrotate.d/task_registry_center
/data/task_registry_center/log/*.log {
size 1M
rotate 20
compress
nodelaycompress
dateformat -%Y-%m-%d-%s
dateext
missingok
notifempty
postrotate
killall -s USR1 gunicorn 13,9 All
endscript
}
- gunicorn receive USR1 signal to reopen access log file and log this
[2020-12-16 17:12:16 +0800] [3330] [INFO] Handling signal: usr1
[2020-12-16 17:12:16 +0800] [3330] [INFO] Handling signal: usr1
[2020-12-16 17:12:16 +0800] [3330] [INFO] Handling signal: usr1
[2020-12-16 17:12:16 +0800] [3330] [INFO] Handling signal: usr1
- now log path is:
[root@localhost log]# ll
total 20
-rw-r--r--. 1 root root 0 Dec 16 17:12 access.log
-rw-r--r--. 1 root root 125 Dec 16 17:11 access.log-2020-12-16-1608109936.gz
- then call one api 10 times, log path is:
[root@localhost log]# ll
total 20
-rw-r--r--. 1 root root 0 Dec 16 17:12 access.log
-rw-r--r--. 1 root root 125 Dec 16 17:11 access.log-2020-12-16-1608109936.gz
access.log-2020-12-16-1608109936.gz context still is
192.168.11.1:60477 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60478 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60479 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60480 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60481 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60482 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60483 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60484 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60485 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
192.168.11.1:60486 - "GET /api/client?page_size=10&page=1 HTTP/1.1" 200
this 10 times does not log to any access log.
Expected behavior
the lastest 10 times api call will log access log to reopened access.log file.
Actual behavior
the lastest 10 times api call does not log to any access log file.
Debugging material
I have manual send USR1 signal instead of call logrotate, the result is same , new log file is created,but no access record log to it.
Environment
- OS is centos7
- Python 3.8.3
- gunicorn 20.0.4
- uvicorn 0.13.1
- fastapi 0.62.0
Additional context
I have find someone has same issue as me on so,see https://stackoverflow.com/questions/61794303/why-doesnt-gunicorn-write-log-to-reopened-file-while-rotating-a-log-file
I have try to rewirte UvicornWorker like:
class RequestUvicornWorker(UvicornWorker):
def __init__(self, *args, **kwargs):
super(RequestUvicornWorker, self).__init__(*args, **kwargs)
logger = logging.getLogger("uvicorn.access")
handler = WatchedFileHandler(filename='log/access.log')
logger.handlers = self.log.access_log.handlers
logger.setLevel(self.log.access_log.level)
change log handler to WatchedFileHandler, still not working. And i have a flask app deploy with gunicorn, this will correctly log access log to new access log file after logrotate.
Hope for reply,THANK YOU!
Issue Analytics
- State:
- Created 3 years ago
- Comments:14 (4 by maintainers)
Top GitHub Comments
I has same question. uvicorn 0.13.3 will restart gunicorn worker for USR1 signal,which is different from gunicorn. Change
init_signals
to original will work:no idea, someone more familiar with gunicorn internals might have a clue
it’s because, I suppose, we have a SIGTERM issue (see #852) , I just tested your snippet on #853 and I have the shutdown logrotate in files