import logging from sqlalchemy import and_ from apps.constants.constants import JOB_LOG_STATUS_LIST from apps.constants.message import PAGE_SIZE from apps.models.job import Job from apps.models.job_log import JobLog from extensions import get_db_session from extensions.sqlalchemy import SessionLocal from utils import R from utils.request import like_contains, parse_id_list logger = logging.getLogger(__name__) # ============================================================ # 日志写入(供调度器调用,可在请求上下文外执行) # ============================================================ def record_job_log(job_id, start_time, end_time, status, exception_info=None, job_message=None): """ 记录任务执行日志 使用独立会话写入,调度器线程等无请求上下文场景也可调用。 """ session = SessionLocal() try: job = session.query(Job).filter(Job.id == job_id, Job.is_delete == 0).first() consume_time = 0 if end_time and start_time: consume_time = int((end_time - start_time).total_seconds() * 1000) log = JobLog( job_id=job_id, job_name=job.job_name if job else '', job_group=job.job_group if job else None, job_trigger=job.job_trigger if job else None, cron_expression=job.cron_expression if job else None, job_message=job_message, status=status, start_time=start_time, end_time=end_time, consume_time=consume_time, exception_info=exception_info, ) session.add(log) session.commit() return log except Exception as e: session.rollback() logger.error(f"记录任务执行日志异常: {str(e)}") return None finally: session.close() # ============================================================ # 日志查询/删除 # ============================================================ def get_job_log_page(request): db = get_db_session() # 页码 page = int(request.query_params.get("pageNo", 1)) # 每页数 limit = int(request.query_params.get("pageSize", PAGE_SIZE)) # 实例化查询对象 query = db.query(JobLog).filter(JobLog.del_flag == 0) # 任务名称 job_name = request.query_params.get('jobName') if job_name: query = query.filter(JobLog.job_name.like(like_contains(job_name), escape='\\')) # 任务分组 job_group = request.query_params.get('jobGroup') if job_group: query = query.filter(JobLog.job_group == job_group) # 执行状态 status = request.query_params.get('status') if status: query = query.filter(JobLog.status == status) # 排序 query = query.order_by(JobLog.id.desc()) # 记录总数 count = query.count() # 分页查询 log_list = query.limit(limit).offset((page - 1) * limit).all() # 若当前页超出末页(数据被并发删除),自动回退到第一页 if page > 1 and not log_list: page = 1 count = query.count() log_list = query.limit(limit).offset(0).all() # 实例化结果 result = [] for item in log_list: data = item.to_dict() data['status_name'] = JOB_LOG_STATUS_LIST.get(item.status) result.append(data) return R.ok(data=result, count=count) # 根据ID查询日志详情 def get_job_log_detail(job_log_id): db = get_db_session() log = db.query(JobLog).filter(and_(JobLog.id == job_log_id, JobLog.del_flag == 0)).first() if not log: return None data = log.to_dict() data['status_name'] = JOB_LOG_STATUS_LIST.get(log.status) return data # 删除任务日志(软删除) def delete_job_log(ids_str): id_list = parse_id_list(ids_str) if not id_list: return R.failed("记录ID不存在") db = get_db_session() result = db.query(JobLog).filter(JobLog.id.in_(id_list), JobLog.del_flag == 0).update( {"del_flag": 1}, synchronize_session=False ) return R.ok(msg="本次共删除{0}条数据".format(result))