2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.components.impl;
23 import java.util.ArrayList;
24 import java.util.List;
26 import java.util.Map.Entry;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.ScheduledExecutorService;
29 import java.util.concurrent.ScheduledFuture;
30 import java.util.concurrent.ThreadFactory;
31 import java.util.concurrent.TimeUnit;
32 import java.util.stream.Collectors;
34 import javax.annotation.PostConstruct;
35 import javax.annotation.PreDestroy;
36 import javax.annotation.Resource;
37 import javax.servlet.ServletContext;
39 import org.openecomp.sdc.be.components.distribution.engine.DistributionEngineClusterHealth;
40 import org.openecomp.sdc.be.components.distribution.engine.UebHealthCheckCall;
41 import org.openecomp.sdc.be.config.BeEcompErrorManager;
42 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
43 import org.openecomp.sdc.be.dao.api.IEsHealthCheckDao;
44 import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
45 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
46 import org.openecomp.sdc.be.switchover.detector.SwitchoverDetector;
47 import org.openecomp.sdc.common.api.Constants;
48 import org.openecomp.sdc.common.api.HealthCheckInfo;
49 import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckComponent;
50 import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus;
51 import org.openecomp.sdc.common.impl.ExternalConfiguration;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.beans.factory.annotation.Autowired;
55 import org.springframework.stereotype.Component;
56 import org.springframework.web.context.WebApplicationContext;
58 @Component("healthCheckBusinessLogic")
59 public class HealthCheckBusinessLogic {
61 protected static String BE_HEALTH_LOG_CONTEXT = "be.healthcheck";
63 private static Logger healthLogger = LoggerFactory.getLogger(BE_HEALTH_LOG_CONTEXT);
65 private static final String BE_HEALTH_CHECK_STR = "beHealthCheck";
68 private TitanGenericDao titanGenericDao;
71 private IEsHealthCheckDao esHealthCheckDao;
74 private DistributionEngineClusterHealth distributionEngineClusterHealth;
77 private SwitchoverDetector switchoverDetector;
79 private static Logger log = LoggerFactory.getLogger(HealthCheckBusinessLogic.class.getName());
81 private volatile List<HealthCheckInfo> lastBeHealthCheckInfos = null;
83 // private static volatile HealthCheckBusinessLogic instance;
85 public HealthCheckBusinessLogic() {
89 private ScheduledFuture<?> scheduledFuture = null;
91 ScheduledExecutorService healthCheckScheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
93 public Thread newThread(Runnable r) {
94 return new Thread(r, "BE-Health-Check-Task");
98 HealthCheckScheduledTask healthCheckScheduledTask = null;
103 lastBeHealthCheckInfos = getBeHealthCheckInfos();
105 log.debug("After initializing lastBeHealthCheckInfos :{}", lastBeHealthCheckInfos);
107 healthCheckScheduledTask = new HealthCheckScheduledTask();
109 if (this.scheduledFuture == null) {
110 this.scheduledFuture = this.healthCheckScheduler.scheduleAtFixedRate(healthCheckScheduledTask, 0, 3, TimeUnit.SECONDS);
116 // public static HealthCheckBusinessLogic getInstance(){
117 //// if (instance == null){
118 //// instance = init();
123 // private synchronized static HealthCheckBusinessLogic init() {
124 // if (instance == null){
125 // instance = new HealthCheckBusinessLogic();
130 private List<HealthCheckInfo> getBeHealthCheckInfos(ServletContext servletContext) {
132 List<HealthCheckInfo> healthCheckInfos = new ArrayList<HealthCheckInfo>();
135 getBeHealthCheck(servletContext, healthCheckInfos);
138 getEsHealthCheck(servletContext, healthCheckInfos);
141 getTitanHealthCheck(servletContext, healthCheckInfos);
143 // Distribution Engine
144 getDistributionEngineCheck(servletContext, healthCheckInfos);
146 return healthCheckInfos;
149 private List<HealthCheckInfo> getBeHealthCheck(ServletContext servletContext, List<HealthCheckInfo> healthCheckInfos) {
150 String appVersion = ExternalConfiguration.getAppVersion();
151 String description = "OK";
152 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.BE, HealthCheckStatus.UP, appVersion, description));
153 return healthCheckInfos;
156 public List<HealthCheckInfo> getTitanHealthCheck(ServletContext servletContext, List<HealthCheckInfo> healthCheckInfos) {
157 // Titan health check and version
158 TitanGenericDao titanStatusDao = (TitanGenericDao) getDao(servletContext, TitanGenericDao.class);
163 isTitanUp = titanStatusDao.isGraphOpen();
164 } catch (Exception e) {
165 description = "Titan error: " + e.getMessage();
166 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.DOWN, null, description));
167 return healthCheckInfos;
171 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.UP, null, description));
173 description = "Titan graph is down";
174 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.DOWN, null, description));
176 return healthCheckInfos;
179 public List<HealthCheckInfo> getEsHealthCheck(ServletContext servletContext, List<HealthCheckInfo> healthCheckInfos) {
181 // ES health check and version
182 IEsHealthCheckDao esStatusDao = (IEsHealthCheckDao) getDao(servletContext, IEsHealthCheckDao.class);
183 HealthCheckStatus healthCheckStatus;
187 healthCheckStatus = esStatusDao.getClusterHealthStatus();
188 } catch (Exception e) {
189 healthCheckStatus = HealthCheckStatus.DOWN;
190 description = "ES cluster error: " + e.getMessage();
191 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, healthCheckStatus, null, description));
192 return healthCheckInfos;
194 if (healthCheckStatus.equals(HealthCheckStatus.DOWN)) {
195 description = "ES cluster is down";
199 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, healthCheckStatus, null, description));
200 return healthCheckInfos;
203 public Object getDao(ServletContext servletContext, Class<?> clazz) {
204 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
206 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(servletContext);
208 return webApplicationContext.getBean(clazz);
211 private void getDistributionEngineCheck(ServletContext servletContext, List<HealthCheckInfo> healthCheckInfos) {
213 DistributionEngineClusterHealth deDao = (DistributionEngineClusterHealth) getDao(servletContext, DistributionEngineClusterHealth.class);
214 HealthCheckInfo healthCheckInfo = deDao.getHealthCheckInfo();
216 healthCheckInfos.add(healthCheckInfo);
220 public boolean isDistributionEngineUp(ServletContext servletContext) {
222 DistributionEngineClusterHealth deDao = (DistributionEngineClusterHealth) getDao(servletContext, DistributionEngineClusterHealth.class);
223 HealthCheckInfo healthCheckInfo = deDao.getHealthCheckInfo();
224 if (healthCheckInfo.getHealthCheckStatus().equals(HealthCheckStatus.DOWN)) {
230 public List<HealthCheckInfo> getBeHealthCheckInfosStatus() {
232 return lastBeHealthCheckInfos;
236 private List<HealthCheckInfo> getBeHealthCheckInfos() {
238 log.trace("In getBeHealthCheckInfos");
240 List<HealthCheckInfo> healthCheckInfos = new ArrayList<HealthCheckInfo>();
243 getBeHealthCheck(healthCheckInfos);
246 getEsHealthCheck(healthCheckInfos);
249 getTitanHealthCheck(healthCheckInfos);
251 // Distribution Engine
252 getDistributionEngineCheck(healthCheckInfos);
254 return healthCheckInfos;
257 private List<HealthCheckInfo> getBeHealthCheck(List<HealthCheckInfo> healthCheckInfos) {
258 String appVersion = ExternalConfiguration.getAppVersion();
259 String description = "OK";
260 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.BE, HealthCheckStatus.UP, appVersion, description));
261 return healthCheckInfos;
264 public List<HealthCheckInfo> getEsHealthCheck(List<HealthCheckInfo> healthCheckInfos) {
266 // ES health check and version
267 HealthCheckStatus healthCheckStatus;
271 healthCheckStatus = esHealthCheckDao.getClusterHealthStatus();
272 } catch (Exception e) {
273 healthCheckStatus = HealthCheckStatus.DOWN;
274 description = "ES cluster error: " + e.getMessage();
275 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, healthCheckStatus, null, description));
276 return healthCheckInfos;
278 if (healthCheckStatus.equals(HealthCheckStatus.DOWN)) {
279 description = "ES cluster is down";
283 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, healthCheckStatus, null, description));
284 return healthCheckInfos;
287 public List<HealthCheckInfo> getTitanHealthCheck(List<HealthCheckInfo> healthCheckInfos) {
288 // Titan health check and version
293 isTitanUp = titanGenericDao.isGraphOpen();
294 } catch (Exception e) {
295 description = "Titan error: " + e.getMessage();
296 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.DOWN, null, description));
297 return healthCheckInfos;
301 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.UP, null, description));
303 description = "Titan graph is down";
304 healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.DOWN, null, description));
306 return healthCheckInfos;
309 private void getDistributionEngineCheck(List<HealthCheckInfo> healthCheckInfos) {
311 HealthCheckInfo healthCheckInfo = distributionEngineClusterHealth.getHealthCheckInfo();
313 healthCheckInfos.add(healthCheckInfo);
318 private void destroy() {
320 if (scheduledFuture != null) {
321 scheduledFuture.cancel(true);
322 scheduledFuture = null;
325 if (healthCheckScheduler != null) {
326 healthCheckScheduler.shutdown();
331 public class HealthCheckScheduledTask implements Runnable {
333 List<UebHealthCheckCall> healthCheckCalls = new ArrayList<>();
335 public HealthCheckScheduledTask() {
342 healthLogger.trace("Executing BE Health Check Task");
344 List<HealthCheckInfo> beHealthCheckInfos = getBeHealthCheckInfos();
345 boolean healthStatus = getAggregateBeStatus(beHealthCheckInfos);
347 boolean lastHealthStatus = getAggregateBeStatus(lastBeHealthCheckInfos);
349 if (lastHealthStatus != healthStatus) {
350 log.trace("BE Health State Changed to {}. Issuing alarm / recovery alarm...", healthStatus);
352 lastBeHealthCheckInfos = beHealthCheckInfos;
353 logAlarm(healthStatus);
356 // check if we need to update the status's list in case one of
357 // the statuses was changed
358 if (true == anyStatusChanged(beHealthCheckInfos, lastBeHealthCheckInfos)) {
359 lastBeHealthCheckInfos = beHealthCheckInfos;
368 private void logAlarm(boolean lastHealthState) {
369 if (lastHealthState == true) {
370 BeEcompErrorManager.getInstance().logBeHealthCheckRecovery(BE_HEALTH_CHECK_STR);
372 BeEcompErrorManager.getInstance().logBeHealthCheckError(BE_HEALTH_CHECK_STR);
376 private boolean getAggregateBeStatus(List<HealthCheckInfo> beHealthCheckInfos) {
378 boolean status = true;
380 for (HealthCheckInfo healthCheckInfo : beHealthCheckInfos) {
381 if (healthCheckInfo.getHealthCheckStatus().equals(HealthCheckStatus.DOWN) && healthCheckInfo.getHealthCheckComponent() != HealthCheckComponent.DE) {
389 public String getSiteMode() {
390 return switchoverDetector.getSiteMode();
393 public boolean anyStatusChanged(List<HealthCheckInfo> beHealthCheckInfos, List<HealthCheckInfo> lastBeHealthCheckInfos) {
395 boolean result = false;
397 if (beHealthCheckInfos != null && lastBeHealthCheckInfos != null) {
399 Map<HealthCheckComponent, HealthCheckStatus> currentValues = beHealthCheckInfos.stream().collect(Collectors.toMap(p -> p.getHealthCheckComponent(), p -> p.getHealthCheckStatus()));
400 Map<HealthCheckComponent, HealthCheckStatus> lastValues = lastBeHealthCheckInfos.stream().collect(Collectors.toMap(p -> p.getHealthCheckComponent(), p -> p.getHealthCheckStatus()));
402 if (currentValues != null && lastValues != null) {
403 int currentSize = currentValues.size();
404 int lastSize = lastValues.size();
406 if (currentSize != lastSize) {
410 for (Entry<HealthCheckComponent, HealthCheckStatus> entry : currentValues.entrySet()) {
411 HealthCheckComponent key = entry.getKey();
412 HealthCheckStatus value = entry.getValue();
414 if (false == lastValues.containsKey(key)) {
419 HealthCheckStatus lastHealthCheckStatus = lastValues.get(key);
421 if (value != lastHealthCheckStatus) {
427 } else if (currentValues == null && lastValues == null) {
433 } else if (beHealthCheckInfos == null && lastBeHealthCheckInfos == null) {