[PATCH] [Wok] User Request Log backend improvements

- Use log_args attribute to improve message quality - Fix handling of utf8 vs str messages Signed-off-by: Lucio Correia <luciojhc@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: -- 1.9.1

Tested-by: Paulo Vital <pvital@linux.vnet.ibm.com> Reviewed-by: Paulo Vital <pvital@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@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:
participants (3)
-
Aline Manera
-
Lucio Correia
-
Paulo Vital