AMBARI-7374. Slider View: BE - Provide alerts in view API
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2a5759c5 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2a5759c5 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2a5759c5 Branch: refs/heads/branch-alerts-dev Commit: 2a5759c5d39fbb70db2b4549bb6cee49601c86d9 Parents: 372514d Author: Srimanth Gunturi <sgunt...@hortonworks.com> Authored: Wed Sep 17 15:01:59 2014 -0700 Committer: Srimanth Gunturi <sgunt...@hortonworks.com> Committed: Wed Sep 17 15:01:59 2014 -0700 ---------------------------------------------------------------------- .../apache/ambari/view/slider/AlertField.java | 62 ++++++++++ .../apache/ambari/view/slider/AlertState.java | 40 +++++++ .../apache/ambari/view/slider/SliderApp.java | 9 ++ .../ambari/view/slider/SliderAppsAlerts.java | 120 +++++++++++++++++++ .../slider/SliderAppsViewControllerImpl.java | 9 +- .../rest/client/SliderAppMasterClient.java | 38 +++--- 6 files changed, 257 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/2a5759c5/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertField.java ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertField.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertField.java new file mode 100644 index 0000000..40fd97f --- /dev/null +++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertField.java @@ -0,0 +1,62 @@ +/** + * 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.view.slider; + +public enum AlertField { + /** + * Description of a service + */ + description, + /** + * Host name where to which service belongs + */ + host_name, + /** + * Last status + */ + last_status, + /** + * Time when last status was checked + */ + last_status_time, + /** + * Service + */ + service_name, + /** + * Component name + */ + component_name, + /** + * Same, as actual_status and last_status + */ + status, + /** + * Time when status was checked + */ + status_time, + /** + * Not yet used, for future purpose + */ + output, + /** + * Same, as status and last_status + */ + actual_status +} http://git-wip-us.apache.org/repos/asf/ambari/blob/2a5759c5/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertState.java ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertState.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertState.java new file mode 100644 index 0000000..d239394 --- /dev/null +++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/AlertState.java @@ -0,0 +1,40 @@ +/** + * 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.view.slider; + + +public enum AlertState { + /** + * Alert does not need to be distributed. Normal Operation. + */ + OK, + /** + * Alert indicates there may be an issue. The component may be operating + * normally but may be in danger of becoming <code>CRITICAL</code>. + */ + WARNING, + /** + * Indicates there is a critical situation that needs to be addressed. + */ + CRITICAL, + /** + * The state of the alert is not known. + */ + UNKNOWN +} http://git-wip-us.apache.org/repos/asf/ambari/blob/2a5759c5/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderApp.java ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderApp.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderApp.java index 9d748fa..6276299 100644 --- a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderApp.java +++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderApp.java @@ -39,6 +39,7 @@ public class SliderApp { private Map<String, Map<String, String>> configs; private Map<String, SliderAppComponent> components; private Map<String, Object> metrics; + private Map<String, Object> alerts; public String getName() { return name; @@ -167,4 +168,12 @@ public class SliderApp { public void setAppVersion(String appVersion) { this.appVersion = appVersion; } + + public Map<String, Object> getAlerts() { + return alerts; + } + + public void setAlerts(Map<String, Object> alerts) { + this.alerts = alerts; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/2a5759c5/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsAlerts.java ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsAlerts.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsAlerts.java new file mode 100644 index 0000000..957c6e8 --- /dev/null +++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsAlerts.java @@ -0,0 +1,120 @@ +/** + * 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.view.slider; + +import com.google.inject.Singleton; +import org.apache.log4j.Logger; + +import java.lang.Exception; +import java.util.*; + +@Singleton +public class SliderAppsAlerts { + private static final Logger logger = Logger + .getLogger(SliderAppsAlerts.class); + + public Map<String, Object> generateComponentsAlerts(Map<String, SliderAppComponent> components, String service){ + HashMap<String, Object> result = new HashMap<String, Object>(); + Set<Map<AlertField,Object>> details = buildAlertsDetails(components, service); + + result.put("detail", details); + result.put("summary", buildAlertsSummary(details)); + + return result; + } + + private Map<AlertState,Integer> buildAlertsSummary(Set<Map<AlertField,Object>> details){ + Map<AlertState,Integer> result = new HashMap<AlertState, Integer>(); + + // Initial filling of map with available states + for (AlertState state:AlertState.values()){ + result.put(state, 0); + } + + for(Map<AlertField,Object> item:details){ + AlertState state = (AlertState)item.get(AlertField.status); + result.put(state,result.get(state)+1); + } + return result; + } + + private Set<Map<AlertField,Object>> buildAlertsDetails(Map<String, SliderAppComponent> components, String service){ + HashSet<Map<AlertField,Object>> resultList = new HashSet<Map<AlertField, Object>>(); + for (String componentKey:components.keySet()){ + resultList.add(buildComponentAlert(components.get(componentKey), service)); + } + return resultList; + } + + private Map<AlertField,Object> buildComponentAlert(SliderAppComponent component, String service){ + HashMap<AlertField,Object> alertItem = new HashMap<AlertField, Object>(); + Date date = Calendar.getInstance().getTime(); + + + AlertState state = getComponentState(component); + alertItem.put(AlertField.description, String.format("%s component",component.getComponentName())); + alertItem.put(AlertField.host_name, getComponentHostName(component)); + alertItem.put(AlertField.last_status, state); + + alertItem.put(AlertField.last_status_time, new java.sql.Timestamp(date.getTime())); + + alertItem.put(AlertField.service_name, service.toUpperCase()); + alertItem.put(AlertField.component_name, component.getComponentName()); + alertItem.put(AlertField.status, state); + alertItem.put(AlertField.status_time, new java.sql.Timestamp(date.getTime())); + alertItem.put(AlertField.output, state); + alertItem.put(AlertField.actual_status, state); + return alertItem; + } + + @SuppressWarnings("unchecked") + private String getComponentHostName(SliderAppComponent component){ + Map<String,Map<String,String>> containers = null; + + if (component.getActiveContainers().size() > 0){ + containers = component.getActiveContainers(); + } + + if (component.getCompletedContainers().size() > 0 && containers == null) { + containers =component.getCompletedContainers(); + } + + + if (containers != null){ + try { + // try to obtain host name from any first available container + return ((Map<String,String>)containers.values().toArray()[0]).get("host"); + } catch (Exception e){ + if (logger.isDebugEnabled()){ + logger.warn("Couldn't obtain host name for the component", e); + } + } + } + return null; + } + + private AlertState getComponentState(SliderAppComponent component){ + if (component.getInstanceCount() == component.getActiveContainers().size()){ + return AlertState.OK; + } + return AlertState.CRITICAL; + } + + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/2a5759c5/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java index 5d6c368..3626cbe 100644 --- a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java +++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java @@ -89,6 +89,8 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController { private ViewContext viewContext; private List<SliderAppType> appTypes; private Integer createAppCounter = -1; + @Inject + private SliderAppsAlerts sliderAlerts; private String getAppsFolderPath() { return viewContext.getAmbariProperty("resources.dir") + "/apps"; @@ -229,17 +231,17 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController { if (appMasterData == null) { appMasterData = sliderAppClient.getAppMasterData(); } - if ("urls".equals(property.toLowerCase())) { + if (appMasterData!=null && "urls".equals(property.toLowerCase())) { if (quickLinks.isEmpty()) { quickLinks = sliderAppClient .getQuickLinks(appMasterData.publisherUrl); } app.setUrls(quickLinks); - } else if ("configs".equals(property.toLowerCase())) { + } else if (appMasterData!=null && "configs".equals(property.toLowerCase())) { Map<String, Map<String, String>> configs = sliderAppClient .getConfigs(appMasterData.publisherUrl); app.setConfigs(configs); - } else if ("jmx".equals(property.toLowerCase())) { + } else if (appMasterData!=null && "jmx".equals(property.toLowerCase())) { if (quickLinks.isEmpty()) { quickLinks = sliderAppClient .getQuickLinks(appMasterData.publisherUrl); @@ -323,6 +325,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController { + appComponent.getCompletedContainers().size()); } } + app.setAlerts(sliderAlerts.generateComponentsAlerts(componentTypeMap, app.getType())); app.setComponents(componentTypeMap); } } catch (UnknownApplicationInstanceException e) { http://git-wip-us.apache.org/repos/asf/ambari/blob/2a5759c5/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/SliderAppMasterClient.java ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/SliderAppMasterClient.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/SliderAppMasterClient.java index d77c1c7..ab6289c 100644 --- a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/SliderAppMasterClient.java +++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/SliderAppMasterClient.java @@ -48,26 +48,28 @@ public class SliderAppMasterClient extends BaseHttpClient { public SliderAppMasterData getAppMasterData() { try { String html = doGet(""); - int from = html.lastIndexOf("<ul>"); - int to = html.lastIndexOf("</ul>"); - if (from < to && from > -1) { - SliderAppMasterData data = new SliderAppMasterData(); - String content = html.substring(from, to); - content = content.replaceAll("<[^>]*>", "\r\n"); - String[] splits = content.split("\r\n"); - for (int i = 0; i < splits.length; i++) { - String split = splits[i].trim(); - if ("Registry Web Service".equals(split)) { - data.registryUrl = splits[i + 1].trim(); - } else if ("Application Master Web UI".equals(split)) { - data.uiUrl = splits[i + 1].trim(); - } else if ("Management REST API".equals(split)) { - data.managementUrl = splits[i + 1].trim(); - } else if ("Publisher Service".equals(split)) { - data.publisherUrl = splits[i + 1].trim(); + if (html != null) { + int from = html.lastIndexOf("<ul>"); + int to = html.lastIndexOf("</ul>"); + if (from < to && from > -1) { + SliderAppMasterData data = new SliderAppMasterData(); + String content = html.substring(from, to); + content = content.replaceAll("<[^>]*>", "\r\n"); + String[] splits = content.split("\r\n"); + for (int i = 0; i < splits.length; i++) { + String split = splits[i].trim(); + if ("Registry Web Service".equals(split)) { + data.registryUrl = splits[i + 1].trim(); + } else if ("Application Master Web UI".equals(split)) { + data.uiUrl = splits[i + 1].trim(); + } else if ("Management REST API".equals(split)) { + data.managementUrl = splits[i + 1].trim(); + } else if ("Publisher Service".equals(split)) { + data.publisherUrl = splits[i + 1].trim(); + } } + return data; } - return data; } } catch (HttpException e) { logger.warn("Unable to determine Ambari clusters", e);