net.welen.jmole.protocols.cloudwatch.CloudWatch Maven / Gradle / Ivy
package net.welen.jmole.protocols.cloudwatch;
/*
* #%L
* JMole, https://bitbucket.org/awelen/jmole
* %%
* Copyright (C) 2015 - 2019 Anders Welén, [email protected]
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.management.ObjectName;
import com.amazonaws.services.cloudwatch.AmazonCloudWatch;
import com.amazonaws.services.cloudwatch.AmazonCloudWatchClientBuilder;
import com.amazonaws.services.cloudwatch.model.ComparisonOperator;
import com.amazonaws.services.cloudwatch.model.DeleteAlarmsRequest;
import com.amazonaws.services.cloudwatch.model.Dimension;
import com.amazonaws.services.cloudwatch.model.MetricDatum;
import com.amazonaws.services.cloudwatch.model.PutMetricAlarmRequest;
import com.amazonaws.services.cloudwatch.model.PutMetricDataRequest;
import com.amazonaws.services.cloudwatch.model.Statistic;
import net.welen.jmole.Configuration;
import net.welen.jmole.JMole;
import net.welen.jmole.collector.MBeanCollector;
import net.welen.jmole.finder.MBeanFinder;
import net.welen.jmole.presentation.PresentationInformation;
import net.welen.jmole.protocols.AbstractIntervalProtocol;
import net.welen.jmole.threshold.Threshold;
import net.welen.jmole.threshold.ThresholdValues;
public class CloudWatch extends AbstractIntervalProtocol implements CloudWatchMBean {
private final static java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(CloudWatch.class.getName());
private static final String PROPERTY_CLOUDWATCH_ENABLED = "jmole.protocol.cloudwatch.enabled";
private static final String PROPERTY_CLOUDWATCH_NAMESPACE = "jmole.protocol.cloudwatch.namespace";
private static final String PROPERTY_CLOUDWATCH_INTERVAL = "jmole.protocol.cloudwatch.interval";
private Long interval;
private String namespace;
private JMole jmole;
private AmazonCloudWatch amazonCloudWatch;
private List alarmList = new ArrayList();
@Override
public boolean isEnabled() {
return Boolean.getBoolean(PROPERTY_CLOUDWATCH_ENABLED);
}
@Override
public void startProtocol(JMole jmole) throws Exception {
this.jmole = jmole;
amazonCloudWatch = AmazonCloudWatchClientBuilder.defaultClient();
interval = Long.getLong(PROPERTY_CLOUDWATCH_INTERVAL);
if (interval == null) {
interval = 60000L;
}
namespace = System.getProperty(PROPERTY_CLOUDWATCH_NAMESPACE);
if (namespace == null) {
namespace = "JMole";
}
createAlarms();
super.startProtocol(jmole);
LOG.log(Level.INFO, "JMole CloudWatch protocol started: Interval=" + interval);
}
@Override
public void stopProtocol() throws Exception {
try {
LOG.log(Level.INFO, "Stopping JMole CloudWatch protocol");
super.stopProtocol();
LOG.log(Level.INFO, "JMole CloudWatch protocol stopped");
} finally {
stopAlarms();
}
}
private void createAlarms() {
for (Configuration configuration : jmole.getConfiguration()) {
MBeanFinder finder = configuration.getMBeanFinder();
if (finder.getMatchingObjectNames().isEmpty()) {
continue;
}
MBeanCollector collector = configuration.getMBeanCollector();
PresentationInformation presentationInformation = configuration.getPresentationInformation();
for (ObjectName objectName : finder.getMatchingObjectNames()) {
for (String attribute : collector.getAttributes()) {
try {
String name = collector.getConstructedName(objectName);
Threshold threshold = configuration.getThresholds().get(attribute);
if (threshold != null) {
ThresholdValues individualValues = threshold.getIndividualThresholds().get(name);
String warnLow;
String warnHigh;
String criticalLow;
String criticalHigh;
if (individualValues == null) {
warnLow = threshold.getWarningLowThreshold();
warnHigh = threshold.getWarningHighThreshold();
criticalLow = threshold.getCriticalLowThreshold();
criticalHigh = threshold.getCriticalHighThreshold();
} else {
warnLow = individualValues.getWarningLowThreshold();
warnHigh = individualValues.getWarningHighThreshold();
criticalLow = individualValues.getCriticalLowThreshold();
criticalHigh = individualValues.getCriticalHighThreshold();
}
String list[] = {warnLow, warnHigh, criticalLow, criticalHigh};
for (String measurement : list) {
String calculatedValue = Threshold.calculateThreshold(measurement, collector, objectName, attribute);
if (!calculatedValue.isEmpty()) {
ComparisonOperator compOper = ComparisonOperator.GreaterThanThreshold;
if (measurement.contains("Low")) {
compOper = ComparisonOperator.LessThanThreshold;
}
String type = "WARNING";
if (measurement.contains("critical")) {
type = "CRITICAL";
}
Dimension dimension = new Dimension()
.withName(presentationInformation.getCategory())
.withValue(name);
String alarmName = presentationInformation.getCategory() +
"/" + name + "/" +
presentationInformation.translateAttributeLabel(attribute);
String description = type + ": ";
if (individualValues == null) {
description += threshold.getMessage();
} else {
description += individualValues.getMessage();
}
description = String.format(description, "");
PutMetricAlarmRequest request = new PutMetricAlarmRequest()
.withAlarmName(alarmName)
.withComparisonOperator(compOper)
.withEvaluationPeriods(1)
.withStatistic(Statistic.SampleCount)
.withPeriod(60)
.withMetricName(presentationInformation.translateAttributeLabel(attribute))
.withAlarmDescription(description)
.withNamespace(namespace)
.withThreshold(Double.parseDouble(calculatedValue))
.withActionsEnabled(false)
.withDimensions(dimension);
amazonCloudWatch.putMetricAlarm(request);
alarmList.add(alarmName);
}
}
}
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
}
private void stopAlarms() {
DeleteAlarmsRequest request = new DeleteAlarmsRequest().withAlarmNames(alarmList);
amazonCloudWatch.deleteAlarms(request);
alarmList.clear();
}
@Override
public long getInterval() {
return interval;
}
@Override
public void setInterval(long interval) {
this.interval = interval;
}
@Override
public String getNamespace() {
return namespace;
}
@Override
public void setNamespace(String namespace) {
this.namespace = namespace;
}
@Override
protected void handleMeasurement(String category, String name, String attribute, Object value,
PresentationInformation presentationInformation) throws Exception {
Dimension dimension = new Dimension()
.withName(category)
.withValue(name);
MetricDatum datum = new MetricDatum()
.withMetricName(presentationInformation.translateAttributeLabel(attribute))
.withValue(Double.valueOf(value.toString()))
.withDimensions(dimension);
PutMetricDataRequest request = new PutMetricDataRequest()
.withNamespace(namespace)
.withMetricData(datum);
amazonCloudWatch.putMetricData(request);
}
@Override
protected void handleWarnings() throws Exception {
// Nothing to do
LOG.fine("handleWarnings() called");
}
@Override
protected void handleCriticals() throws Exception {
// Nothing to do
LOG.fine("handleCritical() called");
}
}