001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.health; 018 019import java.util.Collection; 020import java.util.Collections; 021import java.util.Comparator; 022import java.util.Map; 023import java.util.Optional; 024import java.util.function.Function; 025import java.util.stream.Collectors; 026 027import org.apache.camel.CamelContext; 028import org.apache.camel.util.ObjectHelper; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032public final class HealthCheckHelper { 033 private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheckHelper.class); 034 035 private HealthCheckHelper() { 036 } 037 038 /** 039 * Get the group of the given check or an empty string if the group is not set. 040 * 041 * @param check the health check 042 * @return the {@link HealthCheck#getGroup()} or an empty string if it is <code>null</code> 043 */ 044 public static String getGroup(HealthCheck check) { 045 return ObjectHelper.supplyIfEmpty(check.getGroup(), () -> ""); 046 } 047 048 /** 049 * Invokes the checks and returns a collection of results. 050 */ 051 public static Collection<HealthCheck.Result> invoke(CamelContext camelContext) { 052 return invoke(camelContext, check -> Collections.emptyMap(), check -> false); 053 } 054 055 /** 056 * Invokes the checks and returns a collection of results. 057 */ 058 public static Collection<HealthCheck.Result> invoke( 059 CamelContext camelContext, 060 Function<HealthCheck, Map<String, Object>> optionsSupplier) { 061 062 return invoke(camelContext, optionsSupplier, check -> false); 063 } 064 065 /** 066 * Invokes the checks and returns a collection of results. 067 */ 068 public static Collection<HealthCheck.Result> invoke( 069 CamelContext camelContext, 070 HealthCheckFilter filter) { 071 072 return invoke(camelContext, check -> Collections.emptyMap(), filter); 073 } 074 075 /** 076 * Invokes the checks and returns a collection of results. 077 * 078 * @param camelContext the camel context. 079 * @param optionsSupplier a supplier for options. 080 * @param filter filter to exclude some checks. 081 */ 082 public static Collection<HealthCheck.Result> invoke( 083 CamelContext camelContext, 084 Function<HealthCheck, Map<String, Object>> optionsSupplier, 085 HealthCheckFilter filter) { 086 087 final HealthCheckRegistry registry = HealthCheckRegistry.get(camelContext); 088 final HealthCheckService service = camelContext.hasService(HealthCheckService.class); 089 090 if (service != null) { 091 // If a health check service is defined retrieve the current status 092 // of the checks hold by the service. 093 return service.getResults().stream() 094 .filter(result -> !filter.test(result.getCheck())) 095 .collect(Collectors.toList()); 096 } else if (registry != null) { 097 // If no health check service is defined, this endpoint invokes the 098 // check one by one. 099 return registry.stream() 100 .collect(Collectors.groupingBy(HealthCheckHelper::getGroup)) 101 .entrySet().stream() 102 .map(Map.Entry::getValue) 103 .flatMap(Collection::stream) 104 .filter(check -> !filter.test(check)) 105 .sorted(Comparator.comparingInt(HealthCheck::getOrder)) 106 .map(check -> check.call(optionsSupplier.apply(check))) 107 .collect(Collectors.toList()); 108 } else { 109 LOGGER.debug("No health check source found"); 110 } 111 112 return Collections.emptyList(); 113 } 114 115 /** 116 * Query the status of a check by id. Note that this may result in an effective 117 * invocation of the {@link HealthCheck}, i.e. when no {@link HealthCheckService} 118 * is available. 119 * 120 * @param camelContext the camel context. 121 * @param id the check id. 122 * @param options the check options. 123 * @return an optional {@link HealthCheck.Result}. 124 */ 125 public static Optional<HealthCheck.Result> query(CamelContext camelContext, String id, Map<String, Object> options) { 126 final HealthCheckRegistry registry = HealthCheckRegistry.get(camelContext); 127 final HealthCheckService service = camelContext.hasService(HealthCheckService.class); 128 129 if (service != null) { 130 return service.getResults().stream() 131 .filter(result -> ObjectHelper.equal(result.getCheck().getId(), id)) 132 .findFirst(); 133 } else if (registry != null) { 134 return registry.getCheck(id).map(check -> check.call(options)); 135 } else { 136 LOGGER.debug("No health check source found"); 137 } 138 139 return Optional.empty(); 140 } 141 142 /** 143 * Invoke a check by id. 144 * 145 * @param camelContext the camel context. 146 * @param id the check id. 147 * @param options the check options. 148 * @return an optional {@link HealthCheck.Result}. 149 */ 150 public static Optional<HealthCheck.Result> invoke(CamelContext camelContext, String id, Map<String, Object> options) { 151 final HealthCheckRegistry registry = HealthCheckRegistry.get(camelContext); 152 final HealthCheckService service = camelContext.hasService(HealthCheckService.class); 153 154 if (service != null) { 155 return service.call(id, options); 156 } else if (registry != null) { 157 return registry.getCheck(id).map(check -> check.call(options)); 158 } else { 159 LOGGER.debug("No health check source found"); 160 } 161 162 return Optional.empty(); 163 } 164}