Tested-by: Paulo Vital <pvital(a)linux.vnet.ibm.com>
Reviewed-by: Paulo Vital <pvital(a)linux.vnet.ibm.com>
On 03/07/2016 11:02 AM, Lucio Correia wrote:
- Use log_args attribute to improve message quality
- Fix handling of utf8 vs str messages
Signed-off-by: Lucio Correia <luciojhc(a)linux.vnet.ibm.com>
---
src/wok/control/base.py | 59 ++++++++++++++++++++++++-------------------------
src/wok/reqlogger.py | 5 +++--
src/wok/utils.py | 23 +++++++++++++++++++
3 files changed, 55 insertions(+), 32 deletions(-)
diff --git a/src/wok/control/base.py b/src/wok/control/base.py
index 79dd22c..be2e35e 100644
--- a/src/wok/control/base.py
+++ b/src/wok/control/base.py
@@ -33,13 +33,15 @@ from wok.exception import InvalidOperation, InvalidParameter
from wok.exception import MissingParameter, NotFoundError
from wok.exception import OperationFailed, UnauthorizedError, WokException
from wok.reqlogger import RequestRecord
-from wok.utils import get_plugin_from_request
+from wok.utils import get_plugin_from_request, utf8_dict
# Default request log messages
COLLECTION_DEFAULT_LOG = "request on collection"
RESOURCE_DEFAULT_LOG = "request on resource"
+LOG_DISABLED_METHODS = ['GET']
+
class Resource(object):
"""
@@ -66,6 +68,9 @@ class Resource(object):
self.role_key = None
self.admin_methods = []
self.log_map = {}
+ self.log_args = {
+ 'ident': self.ident.encode('utf-8') if self.ident else
'',
+ }
def _redirect(self, action_result, code=303):
uri_params = []
@@ -129,12 +134,10 @@ class Resource(object):
action_fn = getattr(self.model, model_fn(self, action_name))
action_result = action_fn(*model_args)
- params = {}
- if model_args:
- params = {'ident': model_args[0].encode('utf-8')}
-
+ # log request
+ reqParams = utf8_dict(self.log_args, request)
RequestRecord(
- self.getRequestMessage(method, action_name) % params,
+ self.getRequestMessage(method, action_name) % reqParams,
app=get_plugin_from_request(),
req=method,
user=cherrypy.session.get(USER_NAME, 'N/A')
@@ -175,18 +178,6 @@ class Resource(object):
fn = getattr(self.model, model_fn(self, 'delete'))
fn(*self.model_args)
cherrypy.response.status = 204
-
- method = 'DELETE'
- params = {}
- if self.model_args:
- params = {'ident': self.model_args[0].encode('utf-8')}
-
- RequestRecord(
- self.getRequestMessage(method, 'default') % params,
- app=get_plugin_from_request(),
- req=method,
- user=cherrypy.session.get(USER_NAME, 'N/A')
- ).log()
except AttributeError:
e = InvalidOperation('WOKAPI0002E', {'resource':
get_class_name(self)})
@@ -206,9 +197,9 @@ class Resource(object):
if not self.is_authorized():
raise UnauthorizedError('WOKAPI0009E')
- return {'GET': self.get,
- 'DELETE': self.delete,
- 'PUT': self.update}[method](*args, **kargs)
+ result = {'GET': self.get,
+ 'DELETE': self.delete,
+ 'PUT': self.update}[method](*args, **kargs)
except InvalidOperation, e:
raise cherrypy.HTTPError(400, e.message)
except InvalidParameter, e:
@@ -222,6 +213,17 @@ class Resource(object):
except WokException, e:
raise cherrypy.HTTPError(500, e.message)
+ # log request
+ if method not in LOG_DISABLED_METHODS:
+ RequestRecord(
+ self.getRequestMessage(method) % self.log_args,
+ app=get_plugin_from_request(),
+ req=method,
+ user=cherrypy.session.get(USER_NAME, 'N/A')
+ ).log()
+
+ return result
+
def is_authorized(self):
user_name = cherrypy.session.get(USER_NAME, '')
user_groups = cherrypy.session.get(USER_GROUPS, [])
@@ -249,14 +251,6 @@ class Resource(object):
args = list(self.model_args) + [params]
ident = update(*args)
-
- method = 'PUT'
- RequestRecord(
- self.getRequestMessage(method) % params,
- app=get_plugin_from_request(),
- req=method,
- user=cherrypy.session.get(USER_NAME, 'N/A')
- ).log()
self._redirect(ident)
self.lookup()
return self.get()
@@ -323,6 +317,7 @@ class Collection(object):
self.role_key = None
self.admin_methods = []
self.log_map = {}
+ self.log_args = {}
def create(self, params, *args):
try:
@@ -413,12 +408,16 @@ class Collection(object):
elif method == 'POST':
params = parse_request()
result = self.create(params, *args)
+
+ # log request
+ reqParams = utf8_dict(self.log_args, params)
RequestRecord(
- self.getRequestMessage(method) % params,
+ self.getRequestMessage(method) % reqParams,
app=get_plugin_from_request(),
req=method,
user=cherrypy.session.get(USER_NAME, 'N/A')
).log()
+
return result
except InvalidOperation, e:
raise cherrypy.HTTPError(400, e.message)
diff --git a/src/wok/reqlogger.py b/src/wok/reqlogger.py
index 3e79377..1294be1 100644
--- a/src/wok/reqlogger.py
+++ b/src/wok/reqlogger.py
@@ -29,7 +29,7 @@ from tempfile import NamedTemporaryFile
from wok.config import config, get_log_download_path
from wok.exception import InvalidParameter, OperationFailed
-from wok.utils import remove_old_files
+from wok.utils import ascii_dict, remove_old_files
# Log search setup
@@ -89,7 +89,8 @@ class RequestParser(object):
with fd:
for record in sortedList:
- fd.write(LOG_FORMAT % record)
+ asciiRecord = ascii_dict(record)
+ fd.write(LOG_FORMAT % asciiRecord)
fd.close()
except IOError as e:
diff --git a/src/wok/utils.py b/src/wok/utils.py
index e3a4124..7e9a928 100644
--- a/src/wok/utils.py
+++ b/src/wok/utils.py
@@ -21,6 +21,7 @@
#
import cherrypy
+import copy
import glob
import grp
import os
@@ -135,6 +136,28 @@ def get_plugin_from_request():
return 'wok'
+def ascii_dict(base, overlay=None):
+ result = copy.deepcopy(base)
+ result.update(overlay or {})
+
+ for key, value in result.iteritems():
+ if isinstance(value, unicode):
+ result[key] = str(value.decode('utf-8'))
+
+ return result
+
+
+def utf8_dict(base, overlay=None):
+ result = copy.deepcopy(base)
+ result.update(overlay or {})
+
+ for key, value in result.iteritems():
+ if isinstance(value, unicode):
+ result[key] = value.encode('utf-8')
+
+ return result
+
+
def import_class(class_path):
module_name, class_name = class_path.rsplit('.', 1)
try: