211 lines
7.5 KiB
Python
211 lines
7.5 KiB
Python
from typing import Dict, Any, Optional
|
|
from json import dumps, loads
|
|
from asyncpg.exceptions import UndefinedTableError
|
|
from datetime import datetime
|
|
|
|
from .context import Context
|
|
from .utils import _
|
|
from .config import get_config
|
|
|
|
|
|
class Logger:
|
|
""" An object to manager log
|
|
"""
|
|
async def insert(self,
|
|
msg: str,
|
|
uri: str,
|
|
uris: str,
|
|
risotto_context: Context,
|
|
level: str,
|
|
data: Any=None,
|
|
start: bool=False,
|
|
) -> None:
|
|
insert = 'INSERT INTO RisottoLog(Msg, URI, URIS, UserLogin, Level'
|
|
values = 'VALUES($1,$2,$3,$4,$5'
|
|
args = [msg, uri, uris, risotto_context.username, level]
|
|
if data:
|
|
insert += ', Data'
|
|
values += ',$6'
|
|
args.append(dumps(data))
|
|
context_id = risotto_context.context_id
|
|
if context_id is not None:
|
|
insert += ', ContextId'
|
|
if data:
|
|
values += ',$7'
|
|
else:
|
|
values += ',$6'
|
|
args.append(context_id)
|
|
|
|
sql = insert + ') ' + values + ') RETURNING LogId'
|
|
try:
|
|
log_id = await risotto_context.connection.fetchval(sql, *args)
|
|
if context_id is None and start:
|
|
risotto_context.context_id = log_id
|
|
if start:
|
|
risotto_context.start_id = log_id
|
|
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, Data as data, 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 = []
|
|
for row in await risotto_context.connection.fetch(*args):
|
|
d = {}
|
|
for key, value in row.items():
|
|
if key == 'data':
|
|
if not value:
|
|
value = {}
|
|
else:
|
|
value = loads(value)
|
|
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:
|
|
if risotto_context.paths:
|
|
return risotto_context.paths[-1]
|
|
return ''
|
|
|
|
def _get_message_paths(self,
|
|
risotto_context: Context,
|
|
) -> str:
|
|
if not risotto_context.paths:
|
|
return ''
|
|
paths = risotto_context.paths
|
|
if risotto_context.type:
|
|
paths_msg = f' {risotto_context.type} '
|
|
else:
|
|
paths_msg = ' '
|
|
if len(paths) == 1:
|
|
paths_msg += f'message: {paths[0]}'
|
|
else:
|
|
paths_msg += f'sub-messages: '
|
|
paths_msg += ' > '.join(paths)
|
|
return paths_msg
|
|
|
|
async def error_msg(self,
|
|
risotto_context: Context,
|
|
arguments,
|
|
error: str,
|
|
msg: str='',
|
|
):
|
|
""" send message when an error append
|
|
"""
|
|
paths_msg = self._get_message_paths(risotto_context)
|
|
print(_(f'{risotto_context.username}: ERROR: {error} ({paths_msg} with arguments "{arguments}": {msg})'))
|
|
await self.insert(msg,
|
|
self._get_last_uri(risotto_context),
|
|
paths_msg,
|
|
risotto_context,
|
|
'Error',
|
|
arguments,
|
|
)
|
|
|
|
async def info_msg(self,
|
|
risotto_context: Context,
|
|
arguments: Dict,
|
|
msg: str='',
|
|
) -> None:
|
|
""" send message with common information
|
|
"""
|
|
paths_msg = self._get_message_paths(risotto_context)
|
|
if get_config()['global']['debug']:
|
|
print(_(f'{risotto_context.username}: INFO:{paths_msg}: {msg}'))
|
|
await self.insert(msg,
|
|
self._get_last_uri(risotto_context),
|
|
paths_msg,
|
|
risotto_context,
|
|
'Info',
|
|
arguments,
|
|
)
|
|
|
|
async def start(self,
|
|
risotto_context: Context,
|
|
arguments: dict,
|
|
msg: str,
|
|
) -> None:
|
|
paths_msg = self._get_message_paths(risotto_context)
|
|
if get_config()['global']['debug']:
|
|
print(_(f'{risotto_context.username}: START:{paths_msg}: {msg}'))
|
|
await self.insert(msg,
|
|
self._get_last_uri(risotto_context),
|
|
paths_msg,
|
|
risotto_context,
|
|
'Start',
|
|
arguments,
|
|
start=True,
|
|
)
|
|
|
|
async def success(self,
|
|
risotto_context: Context,
|
|
returns: Optional[dict]=None,
|
|
) -> None:
|
|
if get_config()['global']['debug']:
|
|
paths_msg = self._get_message_paths(risotto_context)
|
|
print(_(f'{risotto_context.username}: SUCCESS:{paths_msg}({risotto_context.context_id})'))
|
|
sql = """UPDATE RisottoLog
|
|
SET StopDate = $2,
|
|
Level = 'SUCCESS'
|
|
"""
|
|
args = [datetime.now()]
|
|
if returns:
|
|
sql += """, Returns = $3
|
|
"""
|
|
args.append(dumps(returns))
|
|
sql += """WHERE LogId = $1
|
|
"""
|
|
await risotto_context.connection.execute(sql,
|
|
risotto_context.start_id,
|
|
*args,
|
|
)
|
|
|
|
async def failed(self,
|
|
risotto_context: Context,
|
|
err: str,
|
|
) -> None:
|
|
if get_config()['global']['debug']:
|
|
paths_msg = self._get_message_paths(risotto_context)
|
|
print(_(f'{risotto_context.username}: FAILED:{paths_msg}({risotto_context.context_id}): err'))
|
|
sql = """UPDATE RisottoLog
|
|
SET StopDate = $2,
|
|
Level = 'FAILED',
|
|
Msg = $3
|
|
WHERE LogId = $1
|
|
"""
|
|
await risotto_context.connection.execute(sql,
|
|
risotto_context.start_id,
|
|
datetime.now(),
|
|
err,
|
|
)
|
|
|
|
async def info(self,
|
|
risotto_context,
|
|
msg,
|
|
):
|
|
if get_config()['global']['debug']:
|
|
print(msg)
|
|
await self.insert(msg,
|
|
'',
|
|
None,
|
|
risotto_context,
|
|
'Info',
|
|
)
|
|
|
|
|
|
log = Logger()
|