##// END OF EJS Templates
gunicorn: allow custom logger to set consistent formatting of requests for gunicorn with rhodecode logging.
marcink -
r2075:0e299543 default
parent child Browse files
Show More
@@ -1,90 +1,113 b''
1 """
1 """
2 gunicorn config extension and hooks. Sets additional configuration that is
2 gunicorn config extension and hooks. Sets additional configuration that is
3 available post the .ini config.
3 available post the .ini config.
4
4
5 - workers = ${cpu_number}
5 - workers = ${cpu_number}
6 - threads = 1
6 - threads = 1
7 - proc_name = ${gunicorn_proc_name}
7 - proc_name = ${gunicorn_proc_name}
8 - worker_class = sync
8 - worker_class = sync
9 - worker_connections = 10
9 - worker_connections = 10
10 - max_requests = 1000
10 - max_requests = 1000
11 - max_requests_jitter = 30
11 - max_requests_jitter = 30
12 - timeout = 21600
12 - timeout = 21600
13
13
14 """
14 """
15
15
16 import multiprocessing
16 import multiprocessing
17 import sys
17 import sys
18 import time
19 import datetime
18 import threading
20 import threading
19 import traceback
21 import traceback
22 from gunicorn.glogging import Logger
20
23
21
24
22 # GLOBAL
25 # GLOBAL
23 errorlog = '-'
26 errorlog = '-'
24 accesslog = '-'
27 accesslog = '-'
25 loglevel = 'debug'
28 loglevel = 'debug'
26
29
27 # SECURITY
30 # SECURITY
28 limit_request_line = 4094
31 limit_request_line = 4094
29 limit_request_fields = 100
32 limit_request_fields = 100
30 limit_request_field_size = 8190
33 limit_request_field_size = 8190
31
34
32 # SERVER MECHANICS
35 # SERVER MECHANICS
33 # None == system temp dir
36 # None == system temp dir
34 worker_tmp_dir = None
37 worker_tmp_dir = None
35 tmp_upload_dir = None
38 tmp_upload_dir = None
36
39
37 # Custom log format
40 # Custom log format
38 access_log_format = (
41 access_log_format = (
39 '%(t)s GNCRN %(p)-8s %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
42 '%(t)s GNCRN %(p)-8s %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
40
43
41 # self adjust workers based on CPU count
44 # self adjust workers based on CPU count
42 # workers = multiprocessing.cpu_count() * 2 + 1
45 # workers = multiprocessing.cpu_count() * 2 + 1
43
46
44
47
45 def post_fork(server, worker):
48 def post_fork(server, worker):
46 server.log.info("[<%-10s>] WORKER spawned", worker.pid)
49 server.log.info("[<%-10s>] WORKER spawned", worker.pid)
47
50
48
51
49 def pre_fork(server, worker):
52 def pre_fork(server, worker):
50 pass
53 pass
51
54
52
55
53 def pre_exec(server):
56 def pre_exec(server):
54 server.log.info("Forked child, re-executing.")
57 server.log.info("Forked child, re-executing.")
55
58
56
59
57 def when_ready(server):
60 def when_ready(server):
58 server.log.info("Server is ready. Spawning workers")
61 server.log.info("Server is ready. Spawning workers")
59
62
60
63
61 def worker_int(worker):
64 def worker_int(worker):
62 worker.log.info("[<%-10s>] worker received INT or QUIT signal", worker.pid)
65 worker.log.info("[<%-10s>] worker received INT or QUIT signal", worker.pid)
63
66
64 # get traceback info, on worker crash
67 # get traceback info, on worker crash
65 id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
68 id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
66 code = []
69 code = []
67 for thread_id, stack in sys._current_frames().items():
70 for thread_id, stack in sys._current_frames().items():
68 code.append(
71 code.append(
69 "\n# Thread: %s(%d)" % (id2name.get(thread_id, ""), thread_id))
72 "\n# Thread: %s(%d)" % (id2name.get(thread_id, ""), thread_id))
70 for fname, lineno, name, line in traceback.extract_stack(stack):
73 for fname, lineno, name, line in traceback.extract_stack(stack):
71 code.append('File: "%s", line %d, in %s' % (fname, lineno, name))
74 code.append('File: "%s", line %d, in %s' % (fname, lineno, name))
72 if line:
75 if line:
73 code.append(" %s" % (line.strip()))
76 code.append(" %s" % (line.strip()))
74 worker.log.debug("\n".join(code))
77 worker.log.debug("\n".join(code))
75
78
76
79
77 def worker_abort(worker):
80 def worker_abort(worker):
78 worker.log.info("[<%-10s>] worker received SIGABRT signal", worker.pid)
81 worker.log.info("[<%-10s>] worker received SIGABRT signal", worker.pid)
79
82
80
83
81 def pre_request(worker, req):
84 def pre_request(worker, req):
82 return
85 return
83 worker.log.debug("[<%-10s>] PRE WORKER: %s %s",
86 worker.log.debug("[<%-10s>] PRE WORKER: %s %s",
84 worker.pid, req.method, req.path)
87 worker.pid, req.method, req.path)
85
88
86
89
87 def post_request(worker, req, environ, resp):
90 def post_request(worker, req, environ, resp):
88 return
91 return
89 worker.log.debug("[<%-10s>] POST WORKER: %s %s resp: %s", worker.pid,
92 worker.log.debug("[<%-10s>] POST WORKER: %s %s resp: %s", worker.pid,
90 req.method, req.path, resp.status_code) No newline at end of file
93 req.method, req.path, resp.status_code)
94
95
96 class RhodeCodeLogger(Logger):
97 """
98 Custom Logger that allows some customization that gunicorn doesn't allow
99 """
100
101 datefmt = r"%Y-%m-%d %H:%M:%S"
102
103 def __init__(self, cfg):
104 Logger.__init__(self, cfg)
105
106 def now(self):
107 """ return date in RhodeCode Log format """
108 now = time.time()
109 msecs = int((now - long(now)) * 1000)
110 return time.strftime(self.datefmt, time.localtime(now)) + '.{0:03d}'.format(msecs)
111
112
113 logger_class = RhodeCodeLogger
General Comments 0
You need to be logged in to leave comments. Login now