Add basic access logging (enabled by default to stdout)

This commit is contained in:
Andrew Godwin 2016-04-04 00:29:05 +02:00
parent e0e27ff9eb
commit 7c330e71fa
2 changed files with 67 additions and 0 deletions

54
daphne/access.py Normal file
View File

@ -0,0 +1,54 @@
import datetime
class AccessLogGenerator(object):
"""
Object that implements the Daphne "action logger" internal interface in
order to provide an access log in something resembling NCSA format.
"""
def __init__(self, stream):
self.stream = stream
def __call__(self, protocol, action, details):
"""
Called when an action happens; use it to generate log entries.
"""
# HTTP requests
if protocol == "http" and action == "complete":
self.write_entry(
host=details['client'],
date=datetime.datetime.now(),
request="%(method)s %(path)s" % details,
status=details['status'],
)
# Websocket requests
elif protocol == "websocket" and action == "connected":
self.write_entry(
host=details['client'],
date=datetime.datetime.now(),
request="WSCONNECT %(path)s" % details,
)
elif protocol == "websocket" and action == "disconnected":
self.write_entry(
host=details['client'],
date=datetime.datetime.now(),
request="WSDISCONNECT %(path)s" % details,
)
def write_entry(self, host, date, request, status=None, length=None, ident=None, user=None):
"""
Writes an NCSA-style entry to the log file (some liberty is taken with
what the entries are for non-HTTP)
"""
self.stream.write(
"%s %s %s [%s] \"%s\" %s %s\n" % (
host,
ident or "-",
user or "-",
date.strftime("%d/%b/%Y:%H:%M:%S"),
request,
status or "-",
length or "-",
)
)

View File

@ -3,6 +3,7 @@ import argparse
import logging
import importlib
from .server import Server
from .access import AccessLogGenerator
logger = logging.getLogger(__name__)
@ -54,6 +55,11 @@ class CommandLineInterface(object):
help='How long to wait for worker server before timing out HTTP connections',
default=120,
)
self.parser.add_argument(
'--access-log',
help='Where to write the access log (- for stdout, the default for verbosity=1)',
default=None,
)
self.parser.add_argument(
'--ping-interval',
type=int,
@ -88,6 +94,12 @@ class CommandLineInterface(object):
}[args.verbosity],
format = "%(asctime)-15s %(levelname)-8s %(message)s" ,
)
# If verbosity is 1 or greater, or they told us explicitly, set up access log
access_log_stream = None
if args.access_log:
access_log_stream = open(args.access_log, "a")
elif args.verbosity >= 1:
access_log_stream = sys.stdout
# Import channel layer
sys.path.insert(0, ".")
module_path, object_path = args.channel_layer.split(":", 1)
@ -107,4 +119,5 @@ class CommandLineInterface(object):
unix_socket=args.unix_socket,
http_timeout=args.http_timeout,
ping_interval=args.ping_interval,
action_logger=AccessLogGenerator(access_log_stream) if access_log_stream else None,
).run()