/** * Licensed 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.seyren.core.service.notification; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ifountain.opsgenie.client.OpsGenieClient; import com.ifountain.opsgenie.client.OpsGenieClientException; import com.ifountain.opsgenie.client.model.alert.CloseAlertRequest; import com.ifountain.opsgenie.client.model.alert.CloseAlertResponse; import com.ifountain.opsgenie.client.model.alert.CreateAlertRequest; import com.ifountain.opsgenie.client.model.alert.CreateAlertResponse; import com.ifountain.opsgenie.client.model.alert.ListAlertsRequest; import com.ifountain.opsgenie.client.model.alert.ListAlertsResponse; import com.seyren.core.domain.Alert; import com.seyren.core.domain.AlertType; import com.seyren.core.domain.Check; import com.seyren.core.domain.Subscription; import com.seyren.core.domain.SubscriptionType; import com.seyren.core.exception.NotificationFailedException; import com.seyren.core.util.config.SeyrenConfig; @Named public class OpsGenieNotificationService implements NotificationService { private static final Logger LOGGER = LoggerFactory.getLogger(OpsGenieNotificationService.class); private SeyrenConfig config; @Inject public OpsGenieNotificationService(SeyrenConfig config) { this.config = config; } @Override public void sendNotification(Check check, Subscription subscription, List<Alert> alerts) throws NotificationFailedException { OpsGenieClient client = new OpsGenieClient(); try { String apiKey = subscription.getTarget(); if (check.getState() == AlertType.WARN || check.getState() == AlertType.ERROR) { openAlert(client, apiKey, check); } else if (check.getState() == AlertType.OK) { closeOpenAlerts(client, apiKey, check); } } catch (OpsGenieClientException e) { LOGGER.warn( "Did not send notification to OpsGenie for check in state: {}", check.getState(), e); } catch (IOException e) { LOGGER.warn( "Did not send notification to OpsGenie for check in state: {}", check.getState(), e); } catch (ParseException e) { LOGGER.warn( "Did not send notification to OpsGenie for check in state: {}", check.getState(), e); } } private List<com.ifountain.opsgenie.client.model.beans.Alert> getOpenAlerts(OpsGenieClient client, String apiKey, Check check) throws OpsGenieClientException, IOException, ParseException { List<com.ifountain.opsgenie.client.model.beans.Alert> openMatchingAlerts = new ArrayList<com.ifountain.opsgenie.client.model.beans.Alert>(); ListAlertsRequest request = new ListAlertsRequest(); request.setApiKey(apiKey); ListAlertsResponse response = client.alert().listAlerts(request); List<com.ifountain.opsgenie.client.model.beans.Alert> alerts = response.getAlerts(); //There could be multiple open alerts for a given check for (com.ifountain.opsgenie.client.model.beans.Alert alert: alerts) { if (String.valueOf(alert.getMessage()).equals(getMessage(check)) && alert.getStatus() == com.ifountain.opsgenie.client.model.beans.Alert.Status.open) { openMatchingAlerts.add(alert); } } return openMatchingAlerts; } private void closeOpenAlerts(OpsGenieClient client, String apiKey, Check check) throws OpsGenieClientException, ParseException, IOException{ List<com.ifountain.opsgenie.client.model.beans.Alert> opsAlerts = getOpenAlerts(client, apiKey, check); for(com.ifountain.opsgenie.client.model.beans.Alert alert : opsAlerts) { closeAlert(alert, client,apiKey,check); } } private void closeAlert(com.ifountain.opsgenie.client.model.beans.Alert alert, OpsGenieClient client, String apiKey, Check check) { try { CloseAlertRequest request = new CloseAlertRequest(); request.setId(alert.getId()); request.setApiKey(apiKey); CloseAlertResponse response = client.alert().closeAlert(request); if(!response.isSuccess()) LOGGER.warn("Unable to close alert for check: " + check.getName()); } catch (OpsGenieClientException e) { LOGGER.warn( "Unable to close alert for check: " + check.getName(), check.getState(), e); } catch (IOException e) { LOGGER.warn( "Unable to close alert for check: " + check.getName(), check.getState(), e); } catch (ParseException e) { LOGGER.warn( "Unable to close alert for check: " + check.getName(), check.getState(), e); } } private void openAlert(OpsGenieClient client, String apiKey, Check check) throws OpsGenieClientException, ParseException, IOException{ CreateAlertRequest request = new CreateAlertRequest(); request.setApiKey(apiKey); request.setMessage(getMessage(check)); request.setDetails(getCheckDetails(check)); request.setSource("Seyren"); request.setTeams(config.getOpsGenieTeams()); request.setDescription(String.valueOf(check.getDescription())); CreateAlertResponse response = client.alert().createAlert(request); assert response.isSuccess(); } private String getMessage(Check check) { return "Check " + check.getName(); } private Map<String,String> getCheckDetails(Check check) { Map<String, String> details = new HashMap<String,String>(); details.put("Check State", check.getState().name()); details.put("Target", check.getTarget()); return details; } @Override public boolean canHandle(SubscriptionType subscriptionType) { return subscriptionType == SubscriptionType.OPSGENIE; } }