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.management.mbean; 018 019import java.util.Collection; 020import java.util.Collections; 021import java.util.Optional; 022 023import javax.management.openmbean.CompositeData; 024import javax.management.openmbean.CompositeDataSupport; 025import javax.management.openmbean.CompositeType; 026import javax.management.openmbean.TabularData; 027import javax.management.openmbean.TabularDataSupport; 028 029import org.apache.camel.CamelContext; 030import org.apache.camel.RuntimeCamelException; 031import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes; 032import org.apache.camel.api.management.mbean.ManagedCamelHealthMBean; 033import org.apache.camel.health.HealthCheck; 034import org.apache.camel.health.HealthCheckHelper; 035import org.apache.camel.health.HealthCheckRegistry; 036import org.apache.camel.health.HealthCheckRepository; 037import org.apache.camel.spi.ManagementStrategy; 038import org.apache.camel.support.ExceptionHelper; 039 040public class ManagedCamelHealth implements ManagedCamelHealthMBean { 041 private final CamelContext context; 042 private final HealthCheckRegistry healthCheckRegistry; 043 044 public ManagedCamelHealth(CamelContext context, HealthCheckRegistry healthCheckRegistry) { 045 this.context = context; 046 this.healthCheckRegistry = healthCheckRegistry; 047 } 048 049 public void init(ManagementStrategy strategy) { 050 // do nothing 051 } 052 053 public CamelContext getContext() { 054 return context; 055 } 056 057 @Override 058 public boolean isEnabled() { 059 return healthCheckRegistry.isEnabled(); 060 } 061 062 @Override 063 public boolean isHealthy() { 064 for (HealthCheck.Result result : HealthCheckHelper.invoke(context)) { 065 if (result.getState() == HealthCheck.State.DOWN) { 066 return false; 067 } 068 } 069 070 return true; 071 } 072 073 @Override 074 public boolean isHealthyReadiness() { 075 for (HealthCheck.Result result : HealthCheckHelper.invokeReadiness(context)) { 076 if (result.getState() == HealthCheck.State.DOWN) { 077 return false; 078 } 079 } 080 081 return true; 082 } 083 084 @Override 085 public boolean isHealthyLiveness() { 086 for (HealthCheck.Result result : HealthCheckHelper.invokeLiveness(context)) { 087 if (result.getState() == HealthCheck.State.DOWN) { 088 return false; 089 } 090 } 091 092 return true; 093 } 094 095 @Override 096 public Collection<String> getHealthChecksIDs() { 097 return healthCheckRegistry.getCheckIDs(); 098 } 099 100 @Override 101 public TabularData details() { 102 try { 103 final TabularData answer = new TabularDataSupport(CamelOpenMBeanTypes.camelHealthDetailsTabularType()); 104 final CompositeType type = CamelOpenMBeanTypes.camelHealthDetailsCompositeType(); 105 106 for (HealthCheck.Result result : HealthCheckHelper.invoke(context)) { 107 String failureUri = (String) result.getDetails().getOrDefault(HealthCheck.ENDPOINT_URI, ""); 108 Integer failureCount = (Integer) result.getDetails().getOrDefault(HealthCheck.FAILURE_COUNT, 0); 109 110 String stacktrace = ""; 111 if (result.getError().isPresent()) { 112 stacktrace = ExceptionHelper.stackTraceToString(result.getError().get()); 113 } 114 115 CompositeData data = new CompositeDataSupport( 116 type, 117 new String[] { 118 "id", 119 "group", 120 "state", 121 "enabled", 122 "message", 123 "failureUri", 124 "failureCount", 125 "failureStackTrace", 126 "readiness", 127 "liveness" 128 }, 129 new Object[] { 130 result.getCheck().getId(), 131 result.getCheck().getGroup(), 132 result.getState().name(), 133 result.getCheck().isEnabled(), 134 result.getMessage().orElse(""), 135 failureUri, 136 failureCount, 137 stacktrace, 138 result.getCheck().isReadiness(), 139 result.getCheck().isLiveness() 140 }); 141 142 answer.put(data); 143 } 144 145 return answer; 146 } catch (Exception e) { 147 throw RuntimeCamelException.wrapRuntimeCamelException(e); 148 } 149 } 150 151 @Override 152 public String invoke(String id) { 153 Optional<HealthCheck.Result> result = HealthCheckHelper.invoke(context, id, Collections.emptyMap()); 154 155 return result.map(r -> r.getState().name()).orElse(HealthCheck.State.UNKNOWN.name()); 156 } 157 158 @Override 159 public void enableById(String id) { 160 Optional<HealthCheck> hc = healthCheckRegistry.getCheck(id); 161 if (hc.isPresent()) { 162 hc.get().setEnabled(true); 163 } else { 164 Optional<HealthCheckRepository> hcr = healthCheckRegistry.getRepository(id); 165 hcr.ifPresent(repository -> repository.setEnabled(true)); 166 } 167 } 168 169 @Override 170 public void disableById(String id) { 171 Optional<HealthCheck> hc = healthCheckRegistry.getCheck(id); 172 if (hc.isPresent()) { 173 hc.get().setEnabled(false); 174 } else { 175 Optional<HealthCheckRepository> hcr = healthCheckRegistry.getRepository(id); 176 hcr.ifPresent(repository -> repository.setEnabled(false)); 177 } 178 } 179}