* Change AsyncTask constructor to receive a dict task_info
instead of adding more parameters
* Handle WokException separately in order to add it in
translatable form to user log
Signed-off-by: Lucio Correia <luciojhc(a)linux.vnet.ibm.com>
---
src/wok/asynctask.py | 71 ++++++++++++++++++++++++++++++++++++++++++----------
src/wok/i18n.py | 3 +++
src/wok/reqlogger.py | 20 +++++++++++++--
3 files changed, 79 insertions(+), 15 deletions(-)
diff --git a/src/wok/asynctask.py b/src/wok/asynctask.py
index 82a91ec..5d32f5e 100644
--- a/src/wok/asynctask.py
+++ b/src/wok/asynctask.py
@@ -24,25 +24,45 @@ import threading
import traceback
-from wok.exception import OperationFailed
-from wok.utils import get_next_task_id
+from wok.exception import OperationFailed, WokException
+from wok.reqlogger import RequestRecord
+from wok.reqlogger import TASK_FAILED, TASK_STARTED, TASK_SUCCESS
+from wok.utils import get_next_task_id, get_plugin_from_uri
+
+
+METHOD_TASK = 'TASK'
+MSG_FAILED = 'WOKASYNC0003L'
+MSG_STARTED = 'WOKASYNC0001L'
+MSG_SUCCESS = 'WOKASYNC0002L'
def add_task(target_uri, fn, objstore, opaque=None):
id = get_next_task_id()
- AsyncTask(id, target_uri, fn, objstore, opaque)
+ task_info = {
+ 'id': id,
+ 'target_uri': target_uri,
+ 'fn': fn,
+ 'objstore': objstore,
+ 'plugin': get_plugin_from_uri(target_uri),
+ 'user': '',
+ 'ip': '',
+ }
+ AsyncTask(task_info, opaque)
return id
class AsyncTask(object):
- def __init__(self, id, target_uri, fn, objstore, opaque=None):
- if objstore is None:
+ def __init__(self, task_info, opaque=None):
+ if task_info['objstore'] is None:
raise OperationFailed("WOKASYNC0001E")
- self.id = str(id)
- self.target_uri = target_uri
- self.fn = fn
- self.objstore = objstore
+ # task info
+ self.id = str(task_info['id'])
+ self.target_uri = task_info['target_uri']
+ self.fn = task_info['fn']
+ self.task_info = task_info
+
+ # task context
self.status = 'running'
self.message = 'OK'
self._save_helper()
@@ -52,9 +72,29 @@ class AsyncTask(object):
self.thread.setDaemon(True)
self.thread.start()
- def _status_cb(self, message, success=None):
+ # log async task start
+ self._log(MSG_STARTED, TASK_STARTED)
+
+ def _log(self, msgCode, status, exception=None):
+ RequestRecord(
+ self.task_info,
+ exception,
+ app=self.task_info['plugin'],
+ msgCode=msgCode,
+ req=METHOD_TASK,
+ status=status,
+ user=self.task_info['user'],
+ ip=self.task_info['ip']
+ ).log()
+
+ def _status_cb(self, message, success=None, exception=None):
if success is not None:
- self.status = 'finished' if success else 'failed'
+ if success:
+ self.status = 'finished'
+ self._log(MSG_SUCCESS, TASK_SUCCESS)
+ else:
+ self.status = 'failed'
+ self._log(MSG_FAILED, TASK_FAILED, exception)
if message.strip():
self.message = message
@@ -65,7 +105,8 @@ class AsyncTask(object):
for attr in ('id', 'target_uri', 'message',
'status'):
obj[attr] = getattr(self, attr)
try:
- with self.objstore as session:
+ objstore = self.task_info['objstore']
+ with objstore as session:
session.store('task', self.id, obj)
except Exception as e:
raise OperationFailed('WOKASYNC0002E', {'err': e.message})
@@ -74,7 +115,11 @@ class AsyncTask(object):
cherrypy.serving.request = self._cp_request
try:
self.fn(cb, opaque)
+ except WokException, e:
+ cherrypy.log.error_log.error("Error in async_task %s " % self.id)
+ cherrypy.log.error_log.error(traceback.format_exc())
+ cb(e.message, success=False, exception=e)
except Exception, e:
cherrypy.log.error_log.error("Error in async_task %s " % self.id)
cherrypy.log.error_log.error(traceback.format_exc())
- cb(e.message, False)
+ cb(e.message, success=False)
diff --git a/src/wok/i18n.py b/src/wok/i18n.py
index 33107ee..c271446 100644
--- a/src/wok/i18n.py
+++ b/src/wok/i18n.py
@@ -58,6 +58,9 @@ messages = {
"WOKPROXY0001E": _("Unable to (re)start system's nginx.service.
Details: '%(error)s'"),
# These messages (ending with L) are for user log purposes
+ "WOKASYNC0001L": _("Started %(plugin)s task ID %(id)s:
%(target_uri)s"),
+ "WOKASYNC0002L": _("Successfully completed %(plugin)s task ID %(id)s:
%(target_uri)s"),
+ "WOKASYNC0003L": _("Failed to complete %(plugin)s task ID %(id)s:
%(target_uri)s"),
"WOKCOL0001L": _("Request made on collection"),
"WOKRES0001L": _("Request made on resource"),
"WOKROOT0001L": _("User '%(username)s' login"),
diff --git a/src/wok/reqlogger.py b/src/wok/reqlogger.py
index 9f1d2c8..c57b141 100644
--- a/src/wok/reqlogger.py
+++ b/src/wok/reqlogger.py
@@ -39,8 +39,8 @@ from wok.utils import remove_old_files
FILTER_FIELDS = ['app', 'date', 'ip', 'req',
'status' 'user', 'time']
LOG_DOWNLOAD_URI = "/data/logs/%s"
LOG_DOWNLOAD_TIMEOUT = 6
-LOG_FORMAT = "[%(date)s %(time)s %(zone)s] %(req)-6s %(status)s %(app)-11s " \
- "%(ip)-15s %(user)s: %(message)s\n"
+LOG_FORMAT = "[%(date)s %(time)s %(zone)s] %(req)-6s %(status)-4s %(app)-11s"
\
+ " %(ip)-15s %(user)s: %(message)s\n"
RECORD_TEMPLATE_DICT = {
'date': '',
'time': '',
@@ -62,6 +62,16 @@ UNSAFE_REQUEST_PARAMETERS = ['password', 'passwd']
REQUEST_LOG_FILE = "wok-req.log"
WOK_REQUEST_LOGGER = "wok_request_logger"
+# Task logging
+TASK_FAILED = 1002
+TASK_STARTED = 1000
+TASK_SUCCESS = 1001
+TASK_STATUSES = {
+ TASK_FAILED: 'FAIL',
+ TASK_STARTED: 'INIT',
+ TASK_SUCCESS: 'SUCC',
+}
+
class RequestLogger(object):
def __init__(self):
@@ -106,6 +116,12 @@ class RequestParser(object):
for record in sortedList:
asciiRecord = RECORD_TEMPLATE_DICT
asciiRecord.update(ascii_dict(record))
+
+ # log meaning of statuses 1000, 1001, 1002 for clarity
+ status = int(asciiRecord['status'])
+ if status in TASK_STATUSES.keys():
+ asciiRecord['status'] = TASK_STATUSES[status]
+
fd.write(LOG_FORMAT % asciiRecord)
fd.close()
--
1.9.1