|
a/Allura/allura/lib/utils.py |
|
b/Allura/allura/lib/utils.py |
1 |
import time
|
1 |
import time
|
2 |
import string
|
2 |
import string
|
3 |
import hashlib
|
3 |
import hashlib
|
4 |
import binascii
|
4 |
import binascii
|
5 |
import logging
|
5 |
import logging.handlers
|
|
|
6 |
import codecs
|
|
|
7 |
import os.path
|
|
|
8 |
import datetime
|
6 |
import random
|
9 |
import random
|
7 |
import mimetypes
|
10 |
import mimetypes
|
8 |
from itertools import groupby
|
11 |
from itertools import groupby
|
9 |
from logging.handlers import WatchedFileHandler
|
|
|
10 |
|
12 |
|
11 |
import tg
|
13 |
import tg
|
12 |
import pylons
|
14 |
import pylons
|
13 |
import webob.multidict
|
15 |
import webob.multidict
|
14 |
from formencode import Invalid
|
16 |
from formencode import Invalid
|
|
... |
|
... |
100 |
|
102 |
|
101 |
def __getattr__(self, name):
|
103 |
def __getattr__(self, name):
|
102 |
if name.startswith('_'): raise AttributeError, name
|
104 |
if name.startswith('_'): raise AttributeError, name
|
103 |
return getattr(self._logger, name)
|
105 |
return getattr(self._logger, name)
|
104 |
|
106 |
|
|
|
107 |
class TimedRotatingHandler(logging.handlers.BaseRotatingHandler):
|
|
|
108 |
|
|
|
109 |
def __init__(self, strftime_pattern):
|
|
|
110 |
self.pattern = strftime_pattern
|
|
|
111 |
self.last_filename = self.current_filename()
|
|
|
112 |
logging.handlers.BaseRotatingHandler.__init__(self, self.last_filename, 'a')
|
|
|
113 |
|
|
|
114 |
def current_filename(self):
|
|
|
115 |
return os.path.abspath(datetime.datetime.utcnow().strftime(self.pattern))
|
|
|
116 |
|
|
|
117 |
def shouldRollover(self, record):
|
|
|
118 |
'Inherited from BaseRotatingFileHandler'
|
|
|
119 |
return self.current_filename() != self.last_filename
|
|
|
120 |
|
|
|
121 |
def doRollover(self):
|
|
|
122 |
self.stream.close()
|
|
|
123 |
self.baseFilename = self.current_filename()
|
|
|
124 |
if self.encoding:
|
|
|
125 |
self.stream = codecs.open(self.baseFilename, 'w', self.encoding)
|
|
|
126 |
else:
|
|
|
127 |
self.stream = open(self.baseFilename, 'w')
|
|
|
128 |
|
105 |
class StatsHandler(WatchedFileHandler):
|
129 |
class StatsHandler(TimedRotatingHandler):
|
106 |
fields=('action', 'action_type', 'tool_type', 'tool_mount', 'project', 'neighborhood',
|
130 |
fields=('action', 'action_type', 'tool_type', 'tool_mount', 'project', 'neighborhood',
|
107 |
'username', 'url', 'ip_address')
|
131 |
'username', 'url', 'ip_address')
|
108 |
|
132 |
|
109 |
def __init__(self,
|
133 |
def __init__(self,
|
110 |
strftime_pattern,
|
134 |
strftime_pattern,
|
111 |
module='allura',
|
135 |
module='allura',
|
112 |
page=1,
|
136 |
page=1,
|
113 |
**kwargs):
|
137 |
**kwargs):
|
114 |
self.page = page
|
138 |
self.page = page
|
115 |
self.module = module
|
139 |
self.module = module
|
116 |
WatchedFileHandler.__init__(self, strftime_pattern)
|
140 |
TimedRotatingHandler.__init__(self, strftime_pattern)
|
117 |
|
141 |
|
118 |
def emit(self, record):
|
142 |
def emit(self, record):
|
119 |
if not hasattr(record, 'action'):
|
143 |
if not hasattr(record, 'action'):
|
120 |
return
|
144 |
return
|
121 |
kwpairs = dict(
|
145 |
kwpairs = dict(
|
|
... |
|
... |
126 |
kwpairs.update(getattr(record, 'kwpairs', {}))
|
150 |
kwpairs.update(getattr(record, 'kwpairs', {}))
|
127 |
record.kwpairs = ','.join(
|
151 |
record.kwpairs = ','.join(
|
128 |
'%s=%s' % (k,v) for k,v in sorted(kwpairs.iteritems())
|
152 |
'%s=%s' % (k,v) for k,v in sorted(kwpairs.iteritems())
|
129 |
if v is not None)
|
153 |
if v is not None)
|
130 |
record.exc_info = None # Never put tracebacks in the rtstats log
|
154 |
record.exc_info = None # Never put tracebacks in the rtstats log
|
131 |
WatchedFileHandler.emit(self, record)
|
155 |
TimedRotatingHandler.emit(self, record)
|
132 |
|
156 |
|
133 |
def chunked_find(cls, query=None, pagesize=1024):
|
157 |
def chunked_find(cls, query=None, pagesize=1024):
|
134 |
if query is None: query = {}
|
158 |
if query is None: query = {}
|
135 |
page = 0
|
159 |
page = 0
|
136 |
while True:
|
160 |
while True:
|