This project has retired. For details please refer to its Attic page.
Source code
001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *      http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.oozie.sla;
020
021import java.sql.Timestamp;
022import java.util.Date;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import javax.persistence.Basic;
028import javax.persistence.Column;
029import javax.persistence.Entity;
030import javax.persistence.Id;
031import javax.persistence.NamedQueries;
032import javax.persistence.NamedQuery;
033import javax.persistence.Table;
034
035import org.apache.oozie.AppType;
036import org.apache.oozie.client.OozieClient;
037import org.apache.oozie.client.event.SLAEvent;
038import org.apache.oozie.client.event.SLAEvent.EventStatus;
039import org.apache.oozie.client.rest.JsonBean;
040import org.apache.oozie.client.rest.JsonTags;
041import org.apache.oozie.client.rest.JsonUtils;
042import org.apache.oozie.util.DateUtils;
043import org.apache.openjpa.persistence.jdbc.Index;
044import org.json.simple.JSONArray;
045import org.json.simple.JSONObject;
046
047@Entity
048@Table(name = "SLA_SUMMARY")
049@NamedQueries({
050
051 @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"),
052
053 @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"),
054
055 @NamedQuery(name = "UPDATE_SLA_SUMMARY_FOR_ACTUAL_TIMES", query = "update SLASummaryBean w set w.eventProcessed = :eventProcessed, w.actualStartTS = :actualStartTS, w.actualEndTS = :actualEndTS, w.actualEndTS = :actualEndTS, w.actualDuration = :actualDuration, w.lastModifiedTS = :lastModifiedTS where w.jobId = :jobId"),
056
057 @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"),
058
059 @NamedQuery(name = "UPDATE_SLA_SUMMARY_EVENTPROCESSED", query = "update SLASummaryBean w set w.eventProcessed = :eventProcessed where w.jobId = :jobId"),
060
061 @NamedQuery(name = "UPDATE_SLA_SUMMARY_LAST_MODIFIED_TIME", query = "update SLASummaryBean w set w.lastModifiedTS = :lastModifiedTS where w.jobId = :jobId"),
062
063 @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"),
064
065 @NamedQuery(name = "GET_SLA_SUMMARY", query = "select OBJECT(w) from SLASummaryBean w where w.jobId = :id"),
066
067 @NamedQuery(name = "GET_SLA_SUMMARY_RECORDS_RESTART", query = "select OBJECT(w) from SLASummaryBean w where w.eventProcessed <= 7 AND w.lastModifiedTS >= :lastModifiedTime"),
068
069 @NamedQuery(name = "GET_SLA_SUMMARY_EVENTPROCESSED", query = "select w.eventProcessed from SLASummaryBean w where w.jobId = :id"),
070
071 @NamedQuery(name = "GET_SLA_SUMMARY_EVENTPROCESSED_LAST_MODIFIED", query = "select w.eventProcessed, w.lastModifiedTS from SLASummaryBean w where w.jobId = :id")
072
073})
074
075/**
076 * Class to store all the SLA related details (summary) per job
077 */
078public class SLASummaryBean implements JsonBean {
079
080    @Id
081    @Basic
082    @Column(name = "job_id")
083    private String jobId;
084
085    @Basic
086    @Index
087    @Column(name = "parent_id")
088    private String parentId;
089
090    @Basic
091    @Index
092    @Column(name = "app_name")
093    private String appName;
094
095    @Basic
096    @Column(name = "app_type")
097    private String appType;
098
099    @Basic
100    @Column(name = "user_name")
101    private String user;
102
103    @Basic
104    @Column(name = "created_time")
105    private Timestamp createdTimeTS = null;
106
107    @Basic
108    @Index
109    @Column(name = "nominal_time")
110    private Timestamp nominalTimeTS = null;
111
112    @Basic
113    @Column(name = "expected_start")
114    private Timestamp expectedStartTS = null;
115
116    @Basic
117    @Column(name = "expected_end")
118    private Timestamp expectedEndTS = null;
119
120    @Basic
121    @Column(name = "expected_duration")
122    private long expectedDuration = -1;
123
124    @Basic
125    @Column(name = "actual_start")
126    private Timestamp actualStartTS = null;
127
128    @Basic
129    @Column(name = "actual_end")
130    private Timestamp actualEndTS = null;
131
132    @Basic
133    @Column(name = "actual_duration")
134    private long actualDuration = -1;
135
136    @Basic
137    @Column(name = "job_status")
138    private String jobStatus;
139
140    @Basic
141    @Column(name = "event_status")
142    private String eventStatus;
143
144    @Basic
145    @Column(name = "sla_status")
146    private String slaStatus;
147
148    @Basic
149    @Index
150    @Column(name = "event_processed")
151    private byte eventProcessed = 0;
152
153    @Basic
154    @Index
155    @Column(name = "last_modified")
156    private Timestamp lastModifiedTS = null;
157
158    public SLASummaryBean() {
159    }
160
161    public SLASummaryBean(SLACalcStatus slaCalc) {
162        SLARegistrationBean reg = slaCalc.getSLARegistrationBean();
163        setId(slaCalc.getId());
164        setAppName(reg.getAppName());
165        setAppType(reg.getAppType());
166        setNominalTime(reg.getNominalTime());
167        setExpectedStart(reg.getExpectedStart());
168        setExpectedEnd(reg.getExpectedEnd());
169        setExpectedDuration(reg.getExpectedDuration());
170        setJobStatus(slaCalc.getJobStatus());
171        setSLAStatus(slaCalc.getSLAStatus());
172        setEventStatus(slaCalc.getEventStatus());
173        setLastModifiedTime(slaCalc.getLastModifiedTime());
174        setUser(reg.getUser());
175        setParentId(reg.getParentId());
176        setEventProcessed(slaCalc.getEventProcessed());
177        setActualDuration(slaCalc.getActualDuration());
178        setActualEnd(slaCalc.getActualEnd());
179        setActualStart(slaCalc.getActualStart());
180    }
181
182    public String getId() {
183        return jobId;
184    }
185
186    public void setId(String jobId) {
187        this.jobId = jobId;
188    }
189
190    public String getParentId() {
191        return parentId;
192    }
193
194    public void setParentId(String parentId) {
195        this.parentId = parentId;
196    }
197
198    public Timestamp getCreatedTimestamp() {
199        return createdTimeTS;
200    }
201
202    public void setCreatedTimestamp(Timestamp createdTime) {
203        this.createdTimeTS = createdTime;
204    }
205
206    public Date getCreatedTime() {
207        return DateUtils.toDate(createdTimeTS);
208    }
209
210    public void setCreatedTime(Date createdTime) {
211        this.createdTimeTS = DateUtils.convertDateToTimestamp(createdTime);
212    }
213
214    public Date getNominalTime() {
215        return DateUtils.toDate(nominalTimeTS);
216    }
217
218    public Timestamp getNominalTimestamp() {
219        return this.nominalTimeTS;
220    }
221
222    public void setNominalTime(Date nominalTime) {
223        this.nominalTimeTS = DateUtils.convertDateToTimestamp(nominalTime);
224    }
225
226
227    public Date getExpectedStart() {
228        return DateUtils.toDate(expectedStartTS);
229    }
230
231    public Timestamp getExpectedStartTimestamp() {
232        return this.expectedStartTS;
233    }
234
235    public void setExpectedStart(Date expectedStart) {
236        this.expectedStartTS = DateUtils.convertDateToTimestamp(expectedStart);
237    }
238
239    public Date getExpectedEnd() {
240        return DateUtils.toDate(expectedEndTS);
241    }
242
243    public Timestamp getExpectedEndTimestamp() {
244        return this.expectedEndTS;
245    }
246    public void setExpectedEnd(Date expectedEnd) {
247        this.expectedEndTS = DateUtils.convertDateToTimestamp(expectedEnd);
248    }
249
250    public long getExpectedDuration() {
251        return expectedDuration;
252    }
253
254    public void setExpectedDuration(long expectedDuration) {
255        this.expectedDuration = expectedDuration;
256    }
257
258    public Date getActualStart() {
259        return DateUtils.toDate(actualStartTS);
260    }
261
262    public Timestamp getActualStartTimestamp() {
263        return this.actualStartTS;
264    }
265
266    public void setActualStart(Date actualStart) {
267        this.actualStartTS = DateUtils.convertDateToTimestamp(actualStart);
268    }
269
270    public Date getActualEnd() {
271        return DateUtils.toDate(actualEndTS);
272    }
273
274    public Timestamp getActualEndTimestamp() {
275        return this.actualEndTS;
276    }
277
278    public void setActualEnd(Date actualEnd) {
279        this.actualEndTS = DateUtils.convertDateToTimestamp(actualEnd);
280    }
281
282    public long getActualDuration() {
283        return actualDuration;
284    }
285
286    public void setActualDuration(long actualDuration) {
287        this.actualDuration = actualDuration;
288    }
289
290    public String getJobStatus() {
291        return jobStatus;
292    }
293
294    public void setJobStatus(String status) {
295        this.jobStatus = status;
296    }
297
298    public SLAEvent.EventStatus getEventStatus() {
299        return (eventStatus != null ? SLAEvent.EventStatus.valueOf(eventStatus) : null);
300    }
301
302    public void setEventStatus(SLAEvent.EventStatus eventStatus) {
303        this.eventStatus = (eventStatus != null ? eventStatus.name() : null);
304    }
305
306    public SLAEvent.SLAStatus getSLAStatus() {
307        return (slaStatus != null ? SLAEvent.SLAStatus.valueOf(slaStatus) : null);
308    }
309
310    public String getSLAStatusString() {
311        return slaStatus;
312    }
313
314    public String getEventStatusString() {
315        return eventStatus;
316    }
317
318    public void setSLAStatus(SLAEvent.SLAStatus stage) {
319        this.slaStatus = (stage != null ? stage.name() : null);
320    }
321
322    public String getUser() {
323        return user;
324    }
325
326    public void setUser(String user) {
327        this.user = user;
328    }
329
330    public String getAppName() {
331        return appName;
332    }
333
334    public void setAppName(String appName) {
335        this.appName = appName;
336    }
337
338    public AppType getAppType() {
339        return AppType.valueOf(appType);
340    }
341
342    public void setAppType(AppType appType) {
343        this.appType = appType.toString();
344    }
345
346    public byte getEventProcessed() {
347        return eventProcessed;
348    }
349
350    public void setEventProcessed(int eventProcessed) {
351        this.eventProcessed = (byte)eventProcessed;
352    }
353
354    public Date getLastModifiedTime() {
355        return DateUtils.toDate(lastModifiedTS);
356    }
357
358    public Timestamp getLastModifiedTimestamp() {
359        return this.lastModifiedTS;
360    }
361
362    public void setLastModifiedTime(Date lastModified) {
363        this.lastModifiedTS = DateUtils.convertDateToTimestamp(lastModified);
364    }
365
366    @Override
367    public JSONObject toJSONObject() {
368        return toJSONObject(null);
369    }
370
371    @Override
372    @SuppressWarnings("unchecked")
373    public JSONObject toJSONObject(String timeZoneId) {
374        JSONObject json = new JSONObject();
375        Map<EventStatus,Long> eventMap = calculateEventStatus();
376        StringBuilder eventStatusStr = new StringBuilder();
377        boolean first = true;
378        for(EventStatus e: eventMap.keySet()) {
379            if(!first) {
380                eventStatusStr.append(",");
381            }
382            eventStatusStr.append(e.toString());
383            first = false;
384        }
385        json.put(JsonTags.SLA_SUMMARY_ID, jobId);
386        if (parentId != null) {
387            json.put(JsonTags.SLA_SUMMARY_PARENT_ID, parentId);
388        }
389        json.put(JsonTags.SLA_SUMMARY_APP_NAME, appName);
390        json.put(JsonTags.SLA_SUMMARY_APP_TYPE, appType);
391        json.put(JsonTags.SLA_SUMMARY_USER, user);
392        json.put(JsonTags.SLA_SUMMARY_NOMINAL_TIME, getTimeOnTimeZone(nominalTimeTS, timeZoneId));
393        if (expectedStartTS != null) {
394            json.put(JsonTags.SLA_SUMMARY_EXPECTED_START, getTimeOnTimeZone(expectedStartTS, timeZoneId));
395        } else {
396            json.put(JsonTags.SLA_SUMMARY_EXPECTED_START, null);
397        }
398
399        if (actualStartTS != null) {
400            json.put(JsonTags.SLA_SUMMARY_ACTUAL_START, getTimeOnTimeZone(actualStartTS, timeZoneId));
401        }
402        else {
403            json.put(JsonTags.SLA_SUMMARY_ACTUAL_START, null);
404        }
405        Long startDelay = eventMap.get(EventStatus.START_MET) != null ? eventMap.get(EventStatus.START_MET) : eventMap
406                .get(EventStatus.START_MISS);
407        if (startDelay != null) {
408            json.put(JsonTags.SLA_SUMMARY_START_DELAY, startDelay);
409        }
410        if (expectedEndTS != null ) {
411            json.put(JsonTags.SLA_SUMMARY_EXPECTED_END, getTimeOnTimeZone(expectedEndTS,timeZoneId));
412        } else {
413            json.put(JsonTags.SLA_SUMMARY_ACTUAL_END, null);
414        }
415        if (actualEndTS != null) {
416            json.put(JsonTags.SLA_SUMMARY_ACTUAL_END, getTimeOnTimeZone(actualEndTS,timeZoneId));
417        }
418        else {
419            json.put(JsonTags.SLA_SUMMARY_ACTUAL_END, null);
420        }
421        Long endDelay = eventMap.get(EventStatus.END_MET) != null ? eventMap.get(EventStatus.END_MET) : eventMap
422                .get(EventStatus.END_MISS);
423        if (endDelay != null) {
424            json.put(JsonTags.SLA_SUMMARY_END_DELAY, endDelay);
425        }
426        json.put(JsonTags.SLA_SUMMARY_EXPECTED_DURATION, expectedDuration);
427        if (actualDuration == -1 && expectedDuration != -1 && actualStartTS != null) {
428            long currentDur = (new Date().getTime() - actualStartTS.getTime()) / (1000 * 60);
429            json.put(JsonTags.SLA_SUMMARY_ACTUAL_DURATION, currentDur);
430        }
431        else {
432            json.put(JsonTags.SLA_SUMMARY_ACTUAL_DURATION, actualDuration);
433        }
434        Long durationDelay = eventMap.get(EventStatus.DURATION_MET) != null ? eventMap.get(EventStatus.DURATION_MET)
435                : eventMap.get(EventStatus.DURATION_MISS);
436        if (durationDelay != null) {
437            json.put(JsonTags.SLA_SUMMARY_DURATION_DELAY, durationDelay);
438        }
439        json.put(JsonTags.SLA_SUMMARY_JOB_STATUS, jobStatus);
440        json.put(JsonTags.SLA_SUMMARY_SLA_STATUS, slaStatus);
441        json.put(JsonTags.SLA_SUMMARY_EVENT_STATUS, eventStatusStr.toString());
442        json.put(JsonTags.SLA_SUMMARY_LAST_MODIFIED, getTimeOnTimeZone(lastModifiedTS, timeZoneId));
443        return json;
444    }
445
446    private Object getTimeOnTimeZone(Timestamp ts, String timeZoneId) {
447        Object ret = null;
448        if(timeZoneId == null) {
449            ret = new Long(String.valueOf(ts.getTime()));
450        } else {
451            ret = JsonUtils.formatDateRfc822(ts, timeZoneId);
452        }
453        return ret;
454    }
455
456    private Map<EventStatus, Long> calculateEventStatus() {
457        Map<EventStatus, Long> events = new HashMap<EventStatus, Long>();
458        if (expectedStartTS != null) {
459            if (actualStartTS != null) {
460                long diff = (actualStartTS.getTime() - expectedStartTS.getTime()) / (1000 * 60);
461                if (diff > 0) {
462                    events.put(EventStatus.START_MISS, diff);
463                }
464                else {
465                    events.put(EventStatus.START_MET, diff);
466                }
467            }
468            else {
469                long diff = (new Date().getTime() - expectedStartTS.getTime()) / (1000 * 60);
470                if (diff > 0) {
471                    events.put(EventStatus.START_MISS, diff);
472                }
473            }
474        }
475        if (expectedDuration != -1) {
476            if (actualDuration != -1) {
477                long diff = actualDuration - expectedDuration;
478                if (diff > 0) {
479                    events.put(EventStatus.DURATION_MISS, diff);
480                }
481                else {
482                    events.put(EventStatus.DURATION_MET, diff);
483                }
484            }
485            else {
486                if (actualStartTS != null) {
487                    long currentDur = (new Date().getTime() - actualStartTS.getTime()) / (1000 * 60);
488                    if (expectedDuration < currentDur) {
489                        events.put(EventStatus.DURATION_MISS, (currentDur - expectedDuration));
490                    }
491                }
492            }
493        }
494        if (expectedEndTS != null) {
495            if (actualEndTS != null) {
496                long diff = (actualEndTS.getTime() - expectedEndTS.getTime()) / (1000 * 60);
497                if (diff > 0) {
498                    events.put(EventStatus.END_MISS, diff);
499                }
500                else {
501                    events.put(EventStatus.END_MET, diff);
502                }
503            }
504            else {
505                long diff = (new Date().getTime() - expectedEndTS.getTime()) / (1000 * 60);
506                if (diff > 0) {
507                    events.put(EventStatus.END_MISS, diff);
508                }
509            }
510        }
511        return events;
512    }
513    /**
514     * Convert a sla summary list into a json object.
515     *
516     * @param slaSummaryList sla summary list.
517     * @param timeZoneId time zone to use for dates in the JSON array.
518     * @return the corresponding JSON object.
519     */
520    @SuppressWarnings("unchecked")
521    public static JSONObject toJSONObject(List<? extends SLASummaryBean> slaSummaryList, String timeZoneId) {
522        JSONObject json = new JSONObject();
523        JSONArray array = new JSONArray();
524        if (slaSummaryList != null) {
525            for (SLASummaryBean summary : slaSummaryList) {
526                array.add(summary.toJSONObject(timeZoneId));
527            }
528        }
529        json.put(JsonTags.SLA_SUMMARY_LIST, array);
530        return json;
531    }
532
533    @SuppressWarnings("unchecked")
534    public static JSONObject toJSONObject(List<? extends SLASummaryBean> slaSummaryList,
535            Map<String, Map<String, String>> slaConfigMap, String timeZoneId) {
536        JSONObject json = new JSONObject();
537        JSONArray array = new JSONArray();
538        if (slaSummaryList != null) {
539            for (SLASummaryBean summary : slaSummaryList) {
540                JSONObject slaJson = summary.toJSONObject(timeZoneId);
541                String slaAlertStatus = "";
542                if (slaConfigMap.containsKey(summary.getId())) {
543                    slaAlertStatus = slaConfigMap.get(summary.getId()).containsKey(OozieClient.SLA_DISABLE_ALERT) ? "Disabled"
544                            : "Enabled";
545                }
546                slaJson.put(JsonTags.SLA_ALERT_STATUS, slaAlertStatus);
547                array.add(slaJson);
548            }
549        }
550        json.put(JsonTags.SLA_SUMMARY_LIST, array);
551        return json;
552    }
553}