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