wcs/wcs/qommon/admin/logger.py

209 lines
8.8 KiB
Python

# w.c.s. - web application for online forms
# Copyright (C) 2005-2010 Entr'ouvert
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
import os
import random
from quixote import get_publisher, get_request, get_response
from quixote.html import htmltext, TemplateIO
from quixote.directory import Directory
from .. import _
from .. import logger, errors
from ..backoffice.menu import html_top
from ..admin.menu import error_page
class ByUserDirectory(Directory):
def _q_lookup(self, component):
return ByUserPages(component)
class LoggerDirectory(Directory):
_q_exports = ['', 'download', 'by_user']
by_user = ByUserDirectory()
def _q_index(self):
get_response().breadcrumb.append(('logs/', _('Logs')))
html_top('logs', title=_('Logs'))
r = TemplateIO(html=False)
request = get_request()
logfile = str(request.get_field('logfile', get_publisher().APP_NAME + '.log'))
if not logfile.startswith(str(get_publisher().APP_NAME + '.log')) or str('/') in str(logfile):
return error_page('logs/', _('Bad log file: %s') % logfile)
logfilename = str(os.path.join(get_publisher().app_dir, logfile))
if not os.path.exists(logfilename):
r += _('Nothing to show')
else:
get_response().filter['sidebar'] = self.get_sidebar(logfile)
user_color_keys = {}
last_date = None
r += htmltext('<table id="logs">\n')
r += htmltext('<thead> <tr>')
r += htmltext(' <th>%s</th>') % _('Time')
r += htmltext(' <th>%s</th>') % _('User')
r += htmltext(' <th>%s</th>') % _('Message')
r += htmltext('<tr></thead>\n')
r += htmltext('<tbody>\n')
i = 1
userlabels = {}
for d in logger.parse_logstream(open(logfilename)):
if not d:
continue
if d.get('user_id'):
user_color_key = d['user_id']
if user_color_key == 'anonymous':
user_color_key += d['ip']
if user_color_key not in user_color_keys:
user_color_keys[user_color_key] = ''.join(
['%x' % random.randint(0xc, 0xf) for x in range(3)])
r += htmltext('<tr class="level-%s" style="background: #%s;">') % (
d['level'].lower(), user_color_keys[user_color_key])
else:
r += htmltext('<tr class="level-%s">') % d['level'].lower()
if last_date != d['date']:
r += htmltext(' <td class="time">%s&nbsp;%s</td>') % (d['date'], d['hour'][:-4])
last_date = d['date']
else:
r += htmltext(' <td class="time">%s</td>') % (d['hour'][:-4])
user_id = d.get('user_id')
if not user_id:
userlabel = None
elif user_id == 'anonymous':
userlabel = _('Anonymous')
ip = d['ip']
r += htmltext(' <td class="userlabel"><span title="%s">%s</span></td>') % (ip, userlabel)
elif user_id == 'unlogged':
userlabel = _('Unlogged')
ip = d['ip']
r += htmltext(' <td class="userlabel"><span title="%s">%s</span></td>') % (ip, userlabel)
elif user_id == 'bot':
userlabel = _('Bot')
r += htmltext(' <td class="userlabel">%s</td>') % userlabel
else:
userlabel = userlabels.get(user_id)
if not userlabel:
try:
user = get_publisher().user_class.get(user_id)
userlabel = htmltext(user.display_name.replace(str(' '), str('&nbsp;')))
except KeyError:
userlabel = _('Unknown')
userlabels[user_id] = userlabel
r += htmltext(' <td class="userlabel">%s</td>') % userlabel
if userlabel:
r += htmltext(' <td class="message">%s</td>') % d['message']
else:
r += htmltext('<td class="message" colspan="2">%s</td>') % d['message']
r += htmltext('</tr>\n')
r += htmltext('</tbody>\n')
r += htmltext('</table>\n')
return r.getvalue()
def get_sidebar(self, logfile):
r = TemplateIO(html=True)
r += htmltext('<ul>')
if logfile:
r += htmltext('<li><a href="download?logfile=%s">%s</a></li>') % (logfile, _('Download Raw Log File'))
else:
r += htmltext('<li><a href="download">%s</a></li>') % _('Download Raw Log File')
r += htmltext('</ul>')
logfiles = [x for x in os.listdir(get_publisher().app_dir) if x.startswith(get_publisher().APP_NAME + str('.log'))]
if len(logfiles) > 1:
options = []
for lfile in logfiles:
firstline = open(os.path.join(get_publisher().app_dir, lfile)).readline()
d = logger.readline(firstline)
if not d:
continue
if logfile == lfile:
selected = 'selected="selected" '
else:
selected = ''
options.append({'selected': selected, 'lfile': lfile,
'date': '%s %s' % (d['date'], d['hour'])})
r += htmltext('<form id="other-log-select">')
r += _('Select another logfile:')
r += htmltext('<select name="logfile">')
options.sort(lambda x,y: cmp(x['date'], y['date']))
options.reverse()
for option in options:
option['since'] = str(_('Since: %s') % option['date'])[:-4]
r += htmltext('<option value="%(lfile)s"%(selected)s>%(since)s</option>') % option
r += htmltext('</select>')
r += htmltext('<input type="submit" value="%s" />') % _('Submit')
return r.getvalue()
def download(self):
request = get_request()
logfile = request.get_field('logfile', get_publisher().APP_NAME + '.log')
if not logfile.startswith(get_publisher().APP_NAME + '.log') or str('/') in logfile:
return error_page('logs/', _('Bad log file: %s') % logfile)
logfilename = os.path.join(get_publisher().app_dir, logfile)
response = get_response()
response.set_content_type('text/x-log', 'iso-8859-1')
response.set_header('content-disposition', 'attachment; filename=%s' % logfile)
return open(logfilename).read()
class ByUserPages(Directory):
_q_exports = ['']
def __init__(self, component):
try:
self.user = get_publisher().user_class.get(component)
except KeyError:
raise errors.TraversalError()
def _q_index(self):
html_top('logs', title=_('Logs'))
r = TemplateIO(html=True)
r += htmltext('<h2>%s - %s</h2>') % (_('User'), self.user.name)
last_date = None
r += htmltext('<table id="logs">')
r += htmltext('<thead> <tr>')
r += htmltext(' <th>%s</th>') % _('Time')
r += htmltext(' <th>%s</th>') % _('Message')
r += htmltext('<tr></thead>')
r += htmltext('<tbody>')
logfilename = str(os.path.join(get_publisher().app_dir, get_publisher().APP_NAME + '.log'))
if os.path.exists(logfilename):
for line in open(logfilename):
d = logger.readline(line)
if not d or d['user_id'] != str(self.user.id):
continue
r += htmltext('<tr>')
if last_date != d['date']:
r += htmltext(' <td class="time">%s&nbsp;%s</td>') % (d['date'], d['hour'][:-4])
last_date = d['date']
else:
r += htmltext(' <td class="time">%s</td>') % (d['hour'][:-4])
r += htmltext(' <td><a href="%s">%s</a></td>') % (d['url'], d['message'])
r += htmltext('</tr>')
r += htmltext('</tbody>')
r += htmltext('</table>')
return r.getvalue()