
de.codecentric.boot.admin.server.services.endpoints.ProbeEndpointsStrategy Maven / Gradle / Ivy
/*
* Copyright 2014-2019 the original author or authors.
*
* 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 de.codecentric.boot.admin.server.services.endpoints;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.values.Endpoint;
import de.codecentric.boot.admin.server.domain.values.Endpoints;
import de.codecentric.boot.admin.server.domain.values.InstanceId;
import de.codecentric.boot.admin.server.web.client.InstanceWebClient;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.groupingBy;
public class ProbeEndpointsStrategy implements EndpointDetectionStrategy {
private static final Logger log = LoggerFactory.getLogger(ProbeEndpointsStrategy.class);
private final List endpoints;
private final InstanceWebClient instanceWebClient;
public ProbeEndpointsStrategy(InstanceWebClient instanceWebClient, String[] endpoints) {
Assert.notNull(endpoints, "'endpoints' must not be null.");
Assert.noNullElements(endpoints, "'endpoints' must not contain null.");
this.endpoints = Arrays.stream(endpoints).map(EndpointDefinition::create).collect(Collectors.toList());
this.instanceWebClient = instanceWebClient;
}
@Override
public Mono detectEndpoints(Instance instance) {
if (instance.getRegistration().getManagementUrl() == null) {
log.debug("Endpoint probe for instance {} omitted. No management-url registered.", instance.getId());
return Mono.empty();
}
return Flux.fromIterable(this.endpoints).flatMap((endpoint) -> detectEndpoint(instance, endpoint)).collectList()
.flatMap(this::convert);
}
protected Mono detectEndpoint(Instance instance, EndpointDefinition endpoint) {
URI uri = UriComponentsBuilder.fromUriString(instance.getRegistration().getManagementUrl()).path("/")
.path(endpoint.getPath()).build().toUri();
return this.instanceWebClient.instance(instance).options().uri(uri).exchange()
.flatMap(this.convert(instance.getId(), endpoint, uri)).onErrorResume((e) -> {
log.warn("Endpoint probe for instance {} on endpoint '{}' failed: {}", instance.getId(), uri,
e.getMessage());
log.debug("Endpoint probe for instance {} on endpoint '{}' failed.", instance.getId(), uri, e);
return Mono.empty();
});
}
protected Function> convert(InstanceId instanceId,
EndpointDefinition endpointDefinition, URI uri) {
return (response) -> {
Mono endpoint = Mono.empty();
if (response.statusCode().is2xxSuccessful()) {
endpoint = Mono.just(DetectedEndpoint.of(endpointDefinition, uri.toString()));
log.debug("Endpoint probe for instance {} on endpoint '{}' successful.", instanceId, uri);
}
else {
log.debug("Endpoint probe for instance {} on endpoint '{}' failed with status {}.", instanceId, uri,
response.rawStatusCode());
}
return response.releaseBody().then(endpoint);
};
}
protected Mono convert(List endpoints) {
if (endpoints.isEmpty()) {
return Mono.empty();
}
Map> endpointsById = endpoints.stream()
.collect(groupingBy((e) -> e.getDefinition().getId()));
List result = endpointsById.values().stream().map((endpointList) -> {
endpointList.sort(comparingInt((e) -> this.endpoints.indexOf(e.getDefinition())));
if (endpointList.size() > 1) {
log.warn("Duplicate endpoints for id '{}' detected. Omitting: {}",
endpointList.get(0).getDefinition().getId(), endpointList.subList(1, endpointList.size()));
}
return endpointList.get(0).getEndpoint();
}).collect(Collectors.toList());
return Mono.just(Endpoints.of(result));
}
@Data
protected static class DetectedEndpoint {
private final EndpointDefinition definition;
private final Endpoint endpoint;
private static DetectedEndpoint of(EndpointDefinition endpointDefinition, String url) {
return new DetectedEndpoint(endpointDefinition, Endpoint.of(endpointDefinition.getId(), url));
}
}
@Data
protected static class EndpointDefinition {
private final String id;
private final String path;
private static EndpointDefinition create(String idWithPath) {
int idxDelimiter = idWithPath.indexOf(':');
if (idxDelimiter < 0) {
return new EndpointDefinition(idWithPath, idWithPath);
}
else {
return new EndpointDefinition(idWithPath.substring(0, idxDelimiter),
idWithPath.substring(idxDelimiter + 1));
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy