AMBARI-22115. Alerts for OneFS mpack (amagyar)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/68e7dd3f Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/68e7dd3f Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/68e7dd3f Branch: refs/heads/branch-feature-AMBARI-22008-isilon Commit: 68e7dd3faad9523b0d7d177e041d94acb256e47b Parents: d88c8ea Author: Attila Magyar <amag...@hortonworks.com> Authored: Thu Oct 12 15:21:13 2017 +0200 Committer: Attila Magyar <amag...@hortonworks.com> Committed: Fri Dec 22 09:57:58 2017 +0100 ---------------------------------------------------------------------- ambari-server/docs/configuration/index.md | 1 + .../server/alerts/JmxServerSideAlert.java | 104 +++++++++++++++++++ .../apache/ambari/server/alerts/Threshold.java | 73 +++++++++++++ .../server/configuration/Configuration.java | 11 ++ .../server/controller/ControllerModule.java | 1 + .../server/controller/jmx/JMXMetricHolder.java | 27 +++++ .../org/apache/ambari/server/state/Alert.java | 1 + .../ambari/server/state/alert/AlertUri.java | 41 ++++++++ .../ambari/server/state/alert/MetricSource.java | 7 ++ .../ambari/server/state/alert/Reporting.java | 43 ++++++++ .../ambari/server/state/alert/ServerSource.java | 15 +++ .../services/AmbariServerAlertService.java | 7 +- .../ambari/server/alerts/ThresholdTest.java | 90 ++++++++++++++++ .../controller/jmx/JMXMetricHolderTest.java | 61 +++++++++++ .../ambari/server/state/alert/AlertUriTest.java | 60 +++++++++++ 15 files changed, 541 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/docs/configuration/index.md ---------------------------------------------------------------------- diff --git a/ambari-server/docs/configuration/index.md b/ambari-server/docs/configuration/index.md index 9dbe9c4..8f1531b 100644 --- a/ambari-server/docs/configuration/index.md +++ b/ambari-server/docs/configuration/index.md @@ -57,6 +57,7 @@ The following are the properties which can be used to configure Ambari. | alerts.execution.scheduler.threadpool.size.core | The core number of threads used to process incoming alert events. The value should be increased as the size of the cluster increases. |`2` | | alerts.execution.scheduler.threadpool.size.max | The number of threads used to handle alerts received from the Ambari Agents. The value should be increased as the size of the cluster increases. |`2` | | alerts.execution.scheduler.threadpool.worker.size | The number of queued alerts allowed before discarding old alerts which have not been handled. The value should be increased as the size of the cluster increases. |`2000` | +| alerts.server.side.scheduler.threadpool.size.core | The core pool size of the executor service that runs server side alerts. |`4` | | alerts.snmp.dispatcher.udp.port | The UDP port to use when binding the SNMP dispatcher on Ambari Server startup. If no port is specified, then a random port will be used. | | | alerts.template.file | The full path to the XML file that describes the different alert templates. | | | ambari.display.url | The URL to use when creating messages which should include the Ambari Server URL.<br/><br/>The following are examples of valid values:<ul><li>`http://ambari.apache.org:8080`</ul> | | http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/alerts/JmxServerSideAlert.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/alerts/JmxServerSideAlert.java b/ambari-server/src/main/java/org/apache/ambari/server/alerts/JmxServerSideAlert.java new file mode 100644 index 0000000..a4b86f8 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/alerts/JmxServerSideAlert.java @@ -0,0 +1,104 @@ +/* + * 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.ambari.server.alerts; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +import java.net.URI; +import java.util.List; +import java.util.Map; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.configuration.ComponentSSLConfiguration; +import org.apache.ambari.server.controller.internal.URLStreamProvider; +import org.apache.ambari.server.controller.jmx.JMXMetricHolder; +import org.apache.ambari.server.orm.entities.AlertDefinitionEntity; +import org.apache.ambari.server.state.Alert; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.ConfigHelper; +import org.apache.ambari.server.state.alert.AlertDefinition; +import org.apache.ambari.server.state.alert.AlertDefinitionFactory; +import org.apache.ambari.server.state.alert.MetricSource; +import org.apache.ambari.server.state.alert.Reporting; +import org.apache.ambari.server.state.alert.ServerSource; +import org.apache.ambari.server.state.services.MetricsRetrievalService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.Inject; + +/** + * I represent a "SERVER" {@link org.apache.ambari.server.state.alert.SourceType} alert + * which can pull JMX metrics from a remote cluster. + */ +public class JmxServerSideAlert extends AlertRunnable { + private final static Logger LOG = LoggerFactory.getLogger(JmxServerSideAlert.class); + @Inject + private AlertDefinitionFactory definitionFactory; + @Inject + private MetricsRetrievalService metricsRetrievalService; + @Inject + private ConfigHelper configHelper; + + public JmxServerSideAlert(String definitionName) { + super(definitionName); + } + + @Override + List<Alert> execute(Cluster cluster, AlertDefinitionEntity entity) throws AmbariException { + AlertDefinition alertDef = definitionFactory.coerce(entity); + ServerSource serverSource = (ServerSource) alertDef.getSource(); + URI jmxUrl = jmxUrl(cluster, serverSource); + JMXMetricHolder metricHolder = jmxMetric(serverSource, jmxUrl); + return metricHolder == null + ? emptyList() + : alerts(alertDef, serverSource.getJmxInfo(), metricHolder, serverSource.getReporting()); + } + + private URI jmxUrl(Cluster cluster, ServerSource serverSource) throws AmbariException { + return serverSource.getUri().resolve(config(cluster)).resolve(serverSource.getJmxInfo().getUrlSuffix()); + } + + private Map<String, Map<String, String>> config(Cluster cluster) throws AmbariException { + return configHelper.getEffectiveConfigProperties(cluster, configHelper.getEffectiveDesiredTags(cluster, null)); + } + + private JMXMetricHolder jmxMetric(ServerSource serverSource, URI jmxUri) { + URLStreamProvider streamProvider = new URLStreamProvider( + serverSource.getUri().getConnectionTimeoutMsec(), + serverSource.getUri().getReadTimeoutMsec(), + ComponentSSLConfiguration.instance()); + metricsRetrievalService.submitRequest(MetricsRetrievalService.MetricSourceType.JMX, streamProvider, jmxUri.toString()); + return metricsRetrievalService.getCachedJMXMetric(jmxUri.toString()); + } + + private List<Alert> alerts(AlertDefinition alertDef, MetricSource.JmxInfo jmxInfo, JMXMetricHolder jmxMetricHolder, Reporting reporting) throws AmbariException { + List<Object> metrics = jmxMetricHolder.findAll(jmxInfo.getPropertyList()); + if (metrics.isEmpty()) { + return emptyList(); + } + if (metrics.get(0) instanceof Number) { + Alert alert = reporting.alert(((Number) metrics.get(0)).doubleValue(), metrics, alertDef); + return singletonList(alert); + } else { + LOG.info("Unsupported metrics value: {} when running alert: {}", metrics.get(0), alertDef); + return emptyList(); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/alerts/Threshold.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/alerts/Threshold.java b/ambari-server/src/main/java/org/apache/ambari/server/alerts/Threshold.java new file mode 100644 index 0000000..ae33eeb --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/alerts/Threshold.java @@ -0,0 +1,73 @@ +/* + * 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.ambari.server.alerts; + +import javax.annotation.Nullable; + +import org.apache.ambari.server.state.AlertState; + +/** + * I'm a 3 level threshold where each level corresponds to ok, warn and critical levels. + * The levels are either increasing or decreasing numerical sequences. + * My main responsibility is to map incoming values to {@link AlertState} based on the threshold levels. + */ +public class Threshold { + private final Double okValue; + private final double warnValue; + private final double critValue; + + public Threshold(@Nullable Double okValue, double warnValue, double critValue) { + this.okValue = okValue; + this.warnValue = warnValue; + this.critValue = critValue; + } + + public AlertState state(double value) { + return directionUp() ? stateWhenDirectionUp(value) : stateWhenDirectionDown(value); + } + + private boolean directionUp() { + return critValue >= warnValue; + } + + private AlertState stateWhenDirectionUp(double value) { + if (value >= critValue) { + return AlertState.CRITICAL; + } + if (value >= warnValue) { + return AlertState.WARNING; + } + if (okValue == null || value >= okValue) { + return AlertState.OK; + } + return AlertState.UNKNOWN; + } + + private AlertState stateWhenDirectionDown(double value) { + if (value <= critValue) { + return AlertState.CRITICAL; + } + if (value <= warnValue) { + return AlertState.WARNING; + } + if (okValue == null || value <= okValue) { + return AlertState.OK; + } + return AlertState.UNKNOWN; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java index 7003c98..09d5799 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java @@ -2786,6 +2786,13 @@ public class Configuration { @Markdown(description = "Whether security password encryption is enabled or not. In case it is we store passwords in their own file(s); otherwise we store passwords in the Ambari credential store.") public static final ConfigurationProperty<Boolean> SECURITY_PASSWORD_ENCRYPTON_ENABLED = new ConfigurationProperty<Boolean>("security.passwords.encryption.enabled", false); + /** + * The core pool size of the executor service that runs server side alerts. + */ + @Markdown(description = "The core pool size of the executor service that runs server side alerts.") + public static final ConfigurationProperty<Integer> SERVER_SIDE_ALERTS_CORE_POOL_SIZE = new ConfigurationProperty<>( + "alerts.server.side.scheduler.threadpool.size.core", 4); + private static final Logger LOG = LoggerFactory.getLogger( Configuration.class); @@ -6234,4 +6241,8 @@ public class Configuration { public String getAutoGroupCreation() { return getProperty(AUTO_GROUP_CREATION); } + + public int getAlertServiceCorePoolSize() { + return Integer.parseInt(getProperty(SERVER_SIDE_ALERTS_CORE_POOL_SIZE)); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index ed7513f..2938b26 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -359,6 +359,7 @@ public class ControllerModule extends AbstractModule { // So it's an "additional time", given to stage to finish execution before // it is considered as timed out bindConstant().annotatedWith(Names.named("actionTimeout")).to(600000L); + bindConstant().annotatedWith(Names.named("alertServiceCorePoolSize")).to(configuration.getAlertServiceCorePoolSize()); bindConstant().annotatedWith(Names.named("dbInitNeeded")).to(dbInitNeeded); bindConstant().annotatedWith(Names.named("statusCheckInterval")).to(5000L); http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetricHolder.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetricHolder.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetricHolder.java index 81d72fb..f6ae54f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetricHolder.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetricHolder.java @@ -18,13 +18,18 @@ package org.apache.ambari.server.controller.jmx; +import static java.util.stream.Collectors.toList; + import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; /** * */ public final class JMXMetricHolder { + private static final String NAME_KEY = "name"; private List<Map<String, Object>> beans; @@ -47,4 +52,26 @@ public final class JMXMetricHolder { } return stringBuilder.toString(); } + + public List<Object> findAll(List<String> properties) { + return properties.stream() + .map(this::find) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(toList()); + } + + public Optional<Object> find(String property) { + String propertyName = property.split("/")[0]; + String propertyValue = property.split("/")[1]; + return beans.stream() + .filter(each -> propertyName.equals(name(each))) + .map(each -> each.get(propertyValue)) + .filter(Objects::nonNull) + .findFirst(); + } + + private String name(Map<String, Object> bean) { + return bean.containsKey(NAME_KEY) ? (String) bean.get(NAME_KEY) : null; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java index 5d2ecc6..49bd5d2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java @@ -56,6 +56,7 @@ public class Alert { component = componentName; this.hostName = hostName; state = alertState; + timestamp = System.currentTimeMillis(); } public Alert() { http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertUri.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertUri.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertUri.java index 93801d5..b3ef2de 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertUri.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertUri.java @@ -17,8 +17,13 @@ */ package org.apache.ambari.server.state.alert; +import java.net.URI; +import java.util.Map; import java.util.Set; +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.state.kerberos.VariableReplacementHelper; + import com.google.gson.annotations.SerializedName; /** @@ -87,6 +92,13 @@ public class AlertUri { @SerializedName("connection_timeout") private float m_connectionTimeout = 5.0f; + + /** + * An optional read timeout value for connections. + */ + @SerializedName("read_timeout") + private float readTimeout = 15.0f; + /** * If present, then the component supports HA mode and the properties * contained within need to be checked to see if an HA URI is required to be @@ -117,6 +129,18 @@ public class AlertUri { m_httpUri = httpUri; } + public void setHttpsUri(String httpsUri) { + this.m_httpsUri = httpsUri; + } + + public void setHttpsPropertyValue(String m_httpsPropertyValue) { + this.m_httpsPropertyValue = m_httpsPropertyValue; + } + + public void setHttpsProperty(String m_httpsProperty) { + this.m_httpsProperty = m_httpsProperty; + } + /** * Gets the default port to use on the host running the alert if none of the * http properties are available. @@ -276,6 +300,23 @@ public class AlertUri { } } + public URI resolve(Map<String, Map<String, String>> config) throws AmbariException { + VariableReplacementHelper variableReplacer = new VariableReplacementHelper(); + String httpsProperty = variableReplacer.replaceVariables(m_httpsProperty, config); + String httpsPropertyValue = variableReplacer.replaceVariables(m_httpsPropertyValue, config); + return httpsProperty == null || !httpsProperty.equals(httpsPropertyValue) + ? URI.create(String.format("http://%s", variableReplacer.replaceVariables(m_httpUri, config))) + : URI.create(String.format("https://%s", variableReplacer.replaceVariables(m_httpsUri, config))); + } + + public int getConnectionTimeoutMsec() { + return (int) m_connectionTimeout * 1000; + } + + public int getReadTimeoutMsec() { + return (int) readTimeout * 1000; + } + /** * {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricSource.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricSource.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricSource.java index 11eee05..d7283fe 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricSource.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricSource.java @@ -129,6 +129,9 @@ public class MetricSource extends Source { private String value; + @SerializedName("url_suffix") + private String urlSuffix = "/jmx"; + public List<String> getPropertyList() { return propertyList; } @@ -152,5 +155,9 @@ public class MetricSource extends Source { return list1.equals(list2); } + + public String getUrlSuffix() { + return urlSuffix; + } } } http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Reporting.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Reporting.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Reporting.java index 4aeba45..51d074e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Reporting.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Reporting.java @@ -17,6 +17,15 @@ */ package org.apache.ambari.server.state.alert; +import static org.apache.ambari.server.state.alert.Reporting.ReportingType.PERCENT; + +import java.text.MessageFormat; +import java.util.List; + +import org.apache.ambari.server.alerts.Threshold; +import org.apache.ambari.server.state.Alert; +import org.apache.ambari.server.state.AlertState; + import com.google.gson.annotations.SerializedName; /** @@ -200,6 +209,40 @@ public class Reporting { } /** + * Map the incoming value to {@link AlertState} and generate an alert with that state. + */ + public Alert alert(double value, List<Object> args, AlertDefinition alertDef) { + Alert alert = new Alert(alertDef.getName(), null, alertDef.getServiceName(), alertDef.getComponentName(), null, state(value)); + alert.setText(MessageFormat.format(message(value), args.toArray())); + return alert; + } + + private AlertState state(double value) { + return getThreshold().state(PERCENT == getType() ? value * 100 : value); + } + + private Threshold getThreshold() { + return new Threshold(getOk().getValue(), getWarning().getValue(), getCritical().getValue()); + } + + private String message(double value) { + switch (state(value)) { + case OK: + return getOk().getText(); + case WARNING: + return getWarning().getText(); + case CRITICAL: + return getCritical().getText(); + case UNKNOWN: + return "Unknown"; + case SKIPPED: + return "Skipped"; + default: + throw new IllegalStateException("Invalid alert state: " + state(value)); + } + } + + /** * The {@link ReportTemplate} class is used to pair a label and threshhold * value. * <p/> http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/state/alert/ServerSource.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/ServerSource.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/ServerSource.java index c58867a..765bdea 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/ServerSource.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/ServerSource.java @@ -28,6 +28,13 @@ public class ServerSource extends ParameterizedSource { @SerializedName("class") private String m_class; + @SerializedName("uri") + private AlertUri uri = null; + + @SerializedName("jmx") + private MetricSource.JmxInfo jmxInfo = null; + + /** * Gets the fully qualified classname specified in the source. */ @@ -35,6 +42,14 @@ public class ServerSource extends ParameterizedSource { return m_class; } + public MetricSource.JmxInfo getJmxInfo() { + return jmxInfo; + } + + public AlertUri getUri() { + return uri; + } + /** * {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java index 305f693..6cce1b2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java @@ -45,6 +45,7 @@ import com.google.common.util.concurrent.AbstractScheduledService; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Provider; +import com.google.inject.name.Named; /** * The {@link AmbariServerAlertService} is used to manage the dynamically loaded @@ -87,7 +88,7 @@ public class AmbariServerAlertService extends AbstractScheduledService { /** * The executor to use to run all {@link Runnable} alert classes. */ - private final ScheduledExecutorService m_scheduledExecutorService = Executors.newScheduledThreadPool(3); + private ScheduledExecutorService m_scheduledExecutorService; /** * A map of all of the definition names to {@link ScheduledFuture}s. @@ -101,6 +102,10 @@ public class AmbariServerAlertService extends AbstractScheduledService { public AmbariServerAlertService() { } + @Inject + public void initExecutor(@Named("alertServiceCorePoolSize") int alertServiceCorePoolSize) { + this.m_scheduledExecutorService = Executors.newScheduledThreadPool(alertServiceCorePoolSize); + } /** * {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/test/java/org/apache/ambari/server/alerts/ThresholdTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/alerts/ThresholdTest.java b/ambari-server/src/test/java/org/apache/ambari/server/alerts/ThresholdTest.java new file mode 100644 index 0000000..07bfa03 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/alerts/ThresholdTest.java @@ -0,0 +1,90 @@ +/* + * 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.ambari.server.alerts; + +import static org.apache.ambari.server.state.AlertState.CRITICAL; +import static org.apache.ambari.server.state.AlertState.OK; +import static org.apache.ambari.server.state.AlertState.UNKNOWN; +import static org.apache.ambari.server.state.AlertState.WARNING; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import org.apache.ambari.server.state.AlertState; +import org.junit.Test; + +public class ThresholdTest { + @Test + public void testBetweenOkAndWarnIsOk_dirUp() throws Exception { + Threshold threshold = new Threshold(10.0, 20.0, 30.0); + assertState(threshold, OK, 10, 15, 19); + } + + @Test + public void testBetweenWarnAndCritIsWarn_dirUp() throws Exception { + Threshold threshold = new Threshold(10.0, 20.0, 30.0); + assertState(threshold, WARNING, 20, 25, 29); + } + + @Test + public void testAboveCritIsCrit_dirUp() throws Exception { + Threshold threshold = new Threshold(10.0, 20.0, 30.0); + assertState(threshold, CRITICAL, 30, 40, 99999); + } + + @Test + public void testBelowOkIsUnknown_dirUp() throws Exception { + Threshold threshold = new Threshold(10.0, 20, 30); + assertState(threshold, UNKNOWN, 9, 2, -99999); + } + + @Test + public void testBelowCritIsCrit_dirDown() throws Exception { + Threshold threshold = new Threshold(40.0, 30.0, 20.0); + assertState(threshold, CRITICAL, 20, 15, 2, -99999); + } + + @Test + public void testBetweenWarnAndCritIsWarn_dirDown() throws Exception { + Threshold threshold = new Threshold(40.0, 30.0, 20.0); + assertState(threshold, WARNING, 30, 25, 21); + } + + @Test + public void testBetweenOkAndWarnIsOk_dirDown() throws Exception { + Threshold threshold = new Threshold(40.0, 30.0, 20.0); + assertState(threshold, OK, 40, 35, 31); + } + + @Test + public void testAboveOkIsUnknown_dirDown() throws Exception { + Threshold threshold = new Threshold(40.0, 30.0, 20.0); + assertState(threshold, UNKNOWN, 41, 50, 9999); + } + + @Test + public void testOkIsOptional() throws Exception { + Threshold threshold = new Threshold(null, 20.0, 30.0); + assertState(threshold, OK, 10, 15, 19); + } + + private void assertState(Threshold threshold, AlertState expectedState, int... values) { + for (int value: values) { + assertThat(expectedState, is(threshold.state(value))); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/test/java/org/apache/ambari/server/controller/jmx/JMXMetricHolderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/jmx/JMXMetricHolderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/jmx/JMXMetricHolderTest.java new file mode 100644 index 0000000..61d5bae --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/jmx/JMXMetricHolderTest.java @@ -0,0 +1,61 @@ +/* + * 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.ambari.server.controller.jmx; + +import static java.util.Arrays.asList; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.junit.internal.matchers.IsCollectionContaining.hasItems; + +import java.util.HashMap; +import java.util.List; +import java.util.Optional; + +import org.junit.Before; +import org.junit.Test; + +public class JMXMetricHolderTest { + private JMXMetricHolder metrics = new JMXMetricHolder(); + + @Before + public void setUp() { + metrics.setBeans(asList( + new HashMap<String, Object>() {{ + put("name", "bean1"); + put("value", "val1"); + }}, + new HashMap<String, Object>() {{ + put("name", "bean2"); + put("value", "val2"); + }} + )); + } + + @Test + public void testFindSingleBeanByName() throws Exception { + assertThat(metrics.find("bean1/value"), is(Optional.of("val1"))); + assertThat(metrics.find("bean2/value"), is(Optional.of("val2"))); + assertThat(metrics.find("bean3/notfound"), is(Optional.empty())); + } + + @Test + public void testFindMultipleBeansByName() throws Exception { + List<Object> result = metrics.findAll(asList("bean1/value", "bean2/value", "bean3/notfound")); + assertThat(result, hasItems("val1", "val2")); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/68e7dd3f/ambari-server/src/test/java/org/apache/ambari/server/state/alert/AlertUriTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/alert/AlertUriTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/alert/AlertUriTest.java new file mode 100644 index 0000000..295e364 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/state/alert/AlertUriTest.java @@ -0,0 +1,60 @@ +/* + * 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.ambari.server.state.alert; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.ambari.server.AmbariException; +import org.junit.Test; + +public class AlertUriTest { + @Test + public void testChoosesHttpByDefault() throws Exception { + AlertUri uri = new AlertUri(); + uri.setHttpUri("${config1/http-host}/path"); + assertThat(resolved(uri), is("http://http-host/path")); + } + + @Test + public void testChoosesHttpsBasedOnProperties() throws Exception { + AlertUri uri = new AlertUri(); + uri.setHttpUri("${config1/http-host}/path"); + uri.setHttpsUri("${config1/https-host}/path"); + uri.setHttpsProperty("${config1/use-http}"); + uri.setHttpsPropertyValue("YES"); + assertThat(resolved(uri), is("https://https-host/path")); + } + + private Map<String, Map<String, String>> config() { + return new HashMap<String, Map<String, String>>() {{ + put("config1", new HashMap<String, String>() {{ + put("http-host", "http-host"); + put("https-host", "https-host"); + put("use-http", "YES"); + }}); + }}; + } + + private String resolved(AlertUri uri) throws AmbariException { + return uri.resolve(config()).toString(); + } +} \ No newline at end of file