cr-connect-workflow/crc/services/task_logging_service.py

85 lines
3.9 KiB
Python

import markdown
import re
from flask import render_template
from flask_mail import Message
from jinja2 import Template
from sqlalchemy import desc
from crc import app, db, mail, session
from crc.api.common import ApiError
from crc.models.email import EmailModel
from crc.models.file import FileDataModel
from crc.models.study import StudyModel
from crc.models.task_log import TaskLogModel, TaskLogLevels, TaskLogQuery
from crc.models.user import UserModel
from crc.services.jinja_service import JinjaService
from crc.services.user_service import UserService
class TaskLoggingService(object):
"""Provides common tools for logging information from running workflows. This logging information
Can be useful in metrics, and as a means of showing what is happening over time. For this reason
we will record some of this data in the database, at least for now. We will also add this information
to our standard logs so all the details exist somewhere, even if the information in the database
is truncated or modified. """
@staticmethod
def add_log(task, level, code, message, study_id, workflow_id):
if level not in TaskLogLevels:
raise ApiError("invalid_logging_level", f"Please specify a valid log level. {TaskLogLevels}")
try:
user_uid = UserService.current_user().uid
except ApiError as e:
user_uid = "unknown"
log_message = f"Workflow {workflow_id}, study {study_id}, task {task.get_name()}, user {user_uid}: {message}"
app.logger.log(TaskLogLevels[level].value, log_message)
log_model = TaskLogModel(level=level,
code=code,
user_uid=user_uid,
message=message,
study_id=study_id,
workflow_id=workflow_id,
task=task.get_name())
session.add(log_model)
session.commit()
return log_model
@staticmethod
def get_logs_for_workflow(workflow_id, tq: TaskLogQuery):
""" Returns an updated TaskLogQuery, with items in reverse chronological order by default. """
query = session.query(TaskLogModel).filter(TaskLogModel.workflow_id == workflow_id)
return TaskLoggingService.__paginate(query, tq)
@staticmethod
def get_logs_for_study(study_id, tq: TaskLogQuery):
""" Returns an updated TaskLogQuery, with items in reverse chronological order by default. """
query = session.query(TaskLogModel).filter(TaskLogModel.study_id == study_id)
return TaskLoggingService.__paginate(query, tq)
@staticmethod
def __paginate(sql_query, task_log_query: TaskLogQuery):
"""Updates the given sql_query with parameters from the task log query, executes it, then updates the
task_log_query with the results from the SQL Query"""
if not task_log_query:
task_log_query = TaskLogQuery()
if task_log_query.sort_column is None:
task_log_query.sort_column = "timestamp"
task_log_query.sort_reverse = True
if task_log_query.code:
sql_query = sql_query.filter(TaskLogModel.code.like(task_log_query.code + "%"))
if task_log_query.level:
sql_query = sql_query.filter(TaskLogModel.level.like(task_log_query.level + "%"))
if task_log_query.user:
sql_query = sql_query.filter(TaskLogModel.user_uid.like(task_log_query.user + "%"))
if task_log_query.sort_reverse:
sort_column = desc(task_log_query.sort_column)
else:
sort_column = task_log_query.sort_column
paginator = sql_query.order_by(sort_column).paginate(task_log_query.page, task_log_query.per_page,
error_out=False)
task_log_query.update_from_sqlalchemy_paginator(paginator)
return task_log_query