blob: c937dc6f1e0eca1c5343a6f9adc699c57ef23865 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.spring.boot.actuate.health;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.status.StatusChecker;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
* Dubbo {@link HealthIndicator}
*
* @see HealthIndicator
* @since 2.7.0
*/
public class DubboHealthIndicator extends AbstractHealthIndicator {
@Autowired
private DubboHealthIndicatorProperties dubboHealthIndicatorProperties;
@Autowired(required = false)
private Map<String, ProtocolConfig> protocolConfigs = Collections.emptyMap();
@Autowired(required = false)
private Map<String, ProviderConfig> providerConfigs = Collections.emptyMap();
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
ExtensionLoader<StatusChecker> extensionLoader = getExtensionLoader(StatusChecker.class);
Map<String, String> statusCheckerNamesMap = resolveStatusCheckerNamesMap();
boolean hasError = false;
boolean hasUnknown = false;
// Up first
builder.up();
for (Map.Entry<String, String> entry : statusCheckerNamesMap.entrySet()) {
String statusCheckerName = entry.getKey();
String source = entry.getValue();
StatusChecker checker = extensionLoader.getExtension(statusCheckerName);
org.apache.dubbo.common.status.Status status = checker.check();
org.apache.dubbo.common.status.Status.Level level = status.getLevel();
if (!hasError && level.equals(org.apache.dubbo.common.status.Status.Level.ERROR)) {
hasError = true;
builder.down();
}
if (!hasError && !hasUnknown && level.equals(org.apache.dubbo.common.status.Status.Level.UNKNOWN)) {
hasUnknown = true;
builder.unknown();
}
Map<String, Object> detail = new LinkedHashMap<>();
detail.put("source", source);
detail.put("status", status);
builder.withDetail(statusCheckerName, detail);
}
}
/**
* Resolves the map of {@link StatusChecker}'s name and its' source.
*
* @return non-null {@link Map}
*/
protected Map<String, String> resolveStatusCheckerNamesMap() {
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties());
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProtocolConfigs());
statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProviderConfig());
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties() {
DubboHealthIndicatorProperties.Status status =
dubboHealthIndicatorProperties.getStatus();
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (String statusName : status.getDefaults()) {
statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.defaults");
}
for (String statusName : status.getExtras()) {
statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.extras");
}
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromProtocolConfigs() {
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (Map.Entry<String, ProtocolConfig> entry : protocolConfigs.entrySet()) {
String beanName = entry.getKey();
ProtocolConfig protocolConfig = entry.getValue();
Set<String> statusCheckerNames = getStatusCheckerNames(protocolConfig);
for (String statusCheckerName : statusCheckerNames) {
String source = buildSource(beanName, protocolConfig);
statusCheckerNamesMap.put(statusCheckerName, source);
}
}
return statusCheckerNamesMap;
}
private Map<String, String> resolveStatusCheckerNamesMapFromProviderConfig() {
Map<String, String> statusCheckerNamesMap = new LinkedHashMap<>();
for (Map.Entry<String, ProviderConfig> entry : providerConfigs.entrySet()) {
String beanName = entry.getKey();
ProviderConfig providerConfig = entry.getValue();
Set<String> statusCheckerNames = getStatusCheckerNames(providerConfig);
for (String statusCheckerName : statusCheckerNames) {
String source = buildSource(beanName, providerConfig);
statusCheckerNamesMap.put(statusCheckerName, source);
}
}
return statusCheckerNamesMap;
}
private Set<String> getStatusCheckerNames(ProtocolConfig protocolConfig) {
String status = protocolConfig.getStatus();
return StringUtils.commaDelimitedListToSet(status);
}
private Set<String> getStatusCheckerNames(ProviderConfig providerConfig) {
String status = providerConfig.getStatus();
return StringUtils.commaDelimitedListToSet(status);
}
private String buildSource(String beanName, Object bean) {
return beanName + "@" + bean.getClass().getSimpleName() + ".getStatus()";
}
}