/** * Copyright 2015 StreamSets Inc. * * Licensed under 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 com.streamsets.datacollector.execution.alerts; import com.google.common.base.Charsets; import com.google.common.io.Resources; import com.streamsets.datacollector.email.EmailException; import com.streamsets.datacollector.email.EmailSender; import com.streamsets.datacollector.execution.PipelineState; import com.streamsets.datacollector.execution.StateEventListener; import com.streamsets.datacollector.main.RuntimeInfo; import com.streamsets.datacollector.runner.PipelineRuntimeException; import com.streamsets.datacollector.util.ContainerError; import com.streamsets.dc.execution.manager.standalone.ThreadUsage; import com.streamsets.pipeline.api.ExecutionMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; public class EmailNotifier implements StateEventListener { private static final Logger LOG = LoggerFactory.getLogger(EmailNotifier.class); private final String pipelineId; private final String pipelineTitle; private final String rev; private final RuntimeInfo runtimeInfo; private final EmailSender emailSender; private final List<String> emails; private final Set<String> pipelineStates; public EmailNotifier( String pipelineId, String pipelineTitle, String rev, RuntimeInfo runtimeInfo, EmailSender emailSender, List<String> emails, Set<String> pipelineStates ) { this.pipelineId = pipelineId; this.pipelineTitle = pipelineTitle; this.rev = rev; this.runtimeInfo = runtimeInfo; this.emailSender = emailSender; this.emails = emails; this.pipelineStates = pipelineStates; } public String getPipelineId() { return pipelineId; } public String getRev() { return rev; } @Override public void onStateChange( PipelineState fromState, PipelineState toState, String toStateJson, ThreadUsage threadUsage, Map<String, String> offset ) throws PipelineRuntimeException { //should not be active in slave mode if(toState.getExecutionMode() != ExecutionMode.SLAVE && pipelineId.equals(toState.getPipelineId())) { if (pipelineStates != null && pipelineStates.contains(toState.getStatus().name())) { //pipeline switched to a terminal state. Send email String emailBody = null; String subject = null; URL url; try { switch (toState.getStatus()) { case START_ERROR: case RUN_ERROR: url = Resources.getResource(EmailConstants.NOTIFY_ERROR_EMAIL_TEMPLATE); emailBody = Resources.toString(url, Charsets.UTF_8); emailBody = emailBody.replace(EmailConstants.DESCRIPTION_KEY, toState.getMessage()); subject = EmailConstants.STREAMSETS_DATA_COLLECTOR_ALERT + pipelineTitle + " - ERROR"; break; case STOPPED: url = Resources.getResource(EmailConstants.PIPELINE_STATE_CHANGE__EMAIL_TEMPLATE); emailBody = Resources.toString(url, Charsets.UTF_8); emailBody = emailBody.replace(EmailConstants.MESSAGE_KEY, "was stopped"); subject = EmailConstants.STREAMSETS_DATA_COLLECTOR_ALERT + pipelineTitle + " - STOPPED"; break; case FINISHED: url = Resources.getResource(EmailConstants.PIPELINE_STATE_CHANGE__EMAIL_TEMPLATE); emailBody = Resources.toString(url, Charsets.UTF_8); emailBody = emailBody.replace(EmailConstants.MESSAGE_KEY, "finished executing"); subject = EmailConstants.STREAMSETS_DATA_COLLECTOR_ALERT + pipelineTitle + " - FINISHED"; break; case RUNNING: url = Resources.getResource(EmailConstants.PIPELINE_STATE_CHANGE__EMAIL_TEMPLATE); emailBody = Resources.toString(url, Charsets.UTF_8); emailBody = emailBody.replace(EmailConstants.MESSAGE_KEY, "started executing"); subject = EmailConstants.STREAMSETS_DATA_COLLECTOR_ALERT + pipelineTitle + " - RUNNING"; break; case DISCONNECTED: url = Resources.getResource(EmailConstants.SDC_STATE_CHANGE__EMAIL_TEMPLATE); emailBody = Resources.toString(url, Charsets.UTF_8); emailBody = emailBody.replace(EmailConstants.MESSAGE_KEY, "was shut down"); subject = EmailConstants.STREAMSETS_DATA_COLLECTOR_ALERT + pipelineTitle + " - DISCONNECTED"; break; case CONNECTING: url = Resources.getResource(EmailConstants.SDC_STATE_CHANGE__EMAIL_TEMPLATE); emailBody = Resources.toString(url, Charsets.UTF_8); emailBody = emailBody.replace(EmailConstants.MESSAGE_KEY, "was started"); subject = EmailConstants.STREAMSETS_DATA_COLLECTOR_ALERT + pipelineTitle + " - CONNECTING"; break; default: throw new IllegalStateException("Unexpected PipelineState " + toState); } } catch (IOException e) { throw new PipelineRuntimeException(ContainerError.CONTAINER_01000, e.toString(), e); } java.text.DateFormat dateTimeFormat = new SimpleDateFormat(EmailConstants.DATE_MASK, Locale.ENGLISH); emailBody = emailBody.replace(EmailConstants.TIME_KEY, dateTimeFormat.format(new Date(toState.getTimeStamp()))) .replace(EmailConstants.PIPELINE_NAME_KEY, pipelineTitle) .replace(EmailConstants.URL_KEY, runtimeInfo.getBaseHttpUrl() + EmailConstants.PIPELINE_URL + toState.getPipelineId().replaceAll(" ", "%20")); try { emailSender.send(emails, subject, emailBody); } catch (EmailException e) { LOG.error("Error sending email : '{}'", e.toString()); } } } } }