Skip to content

Commit

Permalink
Use standard python logging.
Browse files Browse the repository at this point in the history
  • Loading branch information
pjz committed Oct 27, 2015
1 parent b1fc319 commit a1df2ba
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 176 deletions.
24 changes: 24 additions & 0 deletions aspen/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,29 @@

from . import serve, website

import logging.config

logging_cfg = {
'version': 1,
'formatters': {
'threadinfo': {
'format': "%(asctime)s pid-%(process)d thread-%(thread)d (%(threadName)s) %(levelname)s: %(message)s"
}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'threadinfo',
'level': 'INFO',
'stream': 'ext://sys.stderr'
}
},
'root': {
'handlers': [ 'console' ]
}
}

logging.config.dictConfig(logging_cfg)

This comment has been minimized.

Copy link
@jaraco

jaraco Jan 20, 2016

Contributor

This call in inconveniently placed for another application launching aspen programmatically. It's not possible to invoke the behavior without importing aspen.__main__ and it's impossible to import aspen.__main__ without invoking the behavior. At the very least, it would be nice if this behavior could be extracted into a function in a public module and invoked explicitly in the __name__ == '__main__' block or implicitly in serve().

This comment has been minimized.

Copy link
@pjz

pjz Jan 20, 2016

Author Contributor

Good point. Open an issue, please.

This comment has been minimized.

Copy link
@chadwhitacre

chadwhitacre Jan 21, 2016

Contributor

if __name__ == '__main__':
serve(website.Website())
4 changes: 0 additions & 4 deletions aspen/algorithms/website.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,6 @@ def log_result_of_request(website, request=None, dispatch_result=None, response=
"""Log access. With our own format (not Apache's).
"""

if website.logging_threshold > 0: # short-circuit
return


# What was the URL path translated to?
# ====================================

Expand Down
13 changes: 2 additions & 11 deletions aspen/configuration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ def configure(self, **kwargs):
, name
))

# log appropriately
aspen.log_dammit(os.linesep.join(msgs))

# Set some attributes.
# ====================
Expand All @@ -169,17 +171,6 @@ def safe_getcwd(errorstr):
raise
raise ConfigurationError(errorstr)


# LOGGING_THRESHOLD
# -----------------
# This is initially set to -1 and not 0 so that we can tell if the user
# changed it programmatically directly before we got here. I do this in
# the testing module, that's really what this is about.
if logging.LOGGING_THRESHOLD == -1:
logging.LOGGING_THRESHOLD = self.logging_threshold
# Now that we know the user's desires, we can log appropriately.
aspen.log_dammit(os.linesep.join(msgs))

# project root
if self.project_root is None:
aspen.log_dammit("project_root not configured (no template bases, "
Expand Down
83 changes: 25 additions & 58 deletions aspen/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,41 @@
aspen.logging
+++++++++++++
Aspen logging. It's simple.
There are log and log_dammit functions that take arbitrary positional
arguments, stringify them, write them to stdout, and flush stdout. Each line
written is prepended with process and thread identifiers. The philosophy is
that additional abstraction layers above Aspen can handle timestamping along
with piping to files, rotation, etc. PID and thread id are best handled inside
the process, however.
The LOGGING_THRESHOLD attribute controls the amount of information that will be
logged. The level kwarg to log must be greater than or equal to the threshold
for the message to get through. Aspen itself logs at levels zero (via log with
the default level value) and one (with the log_dammit wrapper). It's expected
that your application will have its own wrapper(s).
Unicode objects are encoded as UTF-8. Bytestrings are passed through as-is.
Aspen logging convenience wrappers
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from __future__ import with_statement
import os
import pprint
import sys
import thread
import threading


LOGGING_THRESHOLD = -1
PID = os.getpid()
LOCK = threading.Lock()


def stringify(o):
"""Given an object, return a str, never raising ever.
"""
if isinstance(o, str):
o = o
elif isinstance(o, unicode):
o = o.encode('UTF-8', 'backslashreplace')
else:
o = pprint.pformat(o)
return o
import pprint
import logging

LOGGING_THRESHOLD = 0

def log(*messages, **kw):
level = kw.get('level', 0)
if level >= LOGGING_THRESHOLD:
# Be sure to use Python 2.5-compatible threading API.
t = threading.currentThread()
fmt = "pid-%s thread-%s (%s) %%s" % ( PID
, thread.get_ident()
, t.getName()
)
for message in messages:
message = stringify(message)
for line in message.splitlines():
with LOCK:
# Log lines can get interleaved, but that's okay, because
# we prepend lines with thread identifiers that can be used
# to reassemble log messages per-thread.
print(fmt % line.decode('utf8'))
sys.stdout.flush()
"""
Make logging more convenient - use magic to get the __name__ of the calling module/function
and log as it.
'level' if present as a kwarg, is the level to log at.
'upframes' if present as a kwarg, is how many frames up to look for the name.
def log_dammit(*messages):
log(*messages, **{'level': 1})
#log(*messages, level=1) <-- SyntaxError in Python 2.5
other kwargs are passed through to Logger.log()
"""
level = kw.get('level', logging.WARNING)
if 'level' in kw: del kw['level']
upframes = kw.get('upframes', 1)
if 'upframes' in kw: del kw['upframes']
callerName = sys._getframe(upframes).f_globals.get('__name__', '<unknown>')
logging.getLogger(callerName).log(level, *messages, **kw)

def log_dammit(*messages, **kw):
"""
like log(), but critical instead of warning
"""
kw['level'] = kw.get('level', logging.CRITICAL)
kw['upframes'] = kw.get('upframes', 2)
log(*messages, **kw)
103 changes: 0 additions & 103 deletions tests/test_logging.py

This file was deleted.

0 comments on commit a1df2ba

Please sign in to comment.