package com.linkedin.thirdeye.anomaly.alert.v2; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.linkedin.thirdeye.anomaly.alert.AlertJobContext; import com.linkedin.thirdeye.anomaly.alert.AlertTaskInfo; import com.linkedin.thirdeye.anomaly.job.JobConstants; import com.linkedin.thirdeye.anomaly.task.TaskConstants; import com.linkedin.thirdeye.anomaly.task.TaskGenerator; import com.linkedin.thirdeye.client.DAORegistry; import com.linkedin.thirdeye.datalayer.bao.AlertConfigManager; import com.linkedin.thirdeye.datalayer.bao.JobManager; import com.linkedin.thirdeye.datalayer.bao.TaskManager; import com.linkedin.thirdeye.datalayer.dto.AlertConfigDTO; import com.linkedin.thirdeye.datalayer.dto.JobDTO; import com.linkedin.thirdeye.datalayer.dto.TaskDTO; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.joda.time.DateTime; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AlertJobRunnerV2 implements Job { private static final Logger LOG = LoggerFactory.getLogger(com.linkedin.thirdeye.anomaly.alert.AlertJobRunner.class); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); public static final String ALERT_JOB_CONTEXT_V2 = "ALERT_JOB_CONTEXT_V2"; public static final String ALERT_JOB_MONITORING_WINDOW_START_TIME = "ALERT_JOB_MONITORING_WINDOW_START_TIME"; public static final String ALERT_JOB_MONITORING_WINDOW_END_TIME = "ALERT_JOB_MONITORING_WINDOW_END_TIME"; private JobManager jobDAO = DAORegistry.getInstance().getJobDAO(); private TaskManager taskDAO = DAORegistry.getInstance().getTaskDAO(); private AlertConfigManager alertConfigDAO = DAORegistry.getInstance().getAlertConfigDAO(); private TaskGenerator taskGenerator; private AlertJobContext alertJobContext; public AlertJobRunnerV2() { taskGenerator = new TaskGenerator(); } @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { LOG.info("Running " + jobExecutionContext.getJobDetail().getKey().toString()); alertJobContext = (AlertJobContext) jobExecutionContext.getJobDetail().getJobDataMap().get(ALERT_JOB_CONTEXT_V2); long alertConfigId = alertJobContext.getAlertConfigId(); AlertConfigDTO alertConfig = alertConfigDAO.findById(alertConfigId); if (alertConfig == null) { LOG.error("Alert config with id {} does not exist", alertConfigId); } else { alertJobContext.setAlertConfigDTO(alertConfig); DateTime monitoringWindowStartTime = (DateTime) jobExecutionContext.getJobDetail().getJobDataMap().get(ALERT_JOB_MONITORING_WINDOW_START_TIME); DateTime monitoringWindowEndTime = (DateTime) jobExecutionContext.getJobDetail().getJobDataMap().get(ALERT_JOB_MONITORING_WINDOW_END_TIME); // TODO :remove this monitoring window logic; alert v2 is not based on monitoring window. // Compute window end if (monitoringWindowEndTime == null) { Date scheduledFireTime = jobExecutionContext.getScheduledFireTime(); monitoringWindowEndTime = new DateTime(scheduledFireTime); } // Compute window start according to window end if (monitoringWindowStartTime == null) { monitoringWindowStartTime = monitoringWindowEndTime; } // write to alert_jobs Long jobExecutionId = createJob(monitoringWindowStartTime, monitoringWindowEndTime); alertJobContext.setJobExecutionId(jobExecutionId); // write to alert_tasks List<Long> taskIds = createTasks(monitoringWindowStartTime, monitoringWindowEndTime); LOG.info("Alert V2 tasks created : {}", taskIds); } } private long createJob(DateTime monitoringWindowStartTime, DateTime monitoringWindowEndTime) { Long jobExecutionId = null; try { JobDTO jobSpec = new JobDTO(); jobSpec.setJobName(alertJobContext.getJobName()); jobSpec.setWindowStartTime(monitoringWindowStartTime.getMillis()); jobSpec.setWindowEndTime(monitoringWindowEndTime.getMillis()); jobSpec.setScheduleStartTime(System.currentTimeMillis()); jobSpec.setStatus(JobConstants.JobStatus.SCHEDULED); jobSpec.setTaskType(TaskConstants.TaskType.ALERT2); jobExecutionId = jobDAO.save(jobSpec); LOG.info("Created alert job {} with jobExecutionId {}", jobSpec, jobExecutionId); } catch (Exception e) { LOG.error("Exception in creating alert job", e); } return jobExecutionId; } private List<Long> createTasks(DateTime monitoringWindowStartTime, DateTime monitoringWindowEndTime) { List<Long> taskIds = new ArrayList<>(); try { List<AlertTaskInfo> tasks = taskGenerator .createAlertTasksV2(alertJobContext, monitoringWindowStartTime, monitoringWindowEndTime); for (AlertTaskInfo taskInfo : tasks) { String taskInfoJson = null; try { taskInfoJson = OBJECT_MAPPER.writeValueAsString(taskInfo); } catch (JsonProcessingException e) { LOG.error("Exception when converting AlertTaskInfo {} to jsonString", taskInfo, e); } TaskDTO taskSpec = new TaskDTO(); taskSpec.setTaskType(TaskConstants.TaskType.ALERT2); taskSpec.setJobName(alertJobContext.getJobName()); taskSpec.setStatus(TaskConstants.TaskStatus.WAITING); taskSpec.setStartTime(System.currentTimeMillis()); taskSpec.setTaskInfo(taskInfoJson); taskSpec.setJobId(alertJobContext.getJobExecutionId()); long taskId = taskDAO.save(taskSpec); taskIds.add(taskId); LOG.info("Created alert task {} with taskId {}", taskSpec, taskId); } } catch (Exception e) { LOG.error("Exception in creating alert tasks", e); } return taskIds; } }