From 88c2c168acf6d44320e71bb675a7bd9cbc20da5f Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 12 May 2021 18:36:59 +0200 Subject: [PATCH] add v1.user.log.query message --- sql/risotto.sql | 2 +- src/risotto/dispatcher.py | 13 +++++++--- src/risotto/logger.py | 52 +++++++++------------------------------ src/risotto/message.py | 8 ++++-- 4 files changed, 28 insertions(+), 47 deletions(-) diff --git a/sql/risotto.sql b/sql/risotto.sql index 50812c2..d51a63d 100644 --- a/sql/risotto.sql +++ b/sql/risotto.sql @@ -5,7 +5,7 @@ CREATE TABLE RisottoLog( URI VARCHAR(255), URIS VARCHAR(255), UserLogin VARCHAR(100) NOT NULL, - Level VARCHAR(10) NOT NULL, + Status INTEGER NOT NULL, Kwargs JSON, Returns JSON, StartDate timestamp DEFAULT current_timestamp, diff --git a/src/risotto/dispatcher.py b/src/risotto/dispatcher.py index 2d9c147..607a90f 100644 --- a/src/risotto/dispatcher.py +++ b/src/risotto/dispatcher.py @@ -42,14 +42,21 @@ class CallDispatcher: for ret in returns: async with await Config(response, display_name=lambda self, dyn_name, suffix: self.impl_getname()) as config: await config.property.read_write() + key = None try: for key, value in ret.items(): await config.option(key).value.set(value) - except AttributeError: - err = _(f'function {module_name}.{function_name} return the unknown parameter "{key}" for the uri "{risotto_context.version}.{risotto_context.message}"') + except AttributeError as err: + if key is not None: + err = _(f'function {module_name}.{function_name} return the unknown parameter "{key}" for the uri "{risotto_context.version}.{risotto_context.message}"') + else: + err = _(f'function {module_name}.{function_name} return unconsistency data "{err}" for the uri "{risotto_context.version}.{risotto_context.message}"') raise CallError(err) except ValueError as err: - err = _(f'function {module_name}.{function_name} return the invalid parameter "{key}" for the uri "{risotto_context.version}.{risotto_context.message}": {err}') + if key is not None: + err = _(f'function {module_name}.{function_name} return the invalid parameter "{key}" for the uri "{risotto_context.version}.{risotto_context.message}": {err}') + else: + err = _(f'function {module_name}.{function_name} return unconsistency error for the uri "{risotto_context.version}.{risotto_context.message}": {err}') raise CallError(err) await config.property.read_only() mandatories = await config.value.mandatory() diff --git a/src/risotto/logger.py b/src/risotto/logger.py index 4cc84ab..2c168d7 100644 --- a/src/risotto/logger.py +++ b/src/risotto/logger.py @@ -11,6 +11,9 @@ from .config import get_config database_lock = Lock() +LEVELS = ['Error', 'Info', 'Success', 'Started', 'Failure'] + + class Logger: """ An object to manager log """ @@ -39,9 +42,9 @@ class Logger: ) -> None: uri = self._get_last_uri(risotto_context) uris = " ".join(risotto_context.paths) - insert = 'INSERT INTO RisottoLog(Msg, URI, URIS, UserLogin, Level' + insert = 'INSERT INTO RisottoLog(Msg, URI, URIS, UserLogin, Status' values = 'VALUES($1,$2,$3,$4,$5' - args = [msg, uri, uris, risotto_context.username, level] + args = [msg, uri, uris, risotto_context.username, LEVELS.index(level)] if kwargs: insert += ', Kwargs' values += ',$6' @@ -67,40 +70,6 @@ class Logger: except UndefinedTableError as err: raise Exception(_(f'cannot access to database ({err}), was the database really created?')) - async def query(self, - risotto_context: Context, - context_id: int, - uri: Optional[str], - ) -> list: - sql = '''SELECT Msg as msg, URI as uri_name, URIS as uris, UserLogin as user_login, Level as level, Kwargs as kwargs, Returns as returns, StartDate as start_date, StopDate as stop_date - FROM RisottoLog - WHERE UserLogin = $1 AND (LogId = $2 OR ContextId = $2) - ''' - args = [sql, risotto_context.username, context_id] - if uri is not None: - sql += ' AND URI = $3' - args.append(uri) - ret = [] - async with database_lock: - connection = await self.get_connection(risotto_context) - for row in await connection.fetch(*args): - d = {} - for key, value in row.items(): - if key in ['kwargs', 'returns']: - if isinstance(value, dict): - pass - elif not value: - value = {} - else: - value = loads(value) - if key == 'uris': - value = value.split(' ') - elif key in ['start_date', 'stop_date']: - value = str(value) - d[key] = value - ret.append(d) - return ret - def _get_last_uri(self, risotto_context: Context, ) -> str: @@ -171,7 +140,7 @@ class Logger: print(_(f'{risotto_context.username}: START{context}:{paths_msg}: {msg}')) await self.insert(msg, risotto_context, - 'Start', + 'Started', arguments, start=True, ) @@ -185,11 +154,11 @@ class Logger: print(_(f'{risotto_context.username}: SUCCESS({risotto_context.context_id}):{paths_msg}')) sql = """UPDATE RisottoLog SET StopDate = $2, - Level = 'SUCCESS' + Status = $3 """ - args = [datetime.now()] + args = [datetime.now(), LEVELS.index('Success')] if returns: - sql += """, Returns = $3 + sql += """, Returns = $4 """ args.append(dumps(returns)) sql += """WHERE LogId = $1 @@ -214,7 +183,7 @@ class Logger: print(_(f'{risotto_context.username}: FAILED({risotto_context.context_id}):{paths_msg}: {err}')) sql = """UPDATE RisottoLog SET StopDate = $2, - Level = 'FAILED', + Status = $4, Msg = $3 WHERE LogId = $1 """ @@ -224,6 +193,7 @@ class Logger: risotto_context.start_id, datetime.now(), err, + LEVELS.index('Failure'), ) async def info(self, diff --git a/src/risotto/message.py b/src/risotto/message.py index e4453c9..ed8dd14 100644 --- a/src/risotto/message.py +++ b/src/risotto/message.py @@ -313,6 +313,7 @@ class CustomParam: 'string': 'String', 'number': 'Number', 'object': 'Dict', + 'any': 'Any', 'array': 'Array', 'file': 'File', 'float': 'Float'} @@ -448,6 +449,7 @@ def _get_option(name, 'reverse_condition': ParamValue(True)}), calc_value_property_help)) + props.append('notunique') description = arg.description.strip().rstrip() kwargs = {'name': name, 'doc': _get_description(description, name), @@ -523,6 +525,7 @@ def _parse_responses(message_def, 'Number': IntOption, 'Boolean': BoolOption, 'Dict': DictOption, + 'Any': AnyOption, 'Float': FloatOption, # FIXME 'File': StrOption}.get(type_) @@ -530,8 +533,9 @@ def _parse_responses(message_def, raise Exception(f'unknown param type {obj.type} in responses of message {message_def.message}') if hasattr(obj, 'default'): kwargs['default'] = obj.default + kwargs['properties'] = ('notunique',) else: - kwargs['properties'] = ('mandatory',) + kwargs['properties'] = ('mandatory', 'notunique') options.append(option(**kwargs)) od = OptionDescription(uri, message_def.response.description, @@ -600,7 +604,7 @@ def get_messages(current_module_names, select_option = ChoiceOption('message', 'Nom du message.', tuple(messages), - properties=frozenset(['mandatory', 'positional'])) + properties=frozenset(['mandatory', 'positional', 'notunique'])) for uri in messages: message_def = get_message(uri, current_module_names,