Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

log HTTP errors in access log. close #317

  • Loading branch information...
commit 5f117136787ea3b8a69c621cfda6f11bf3ca3007 1 parent 1c27d36
Benoit Chesneau benoitc authored
1  examples/test.py
View
@@ -21,6 +21,5 @@ def app(environ, start_response):
('Content-Length', str(len(data))),
('X-Gunicorn-Version', __version__)
]
-
start_response(status, response_headers)
return iter([data])
2  gunicorn/config.py
View
@@ -273,7 +273,7 @@ def _wrapped(instance, req, environ):
elif largs == 2:
return wrap_post_request(val)
else:
- raise TypeError("Value must have an arity of: 3")
+ raise TypeError("Value must have an arity of: 3")
2  gunicorn/glogging.py
View
@@ -157,7 +157,7 @@ def access(self, resp, req, environ, request_time):
status = resp.status.split(None, 1)[0]
atoms = {
- 'h': environ['REMOTE_ADDR'],
+ 'h': environ.get('REMOTE_ADDR', '-'),
'l': '-',
'u': '-', # would be cool to get username from basic auth header
't': self.now(),
11 gunicorn/http/wsgi.py
View
@@ -39,10 +39,9 @@ def __getitem__(self, key):
return data
raise IndexError
-def create(req, sock, client, server, cfg):
- resp = Response(req, sock)
- environ = {
+def default_environ(req, sock, cfg):
+ return {
"wsgi.input": req.body,
"wsgi.errors": sys.stderr,
"wsgi.version": (1, 0),
@@ -58,6 +57,12 @@ def create(req, sock, client, server, cfg):
"SERVER_PROTOCOL": "HTTP/%s" % ".".join(map(str, req.version))
}
+
+def create(req, sock, client, server, cfg):
+ resp = Response(req, sock)
+
+ environ = default_environ(req, sock, cfg)
+
# authors should be aware that REMOTE_HOST and REMOTE_ADDR
# may not qualify the remote addr:
# http://www.ietf.org/rfc/rfc3875
5 gunicorn/util.py
View
@@ -125,8 +125,9 @@ def load_class(uri, default="sync", section="gunicorn.workers"):
return pkg_resources.load_entry_point("gunicorn",
section, uri)
- except ImportError:
- raise RuntimeError("class uri invalid or not found")
+ except ImportError, e:
+ raise RuntimeError("class uri invalid or not found: [%s]",
+ str(e))
klass = components.pop(-1)
mod = __import__('.'.join(components))
for comp in components[1:]:
7 gunicorn/workers/async.py
View
@@ -26,6 +26,7 @@ def timeout_ctx(self):
raise NotImplementedError()
def handle(self, client, addr):
+ req = None
try:
parser = http.RequestParser(self.cfg, client)
try:
@@ -38,6 +39,8 @@ def handle(self, client, addr):
self.handle_request(req, client, addr)
except StopIteration, e:
self.log.debug("Closing connection. %s", e)
+ except Exception, e:
+ self.handle_error(req, client, addr, e)
except socket.error, e:
if e[0] not in (errno.EPIPE, errno.ECONNRESET):
self.log.exception("Socket error processing request.")
@@ -47,14 +50,14 @@ def handle(self, client, addr):
else:
self.log.debug("Ignoring EPIPE")
except Exception, e:
- self.handle_error(client, e)
+ self.handle_error(req, client, addr, e)
finally:
util.close(client)
def handle_request(self, req, sock, addr):
+ request_start = datetime.now()
try:
self.cfg.pre_request(self, req)
- request_start = datetime.now()
resp, environ = wsgi.create(req, sock, addr, self.address, self.cfg)
self.nr += 1
if self.alive and self.nr >= self.max_requests:
17 gunicorn/workers/base.py
View
@@ -3,6 +3,7 @@
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
+from datetime import datetime
import os
import signal
import sys
@@ -11,11 +12,10 @@
from gunicorn import util
from gunicorn.workers.workertmp import WorkerTmp
-
from gunicorn.http.errors import InvalidHeader, InvalidHeaderName, \
InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion, \
LimitRequestLine, LimitRequestHeaders
-
+from gunicorn.http.wsgi import default_environ, Response
class Worker(object):
@@ -125,7 +125,8 @@ def handle_exit(self, sig, frame):
self.alive = False
sys.exit(0)
- def handle_error(self, client, exc):
+ def handle_error(self, req, client, addr, exc):
+ request_start = datetime.now()
if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,
InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,)):
@@ -157,6 +158,16 @@ def handle_error(self, client, exc):
reason = "Internal Server Error"
mesg = ""
+ if req is not None:
+ request_time = datetime.now() - request_start
+ environ = default_environ(req, client, self.cfg)
+ environ['REMOTE_ADDR'] = addr[0]
+ environ['REMOTE_PORT'] = str(addr[1])
+ resp = Response(req, client)
+ resp.status = "%s %s" % (status_int, reason)
+ resp.response_length = len(mesg)
+ self.log.access(resp, req, environ, request_time)
+
if self.debug:
tb = traceback.format_exc()
mesg += "<h2>Traceback:</h2>\n<pre>%s</pre>" % tb
5 gunicorn/workers/sync.py
View
@@ -65,6 +65,7 @@ def run(self):
raise
def handle(self, client, addr):
+ req = None
try:
parser = http.RequestParser(self.cfg, client)
req = parser.next()
@@ -77,7 +78,7 @@ def handle(self, client, addr):
else:
self.log.debug("Ignoring EPIPE")
except Exception, e:
- self.handle_error(client, e)
+ self.handle_error(req, client, addr, e)
finally:
util.close(client)
@@ -113,7 +114,7 @@ def handle_request(self, req, client, addr):
raise
except Exception, e:
# Only send back traceback in HTTP in debug mode.
- self.handle_error(client, e)
+ self.handle_error(req, client, addr, e)
return
finally:
try:
Please sign in to comment.
Something went wrong with that request. Please try again.