blob: 65802d9ee159827bfa23d8751510964a1b14f7e5 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.oozie.sla;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import org.apache.oozie.AppType;
import org.apache.oozie.client.OozieClient;
import org.apache.oozie.client.event.SLAEvent;
import org.apache.oozie.client.event.SLAEvent.EventStatus;
import org.apache.oozie.client.rest.JsonBean;
import org.apache.oozie.client.rest.JsonTags;
import org.apache.oozie.client.rest.JsonUtils;
import org.apache.oozie.util.DateUtils;
import org.apache.openjpa.persistence.jdbc.Index;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
@Entity
@Table(name = "SLA_SUMMARY")
@NamedQueries({
@NamedQuery(name = "UPDATE_SLA_SUMMARY_FOR_SLA_STATUS", query = "update SLASummaryBean w set w.slaStatus = :slaStatus,"
+ " w.eventStatus = :eventStatus, w.eventProcessed = :eventProcessed, w.lastModifiedTS = :lastModifiedTS "
+ "where w.jobId = :jobId"),
@NamedQuery(name = "UPDATE_SLA_SUMMARY_FOR_STATUS_ACTUAL_TIMES", query = "update SLASummaryBean w set w.slaStatus = :slaStatus,"
+ " w.eventStatus = :eventStatus, w.eventProcessed = :eventProcessed, w.jobStatus = :jobStatus, w.lastModifiedTS "
+ "= :lastModifiedTS, w.actualStartTS = :actualStartTS, w.actualEndTS = :actualEndTS, w.actualDuration = :actualDuration"
+ " where w.jobId = :jobId"),
@NamedQuery(name = "UPDATE_SLA_SUMMARY_FOR_EXPECTED_TIMES", query = "update SLASummaryBean w set w.nominalTimeTS "
+ "= :nominalTime, w.expectedStartTS = :expectedStartTime, w.expectedEndTS = :expectedEndTime, w.expectedDuration "
+ "= :expectedDuration , w.lastModifiedTS = :lastModTime where w.jobId = :jobId"),
@NamedQuery(name = "UPDATE_SLA_SUMMARY_EVENTPROCESSED", query = "update SLASummaryBean w set w.eventProcessed "
+ "= :eventProcessed where w.jobId = :jobId"),
@NamedQuery(name = "UPDATE_SLA_SUMMARY_LAST_MODIFIED_TIME", query = "update SLASummaryBean w set w.lastModifiedTS "
+ "= :lastModifiedTS where w.jobId = :jobId"),
@NamedQuery(name = "UPDATE_SLA_SUMMARY_ALL", query = "update SLASummaryBean w set w.jobId = :jobId, w.appName = :appName,"
+ " w.appType = :appType, w.nominalTimeTS = :nominalTime, w.expectedStartTS = :expectedStartTime, w.expectedEndTS "
+ "= :expectedEndTime, w.expectedDuration = :expectedDuration, w.jobStatus = :jobStatus, w.slaStatus = :slaStatus,"
+ " w.eventStatus = :eventStatus, w.lastModifiedTS = :lastModTime, w.user = :user, w.parentId = :parentId,"
+ " w.eventProcessed = :eventProcessed, w.actualDuration = :actualDuration, w.actualEndTS = :actualEndTS,"
+ " w.actualStartTS = :actualStartTS where w.jobId = :jobId"),
@NamedQuery(name = "GET_SLA_SUMMARY", query = "select OBJECT(w) from SLASummaryBean w where w.jobId = :id"),
@NamedQuery(name = "GET_SLA_SUMMARY_RECORDS_RESTART", query = "select OBJECT(w) from SLASummaryBean w where w.eventProcessed "
+ "<= 7 AND w.lastModifiedTS >= :lastModifiedTime"),
@NamedQuery(name = "GET_SLA_SUMMARY_EVENTPROCESSED", query = "select w.eventProcessed from SLASummaryBean w where w.jobId = :id"),
@NamedQuery(name = "GET_SLA_SUMMARY_EVENTPROCESSED_LAST_MODIFIED",
query = "select w.eventProcessed, w.lastModifiedTS from SLASummaryBean w where w.jobId = :id"),
@NamedQuery(name = "GET_SLA_SUMMARY_ALL", query = "select OBJECT(w) from SLASummaryBean w")
})
/**
* Class to store all the SLA related details (summary) per job
*/
public class SLASummaryBean implements JsonBean {
@Id
@Basic
@Column(name = "job_id")
private String jobId;
@Basic
@Index
@Column(name = "parent_id")
private String parentId;
@Basic
@Index
@Column(name = "app_name")
private String appName;
@Basic
@Column(name = "app_type")
private String appType;
@Basic
@Column(name = "user_name")
private String user;
@Basic
@Column(name = "created_time")
private Timestamp createdTimeTS = null;
@Basic
@Index
@Column(name = "nominal_time")
private Timestamp nominalTimeTS = null;
@Basic
@Column(name = "expected_start")
private Timestamp expectedStartTS = null;
@Basic
@Column(name = "expected_end")
private Timestamp expectedEndTS = null;
@Basic
@Column(name = "expected_duration")
private long expectedDuration = -1;
@Basic
@Column(name = "actual_start")
private Timestamp actualStartTS = null;
@Basic
@Column(name = "actual_end")
private Timestamp actualEndTS = null;
@Basic
@Column(name = "actual_duration")
private long actualDuration = -1;
@Basic
@Column(name = "job_status")
private String jobStatus;
@Basic
@Column(name = "event_status")
private String eventStatus;
@Basic
@Column(name = "sla_status")
private String slaStatus;
@Basic
@Index
@Column(name = "event_processed")
private byte eventProcessed = 0;
@Basic
@Index
@Column(name = "last_modified")
private Timestamp lastModifiedTS = null;
public SLASummaryBean() {
}
public SLASummaryBean(SLACalcStatus slaCalc) {
SLARegistrationBean reg = slaCalc.getSLARegistrationBean();
setId(slaCalc.getId());
setAppName(reg.getAppName());
setAppType(reg.getAppType());
setNominalTime(reg.getNominalTime());
setExpectedStart(reg.getExpectedStart());
setExpectedEnd(reg.getExpectedEnd());
setExpectedDuration(reg.getExpectedDuration());
setJobStatus(slaCalc.getJobStatus());
setSLAStatus(slaCalc.getSLAStatus());
setEventStatus(slaCalc.getEventStatus());
setLastModifiedTime(slaCalc.getLastModifiedTime());
setUser(reg.getUser());
setParentId(reg.getParentId());
setEventProcessed(slaCalc.getEventProcessed());
setActualDuration(slaCalc.getActualDuration());
setActualEnd(slaCalc.getActualEnd());
setActualStart(slaCalc.getActualStart());
}
public String getId() {
return jobId;
}
public void setId(String jobId) {
this.jobId = jobId;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public Timestamp getCreatedTimestamp() {
return createdTimeTS;
}
public void setCreatedTimestamp(Timestamp createdTime) {
this.createdTimeTS = createdTime;
}
public Date getCreatedTime() {
return DateUtils.toDate(createdTimeTS);
}
public void setCreatedTime(Date createdTime) {
this.createdTimeTS = DateUtils.convertDateToTimestamp(createdTime);
}
public Date getNominalTime() {
return DateUtils.toDate(nominalTimeTS);
}
public Timestamp getNominalTimestamp() {
return this.nominalTimeTS;
}
public void setNominalTime(Date nominalTime) {
this.nominalTimeTS = DateUtils.convertDateToTimestamp(nominalTime);
}
public Date getExpectedStart() {
return DateUtils.toDate(expectedStartTS);
}
public Timestamp getExpectedStartTimestamp() {
return this.expectedStartTS;
}
public void setExpectedStart(Date expectedStart) {
this.expectedStartTS = DateUtils.convertDateToTimestamp(expectedStart);
}
public Date getExpectedEnd() {
return DateUtils.toDate(expectedEndTS);
}
public Timestamp getExpectedEndTimestamp() {
return this.expectedEndTS;
}
public void setExpectedEnd(Date expectedEnd) {
this.expectedEndTS = DateUtils.convertDateToTimestamp(expectedEnd);
}
public long getExpectedDuration() {
return expectedDuration;
}
public void setExpectedDuration(long expectedDuration) {
this.expectedDuration = expectedDuration;
}
public Date getActualStart() {
return DateUtils.toDate(actualStartTS);
}
public Timestamp getActualStartTimestamp() {
return this.actualStartTS;
}
public void setActualStart(Date actualStart) {
this.actualStartTS = DateUtils.convertDateToTimestamp(actualStart);
}
public Date getActualEnd() {
return DateUtils.toDate(actualEndTS);
}
public Timestamp getActualEndTimestamp() {
return this.actualEndTS;
}
public void setActualEnd(Date actualEnd) {
this.actualEndTS = DateUtils.convertDateToTimestamp(actualEnd);
}
public long getActualDuration() {
return actualDuration;
}
public void setActualDuration(long actualDuration) {
this.actualDuration = actualDuration;
}
public String getJobStatus() {
return jobStatus;
}
public void setJobStatus(String status) {
this.jobStatus = status;
}
public SLAEvent.EventStatus getEventStatus() {
return (eventStatus != null ? SLAEvent.EventStatus.valueOf(eventStatus) : null);
}
public void setEventStatus(SLAEvent.EventStatus eventStatus) {
this.eventStatus = (eventStatus != null ? eventStatus.name() : null);
}
public SLAEvent.SLAStatus getSLAStatus() {
return (slaStatus != null ? SLAEvent.SLAStatus.valueOf(slaStatus) : null);
}
public String getSLAStatusString() {
return slaStatus;
}
public String getEventStatusString() {
return eventStatus;
}
public void setSLAStatus(SLAEvent.SLAStatus stage) {
this.slaStatus = (stage != null ? stage.name() : null);
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public AppType getAppType() {
return AppType.valueOf(appType);
}
public void setAppType(AppType appType) {
this.appType = appType.toString();
}
public byte getEventProcessed() {
return eventProcessed;
}
public void setEventProcessed(int eventProcessed) {
this.eventProcessed = (byte)eventProcessed;
}
public Date getLastModifiedTime() {
return DateUtils.toDate(lastModifiedTS);
}
public Timestamp getLastModifiedTimestamp() {
return this.lastModifiedTS;
}
public void setLastModifiedTime(Date lastModified) {
this.lastModifiedTS = DateUtils.convertDateToTimestamp(lastModified);
}
@Override
public JSONObject toJSONObject() {
return toJSONObject(null);
}
@Override
@SuppressWarnings("unchecked")
public JSONObject toJSONObject(String timeZoneId) {
JSONObject json = new JSONObject();
Map<EventStatus,Long> eventMap = calculateEventStatus();
StringBuilder eventStatusStr = new StringBuilder();
boolean first = true;
for(EventStatus e: eventMap.keySet()) {
if(!first) {
eventStatusStr.append(",");
}
eventStatusStr.append(e.toString());
first = false;
}
json.put(JsonTags.SLA_SUMMARY_ID, jobId);
if (parentId != null) {
json.put(JsonTags.SLA_SUMMARY_PARENT_ID, parentId);
}
json.put(JsonTags.SLA_SUMMARY_APP_NAME, appName);
json.put(JsonTags.SLA_SUMMARY_APP_TYPE, appType);
json.put(JsonTags.SLA_SUMMARY_USER, user);
json.put(JsonTags.SLA_SUMMARY_NOMINAL_TIME, getTimeOnTimeZone(nominalTimeTS, timeZoneId));
if (expectedStartTS != null) {
json.put(JsonTags.SLA_SUMMARY_EXPECTED_START, getTimeOnTimeZone(expectedStartTS, timeZoneId));
} else {
json.put(JsonTags.SLA_SUMMARY_EXPECTED_START, null);
}
if (actualStartTS != null) {
json.put(JsonTags.SLA_SUMMARY_ACTUAL_START, getTimeOnTimeZone(actualStartTS, timeZoneId));
}
else {
json.put(JsonTags.SLA_SUMMARY_ACTUAL_START, null);
}
Long startDelay = eventMap.get(EventStatus.START_MET) != null ? eventMap.get(EventStatus.START_MET) : eventMap
.get(EventStatus.START_MISS);
if (startDelay != null) {
json.put(JsonTags.SLA_SUMMARY_START_DELAY, startDelay);
}
if (expectedEndTS != null ) {
json.put(JsonTags.SLA_SUMMARY_EXPECTED_END, getTimeOnTimeZone(expectedEndTS,timeZoneId));
} else {
json.put(JsonTags.SLA_SUMMARY_ACTUAL_END, null);
}
if (actualEndTS != null) {
json.put(JsonTags.SLA_SUMMARY_ACTUAL_END, getTimeOnTimeZone(actualEndTS,timeZoneId));
}
else {
json.put(JsonTags.SLA_SUMMARY_ACTUAL_END, null);
}
Long endDelay = eventMap.get(EventStatus.END_MET) != null ? eventMap.get(EventStatus.END_MET) : eventMap
.get(EventStatus.END_MISS);
if (endDelay != null) {
json.put(JsonTags.SLA_SUMMARY_END_DELAY, endDelay);
}
json.put(JsonTags.SLA_SUMMARY_EXPECTED_DURATION, expectedDuration);
if (actualDuration == -1 && expectedDuration != -1 && actualStartTS != null) {
long currentDur = new Date().getTime() - actualStartTS.getTime();
json.put(JsonTags.SLA_SUMMARY_ACTUAL_DURATION, currentDur);
}
else {
json.put(JsonTags.SLA_SUMMARY_ACTUAL_DURATION, actualDuration);
}
Long durationDelay = eventMap.get(EventStatus.DURATION_MET) != null ? eventMap.get(EventStatus.DURATION_MET)
: eventMap.get(EventStatus.DURATION_MISS);
if (durationDelay != null) {
json.put(JsonTags.SLA_SUMMARY_DURATION_DELAY, durationDelay / (1000 * 60));
}
json.put(JsonTags.SLA_SUMMARY_JOB_STATUS, jobStatus);
json.put(JsonTags.SLA_SUMMARY_SLA_STATUS, slaStatus);
json.put(JsonTags.SLA_SUMMARY_EVENT_STATUS, eventStatusStr.toString());
json.put(JsonTags.SLA_SUMMARY_LAST_MODIFIED, getTimeOnTimeZone(lastModifiedTS, timeZoneId));
return json;
}
private Object getTimeOnTimeZone(Timestamp ts, String timeZoneId) {
Object ret = null;
if(timeZoneId == null) {
ret = new Long(String.valueOf(ts.getTime()));
} else {
ret = JsonUtils.formatDateRfc822(ts, timeZoneId);
}
return ret;
}
private Map<EventStatus, Long> calculateEventStatus() {
Map<EventStatus, Long> events = new HashMap<EventStatus, Long>();
if (expectedStartTS != null) {
if (actualStartTS != null) {
long diff = (actualStartTS.getTime() - expectedStartTS.getTime()) / (1000 * 60);
if (diff > 0) {
events.put(EventStatus.START_MISS, diff);
}
else {
events.put(EventStatus.START_MET, diff);
}
}
else {
long diff = (new Date().getTime() - expectedStartTS.getTime()) / (1000 * 60);
if (diff > 0) {
events.put(EventStatus.START_MISS, diff);
}
}
}
if (expectedDuration != -1) {
if (actualDuration != -1) {
long diff = actualDuration - expectedDuration;
if (diff > 0) {
events.put(EventStatus.DURATION_MISS, diff);
}
else {
events.put(EventStatus.DURATION_MET, diff);
}
}
else {
if (actualStartTS != null) {
long currentDur = new Date().getTime() - actualStartTS.getTime();
if (expectedDuration < currentDur) {
events.put(EventStatus.DURATION_MISS, currentDur - expectedDuration);
}
}
}
}
if (expectedEndTS != null) {
if (actualEndTS != null) {
long diff = (actualEndTS.getTime() - expectedEndTS.getTime()) / (1000 * 60);
if (diff > 0) {
events.put(EventStatus.END_MISS, diff);
}
else {
events.put(EventStatus.END_MET, diff);
}
}
else {
long diff = (new Date().getTime() - expectedEndTS.getTime()) / (1000 * 60);
if (diff > 0) {
events.put(EventStatus.END_MISS, diff);
}
}
}
return events;
}
/**
* Convert a sla summary list into a json object.
*
* @param slaSummaryList sla summary list.
* @param timeZoneId time zone to use for dates in the JSON array.
* @return the corresponding JSON object.
*/
@SuppressWarnings("unchecked")
public static JSONObject toJSONObject(List<? extends SLASummaryBean> slaSummaryList, String timeZoneId) {
JSONObject json = new JSONObject();
JSONArray array = new JSONArray();
if (slaSummaryList != null) {
for (SLASummaryBean summary : slaSummaryList) {
array.add(summary.toJSONObject(timeZoneId));
}
}
json.put(JsonTags.SLA_SUMMARY_LIST, array);
return json;
}
@SuppressWarnings("unchecked")
public static JSONObject toJSONObject(List<? extends SLASummaryBean> slaSummaryList,
Map<String, Map<String, String>> slaConfigMap, String timeZoneId) {
JSONObject json = new JSONObject();
JSONArray array = new JSONArray();
if (slaSummaryList != null) {
for (SLASummaryBean summary : slaSummaryList) {
JSONObject slaJson = summary.toJSONObject(timeZoneId);
String slaAlertStatus = "";
if (slaConfigMap.containsKey(summary.getId())) {
slaAlertStatus = slaConfigMap.get(summary.getId()).containsKey(OozieClient.SLA_DISABLE_ALERT) ? "Disabled"
: "Enabled";
}
slaJson.put(JsonTags.SLA_ALERT_STATUS, slaAlertStatus);
array.add(slaJson);
}
}
json.put(JsonTags.SLA_SUMMARY_LIST, array);
return json;
}
}