| /** |
| * 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.text.ParseException; |
| import java.util.Date; |
| |
| import org.apache.oozie.AppType; |
| import org.apache.oozie.ErrorCode; |
| import org.apache.oozie.client.OozieClient; |
| import org.apache.oozie.client.event.SLAEvent.EventStatus; |
| import org.apache.oozie.command.CommandException; |
| import org.apache.oozie.executor.jpa.JPAExecutorException; |
| import org.apache.oozie.executor.jpa.SLARegistrationQueryExecutor; |
| import org.apache.oozie.executor.jpa.SLARegistrationQueryExecutor.SLARegQuery; |
| import org.apache.oozie.service.ServiceException; |
| import org.apache.oozie.service.Services; |
| import org.apache.oozie.sla.service.SLAService; |
| import org.apache.oozie.util.DateUtils; |
| import org.apache.oozie.util.XLog; |
| import org.apache.oozie.util.XmlUtils; |
| import org.jdom.Element; |
| |
| public class SLAOperations { |
| |
| public static final String NOMINAL_TIME = "nominal-time"; |
| public static final String SHOULD_START = "should-start"; |
| public static final String SHOULD_END = "should-end"; |
| public static final String MAX_DURATION = "max-duration"; |
| public static final String ALERT_EVENTS = "alert-events"; |
| public static final String ALL_VALUE = "ALL"; |
| |
| |
| static public XLog LOG = XLog.getLog(SLAOperations.class); |
| |
| |
| public static SLARegistrationBean createSlaRegistrationEvent(Element eSla, String jobId, String parentId, |
| AppType appType, String user, String appName, XLog log, boolean rerun, boolean disableAlert) |
| throws CommandException { |
| if (eSla == null || !SLAService.isEnabled()) { |
| log.debug("Not registering SLA for job [{0}]. Sla-Xml null OR SLAService not enabled", jobId); |
| return null; |
| } |
| SLARegistrationBean sla = new SLARegistrationBean(); |
| |
| // Setting nominal time |
| String strNominalTime = getTagElement(eSla, NOMINAL_TIME); |
| Date nominalTime = setNominalTime(strNominalTime, sla); |
| |
| // Setting expected start time |
| String strExpectedStart = getTagElement(eSla, SHOULD_START); |
| setExpectedStart(strExpectedStart, nominalTime, sla); |
| |
| // Setting expected end time |
| String strExpectedEnd = getTagElement(eSla, SHOULD_END); |
| setExpectedEnd(strExpectedEnd, nominalTime, sla); |
| |
| // Setting expected duration in milliseconds |
| String expectedDurationStr = getTagElement(eSla, MAX_DURATION); |
| setExpectedDuration(expectedDurationStr, sla); |
| |
| // Parse desired alert-types i.e. start-miss, end-miss, start-met etc.. |
| String alertEvents = getTagElement(eSla, ALERT_EVENTS); |
| if (alertEvents != null) { |
| String events[] = alertEvents.split(","); |
| StringBuilder alertsStr = new StringBuilder(); |
| for (int i = 0; i < events.length; i++) { |
| String event = events[i].trim().toUpperCase(); |
| try { |
| EventStatus.valueOf(event); |
| } |
| catch (IllegalArgumentException iae) { |
| XLog.getLog(SLAService.class).warn( |
| "Invalid value: [" + event + "]" + " for SLA Alert-event. Should be one of " |
| + EventStatus.values() + ". Setting it to default [" + EventStatus.END_MISS.name() |
| + "]"); |
| event = EventStatus.END_MISS.name(); |
| } |
| alertsStr.append(event).append(","); |
| } |
| sla.setAlertEvents(alertsStr.toString().substring(0, alertsStr.lastIndexOf(","))); |
| } |
| |
| // Other sla config |
| sla.setNotificationMsg(getTagElement(eSla, "notification-msg")); |
| sla.setAlertContact(getTagElement(eSla, "alert-contact")); |
| sla.setUpstreamApps(getTagElement(eSla, "upstream-apps")); |
| |
| //disable Alert flag in slaConfig |
| if (disableAlert) { |
| sla.addToSLAConfigMap(OozieClient.SLA_DISABLE_ALERT, Boolean.toString(disableAlert)); |
| } |
| // Oozie defined |
| sla.setId(jobId); |
| sla.setAppType(appType); |
| sla.setAppName(appName); |
| sla.setUser(user); |
| sla.setParentId(parentId); |
| |
| SLAService slaService = Services.get().get(SLAService.class); |
| try { |
| if (!rerun) { |
| slaService.addRegistrationEvent(sla); |
| } |
| else { |
| slaService.updateRegistrationEvent(sla); |
| } |
| } |
| catch (ServiceException e) { |
| throw new CommandException(ErrorCode.E1007, " id " + jobId, e.getMessage(), e); |
| } |
| |
| log.debug("Job [{0}] reg for SLA. Size of Sla Xml = [{1}]", jobId, XmlUtils.prettyPrint(eSla).toString().length()); |
| return sla; |
| } |
| |
| public static Date setNominalTime(String strNominalTime, SLARegistrationBean sla) throws CommandException { |
| if (strNominalTime == null || strNominalTime.length() == 0) { |
| return sla.getNominalTime(); |
| } |
| Date nominalTime; |
| try { |
| nominalTime = DateUtils.parseDateOozieTZ(strNominalTime); |
| sla.setNominalTime(nominalTime); |
| } |
| catch (ParseException pex) { |
| throw new CommandException(ErrorCode.E0302, strNominalTime, pex); |
| } |
| return nominalTime; |
| } |
| |
| public static void setExpectedStart(String strExpectedStart, Date nominalTime, SLARegistrationBean sla) |
| throws CommandException { |
| if (strExpectedStart != null) { |
| float expectedStart = Float.parseFloat(strExpectedStart); |
| if (expectedStart < 0) { |
| throw new CommandException(ErrorCode.E0302, strExpectedStart, "for SLA Expected start time"); |
| } |
| else { |
| Date expectedStartTime = new Date(nominalTime.getTime() + (long) (expectedStart * 60 * 1000)); |
| sla.setExpectedStart(expectedStartTime); |
| LOG.debug("Setting expected start to " + expectedStartTime + " for job " + sla.getId()); |
| } |
| } |
| } |
| |
| public static void setExpectedEnd(String strExpectedEnd, Date nominalTime, SLARegistrationBean sla) |
| throws CommandException { |
| if (strExpectedEnd != null) { |
| float expectedEnd = Float.parseFloat(strExpectedEnd); |
| if (expectedEnd < 0) { |
| throw new CommandException(ErrorCode.E0302, strExpectedEnd, "for SLA Expected end time"); |
| } |
| else { |
| Date expectedEndTime = new Date(nominalTime.getTime() + (long) (expectedEnd * 60 * 1000)); |
| sla.setExpectedEnd(expectedEndTime); |
| LOG.debug("Setting expected end to " + expectedEndTime + " for job " + sla.getId()); |
| |
| } |
| } |
| } |
| |
| public static void setExpectedDuration(String expectedDurationStr, SLARegistrationBean sla) { |
| if (expectedDurationStr != null && expectedDurationStr.length() > 0) { |
| float expectedDuration = Float.parseFloat(expectedDurationStr); |
| if (expectedDuration > 0) { |
| long duration = (long) (expectedDuration * 60 * 1000); |
| LOG.debug("Setting expected duration to " + duration + " for job " + sla.getId()); |
| sla.setExpectedDuration(duration); |
| } |
| } |
| else if (sla.getExpectedStart() != null) { |
| long duration = sla.getExpectedEnd().getTime() - sla.getExpectedStart().getTime(); |
| LOG.debug("Setting expected duration to " + duration + " for job " + sla.getId()); |
| sla.setExpectedDuration(sla.getExpectedEnd().getTime() - sla.getExpectedStart().getTime()); |
| } |
| } |
| |
| /** |
| * Retrieve registration event |
| * @param jobId the jobId |
| * @throws CommandException update failure |
| * @throws JPAExecutorException if JPA related issue occurs |
| */ |
| public static void updateRegistrationEvent(String jobId) throws CommandException, JPAExecutorException { |
| SLAService slaService = Services.get().get(SLAService.class); |
| try { |
| SLARegistrationBean reg = SLARegistrationQueryExecutor.getInstance().get(SLARegQuery.GET_SLA_REG_ALL, jobId); |
| if (reg != null) { //handle coord rerun with different config without sla |
| slaService.updateRegistrationEvent(reg); |
| } |
| } |
| catch (ServiceException e) { |
| throw new CommandException(ErrorCode.E1007, " id " + jobId, e.getMessage(), e); |
| } |
| |
| } |
| |
| /* |
| * parentId null |
| */ |
| public static SLARegistrationBean createSlaRegistrationEvent(Element eSla, String jobId, AppType appType, |
| String user, String appName, XLog log) throws CommandException { |
| return createSlaRegistrationEvent(eSla, jobId, null, appType, user, appName, log, false); |
| } |
| |
| /* |
| * appName null |
| */ |
| public static SLARegistrationBean createSlaRegistrationEvent(Element eSla, String jobId, String parentId, |
| AppType appType, String user, XLog log) throws CommandException { |
| return createSlaRegistrationEvent(eSla, jobId, parentId, appType, user, null, log, false); |
| } |
| |
| /* |
| * parentId + appName null |
| */ |
| public static SLARegistrationBean createSlaRegistrationEvent(Element eSla, String jobId, AppType appType, |
| String user, XLog log) throws CommandException { |
| return createSlaRegistrationEvent(eSla, jobId, null, appType, user, null, log, false); |
| } |
| |
| /* |
| * default disableAlert flag |
| */ |
| public static SLARegistrationBean createSlaRegistrationEvent(Element eSla, String jobId, String parentId, |
| AppType appType, String user, String appName, XLog log, boolean rerun) throws CommandException { |
| return createSlaRegistrationEvent(eSla, jobId, null, appType, user, appName, log, rerun, false); |
| } |
| |
| public static String getTagElement(Element elem, String tagName) { |
| if (elem != null && elem.getChild(tagName, elem.getNamespace("sla")) != null) { |
| return elem.getChild(tagName, elem.getNamespace("sla")).getText().trim(); |
| } |
| else { |
| return null; |
| } |
| } |
| |
| } |