/* Copyright 2009-2015 Comcast Interactive Media, LLC.
*
* 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.
*/
package org.fishwife.jrugged;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* A {@link RolledUpMonitoredService} provides for grouping
* {@link MonitoredService} instances together into a single system for status
* reporting purposes. Subsystems are divided into <em>critical</em> and
* <em>noncritical</em> groups. The system as a whole will only report UP
* status (GREEN) if all subsystems, critical and noncritical alike, are
* likewise UP. Critical systems are necessary for providing functionality
* within the system, so the system as a whole reports the lowest
* (least functional) status of any critical systems which are not UP. If all
* critical systems are UP, but one or more noncritical systems are not UP,
* then the system as a whole will be in the DEGRADED (YELLOW) state.
*/
public class RolledUpMonitoredService implements MonitoredService {
private String name;
private Collection<? extends MonitoredService> criticals;
private Collection<? extends MonitoredService> noncriticals;
/** Initializes the {@link RolledUpMonitoredService} with its component
* subsystems.
* @param name the name for this rolled up service.
* @param criticals the set of {@link MonitoredService} subsystems
* that are necessary for the system as a whole to be functional
* @param noncriticals the set of <code>MonitoredService</code> subsystems
* that are part of the system as a whole but which are not
* strictly necessary for functionality.
*/
public RolledUpMonitoredService(String name,
Collection<? extends MonitoredService> criticals,
Collection<? extends MonitoredService> noncriticals) {
this.name = name;
this.criticals = criticals;
this.noncriticals = noncriticals;
}
/**
* Get the {@link ServiceStatus} for the rolled up service. The
* name for the ServiceStatus is the name of this rolled up service.
* The {@link Status} is computed based on the status of the critical
* and non-critical subsystems. The {@link List} of reasons contains the
* reasons reported for each system. Each service returns the service
* name in addition to the reason that it has that status (which is
* reported by the service itself)
*
* @return the {@link ServiceStatus}.
*/
public ServiceStatus getServiceStatus() {
List<String> reasons = new ArrayList<String>();
Status criticalStatus = Status.UP;
for (MonitoredService m : criticals) {
ServiceStatus serviceStatus = m.getServiceStatus();
Status status = serviceStatus.getStatus();
if (statusIsNotUp(status)) {
for (String reason : serviceStatus.getReasons()) {
reasons.add(serviceStatus.getName() + ":" + reason);
}
}
if (status.getValue() < criticalStatus.getValue()) {
criticalStatus = status;
}
}
Status result = Status.UP;
for (MonitoredService m : noncriticals) {
ServiceStatus serviceStatus = m.getServiceStatus();
Status status = serviceStatus.getStatus();
if (statusIsNotUp(status)) {
for (String reason : serviceStatus.getReasons()) {
reasons.add(serviceStatus.getName() + ":" + reason);
}
result = Status.DEGRADED;
}
}
if (criticalStatus.getValue() < result.getValue()) {
result = criticalStatus;
}
return new ServiceStatus(name, result, reasons);
}
/**
* Get the {@link List} of {@link ServiceStatus} instances for all
* subsystems.
* @return the {@link List} of {@link ServiceStatus} instances.
*/
public List<ServiceStatus> getAllStatuses() {
List<ServiceStatus> list = getCriticalStatuses();
list.addAll(getNonCriticalStatuses());
return list;
}
/**
* Get the {@link List} of {@link ServiceStatus} instances for all
* critical subsystems.
* @return the {@link List} of {@link ServiceStatus} instances.
*/
public List<ServiceStatus> getCriticalStatuses() {
List<ServiceStatus> list = new ArrayList<ServiceStatus>();
for (MonitoredService m : criticals) {
ServiceStatus serviceStatus = m.getServiceStatus();
list.add(serviceStatus);
}
return list;
}
/**
* Get the {@link List} of {@link ServiceStatus} instances for all
* non-critical subsystems.
* @return the {@link List} of {@link ServiceStatus} instances.
*/
public List<ServiceStatus> getNonCriticalStatuses() {
List<ServiceStatus> list = new ArrayList<ServiceStatus>();
for (MonitoredService m : noncriticals) {
ServiceStatus serviceStatus = m.getServiceStatus();
list.add(serviceStatus);
}
return list;
}
private boolean statusIsNotUp(Status status) {
return Status.UP != status;
}
}