| /******************************************************************************* |
| * Copyright 2017 General Electric Company |
| * |
| * 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. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| *******************************************************************************/ |
| |
| package com.ge.predix.acs.monitoring; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.springframework.boot.actuate.health.Health; |
| import org.springframework.boot.actuate.health.HealthAggregator; |
| import org.springframework.boot.actuate.health.Status; |
| import org.springframework.stereotype.Component; |
| import org.springframework.util.Assert; |
| |
| @Component |
| // Modified version of org.springframework.boot.actuate.health.OrderedHealthAggregator |
| public class AcsHealthAggregator implements HealthAggregator { |
| |
| static final Status DEGRADED_STATUS = new Status(AcsMonitoringUtilities.HealthCode.DEGRADED.toString()); |
| |
| private List<String> statusOrder; |
| |
| AcsHealthAggregator() { |
| this.setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, DEGRADED_STATUS, Status.UP, Status.UNKNOWN); |
| } |
| |
| void setStatusOrder(final Status... statusOrder) { |
| String[] order = new String[statusOrder.length]; |
| for (int i = 0; i < statusOrder.length; ++i) { |
| order[i] = statusOrder[i].getCode(); |
| } |
| this.setStatusOrder(Arrays.asList(order)); |
| } |
| |
| void setStatusOrder(final List<String> statusOrder) { |
| Assert.notNull(statusOrder, "StatusOrder must not be null"); |
| this.statusOrder = statusOrder; |
| } |
| |
| @Override |
| public final Health aggregate(final Map<String, Health> healths) { |
| List<Status> statusCandidates = new ArrayList<>(); |
| for (Map.Entry<String, Health> entry : healths.entrySet()) { |
| Status status = entry.getValue().getStatus(); |
| if (entry.getKey().toLowerCase().contains("cache")) { |
| if (status.equals(Status.DOWN)) { |
| statusCandidates.add(DEGRADED_STATUS); |
| } else if (status.equals(Status.UNKNOWN)) { |
| statusCandidates.add(Status.UP); |
| } |
| } else { |
| statusCandidates.add(entry.getValue().getStatus()); |
| } |
| } |
| Status status = this.aggregateStatus(statusCandidates); |
| Map<String, Object> details = aggregateDetails(healths); |
| return new Health.Builder(status, details).build(); |
| } |
| |
| private Status aggregateStatus(final List<Status> candidates) { |
| // Only sort those status instances that we know about |
| List<Status> filteredCandidates = new ArrayList<>(); |
| for (Status candidate : candidates) { |
| if (this.statusOrder.contains(candidate.getCode())) { |
| filteredCandidates.add(candidate); |
| } |
| } |
| // If no status is given return UNKNOWN |
| if (filteredCandidates.isEmpty()) { |
| return Status.UNKNOWN; |
| } |
| // Sort given Status instances by configured order |
| filteredCandidates.sort(new StatusComparator(this.statusOrder)); |
| return filteredCandidates.get(0); |
| } |
| |
| private static Map<String, Object> aggregateDetails(final Map<String, Health> healths) { |
| return new LinkedHashMap<>(healths); |
| } |
| |
| private class StatusComparator implements Comparator<Status> { |
| |
| private final List<String> statusOrder; |
| |
| StatusComparator(final List<String> statusOrder) { |
| this.statusOrder = statusOrder; |
| } |
| |
| @Override |
| public int compare(final Status s1, final Status s2) { |
| int i1 = this.statusOrder.indexOf(s1.getCode()); |
| int i2 = this.statusOrder.indexOf(s2.getCode()); |
| if (i1 < i2) { |
| return -1; |
| } else if (i1 == i2) { |
| return s1.getCode().compareTo(s2.getCode()); |
| } else { |
| return 1; |
| } |
| } |
| } |
| } |