Skip to content

Commit

Permalink
Remove stacktrace from Catalog log when service is down (#3019)
Browse files Browse the repository at this point in the history
* Fix a few Catalog messages
  • Loading branch information
JirkaAichler authored Aug 16, 2023
1 parent c2b02c0 commit b1df6f0
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

package org.zowe.apiml.apicatalog.instance;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class EurekaServiceInstanceRequest {

private String serviceId;
private String eurekaRequestUrl;
private String username;
private String password;

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import com.netflix.discovery.converters.jackson.EurekaJsonJacksonCodec;
import com.netflix.discovery.shared.Applications;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
Expand Down Expand Up @@ -78,17 +77,18 @@ public InstanceInfo getInstanceInfo(@NotBlank(message = "Service Id must be supp
return null;
}

List<Pair<String, Pair<String, String>>> requestInfoList = constructServiceInfoQueryRequest(serviceId, false);
List<EurekaServiceInstanceRequest> eurekaServiceInstanceRequests = constructServiceInfoQueryRequest(serviceId, false);
// iterate over list of discovery services, return at first success
for (Pair<String, Pair<String, String>> requestInfo : requestInfoList) {
for (EurekaServiceInstanceRequest eurekaServiceInstanceRequest : eurekaServiceInstanceRequests) {
// call Eureka REST endpoint to fetch single or all Instances
try {
String responseBody = queryDiscoveryForInstances(requestInfo);
String responseBody = queryDiscoveryForInstances(eurekaServiceInstanceRequest);
if (responseBody != null) {
return extractSingleInstanceFromApplication(serviceId, responseBody);
}
} catch (Exception e) {
log.debug("Error getting instance info from {}, error message: {}", requestInfo.getLeft(), e.getMessage());
log.debug("Error obtaining instance information from {}, error message: {}",
eurekaServiceInstanceRequest.getEurekaRequestUrl(), e.getMessage());
}
}
String msg = "An error occurred when trying to get instance info for: " + serviceId;
Expand All @@ -103,13 +103,13 @@ public InstanceInfo getInstanceInfo(@NotBlank(message = "Service Id must be supp
*/
public Applications getAllInstancesFromDiscovery(boolean delta) {

List<Pair<String, Pair<String, String>>> requestInfoList = constructServiceInfoQueryRequest(null, delta);
for (Pair<String, Pair<String, String>> requestInfo : requestInfoList) {
List<EurekaServiceInstanceRequest> requestInfoList = constructServiceInfoQueryRequest(null, delta);
for (EurekaServiceInstanceRequest requestInfo : requestInfoList) {
try {
String responseBody = queryDiscoveryForInstances(requestInfo);
return extractApplications(responseBody);
} catch (Exception e) {
log.debug("Not able to contact discovery service: " + requestInfo.getKey(), e);
log.debug("Not able to contact discovery service: {}", requestInfo.getEurekaRequestUrl(), e);
}
}
// call Eureka REST endpoint to fetch single or all Instances
Expand Down Expand Up @@ -139,12 +139,12 @@ private Applications extractApplications(String responseBody) {
/**
* Query Discovery
*
* @param requestInfo information used to query the discovery service
* @param eurekaServiceInstanceRequest information used to query the discovery service
* @return ResponseEntity<String> query response
*/
private String queryDiscoveryForInstances(Pair<String, Pair<String, String>> requestInfo) throws IOException {
HttpGet httpGet = new HttpGet(requestInfo.getLeft());
for (Header header : createRequestHeader(requestInfo.getRight())) {
private String queryDiscoveryForInstances(EurekaServiceInstanceRequest eurekaServiceInstanceRequest) throws IOException {
HttpGet httpGet = new HttpGet(eurekaServiceInstanceRequest.getEurekaRequestUrl());
for (Header header : createRequestHeader(eurekaServiceInstanceRequest)) {
httpGet.setHeader(header);
}
CloseableHttpResponse response = httpClient.execute(httpGet);
Expand All @@ -157,9 +157,14 @@ private String queryDiscoveryForInstances(Pair<String, Pair<String, String>> req
if (statusCode >= HttpStatus.SC_OK && statusCode < HttpStatus.SC_MULTIPLE_CHOICES) {
return responseBody;
}

apimlLog.log("org.zowe.apiml.apicatalog.serviceRetrievalRequestFailed",
statusCode, response.getStatusLine() != null ? response.getStatusLine().getReasonPhrase() : responseBody,
requestInfo.getLeft());
eurekaServiceInstanceRequest.getServiceId(),
eurekaServiceInstanceRequest.getEurekaRequestUrl(),
statusCode,
response.getStatusLine() != null ? response.getStatusLine().getReasonPhrase() : responseBody
);

return null;
}

Expand Down Expand Up @@ -195,9 +200,9 @@ private InstanceInfo extractSingleInstanceFromApplication(String serviceId, Stri
* @param serviceId optional service id
* @return request information
*/
private List<Pair<String, Pair<String, String>>> constructServiceInfoQueryRequest(String serviceId, boolean getDelta) {
private List<EurekaServiceInstanceRequest> constructServiceInfoQueryRequest(String serviceId, boolean getDelta) {
String[] discoveryServiceUrls = discoveryConfigProperties.getLocations();
List<Pair<String, Pair<String, String>>> discoveryPairs = new ArrayList<>(discoveryServiceUrls.length);
List<EurekaServiceInstanceRequest> eurekaServiceInstanceRequests = new ArrayList<>(discoveryServiceUrls.length);
for (String discoveryUrl : discoveryServiceUrls) {
String discoveryServiceLocatorUrl = discoveryUrl + APPS_ENDPOINT;
if (getDelta) {
Expand All @@ -211,29 +216,32 @@ private List<Pair<String, Pair<String, String>>> constructServiceInfoQueryReques
String eurekaUsername = discoveryConfigProperties.getEurekaUserName();
String eurekaUserPassword = discoveryConfigProperties.getEurekaUserPassword();

Pair<String, String> discoveryServiceCredentials = Pair.of(eurekaUsername, eurekaUserPassword);

log.debug("Eureka credentials retrieved for user: {} {}",
eurekaUsername,
(!eurekaUserPassword.isEmpty() ? "*******" : "NO PASSWORD")
);

log.debug("Checking instance info from: " + discoveryServiceLocatorUrl);
discoveryPairs.add(Pair.of(discoveryServiceLocatorUrl, discoveryServiceCredentials));
log.debug("Querying instance information of the service {} from the URL {} with the user {} and password {}",
serviceId, discoveryServiceLocatorUrl, eurekaUsername,
eurekaUserPassword.isEmpty() ? "NO PASSWORD" : "*******");

EurekaServiceInstanceRequest eurekaServiceInstanceRequest = EurekaServiceInstanceRequest.builder()
.serviceId(serviceId)
.eurekaRequestUrl(discoveryServiceLocatorUrl)
.username(eurekaUsername)
.password(eurekaUserPassword)
.build();
eurekaServiceInstanceRequests.add(eurekaServiceInstanceRequest);
}
return discoveryPairs;

return eurekaServiceInstanceRequests;
}

/**
* Create HTTP headers
*
* @return HTTP Headers
*/
private List<Header> createRequestHeader(Pair<String, String> credentials) {
private List<Header> createRequestHeader(EurekaServiceInstanceRequest eurekaServiceInstanceRequest) {
List<Header> headers = new ArrayList<>();
if (credentials != null && credentials.getLeft() != null && credentials.getRight() != null) {
String basicToken = "Basic " + Base64.getEncoder().encodeToString((credentials.getLeft() + ":"
+ credentials.getRight()).getBytes());
if (eurekaServiceInstanceRequest != null && eurekaServiceInstanceRequest.getUsername() != null && eurekaServiceInstanceRequest.getPassword() != null) {
String basicToken = "Basic " + Base64.getEncoder().encodeToString((eurekaServiceInstanceRequest.getUsername() + ":"
+ eurekaServiceInstanceRequest.getPassword()).getBytes());
headers.add(new BasicHeader(HttpHeaders.AUTHORIZATION, basicToken));
}
headers.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.zowe.apiml.eurekaservice.client.util.EurekaMetadataParser;
import org.zowe.apiml.product.gateway.GatewayClient;
import org.zowe.apiml.product.gateway.GatewayConfigProperties;
import org.zowe.apiml.product.instance.InstanceInitializationException;
import org.zowe.apiml.product.routing.RoutedService;
import org.zowe.apiml.product.routing.RoutedServices;

Expand Down Expand Up @@ -395,11 +396,17 @@ private ApiInfo findApi(List<ApiInfo> apiInfos, String apiVersion) {
}

private InstanceInfo getInstanceInfo(String serviceId) {
InstanceInfo instanceInfo = instanceRetrievalService.getInstanceInfo(serviceId);
if (instanceInfo == null) {
throw new ApiDocNotFoundException("Could not load instance information for service " + serviceId + ".");
String errMsg = "Could not load instance information for service " + serviceId + ".";
try {
InstanceInfo instanceInfo = instanceRetrievalService.getInstanceInfo(serviceId);
if (instanceInfo == null) {
throw new ApiDocNotFoundException(errMsg);
}

return instanceInfo;
} catch (InstanceInitializationException e) {
throw new ApiDocNotFoundException(errMsg, e);
}
return instanceInfo;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ messages:
- key: org.zowe.apiml.apicatalog.serviceRetrievalRequestFailed
number: ZWEAC100
type: WARNING
text: "Could not retrieve all service info from discovery -- %s -- %s -- %s"
reason: "The response from The Discovery Service about the registered instances returned an error or empty body."
action: "Make sure the Discovery Service is up and running. If the http response error code refers to a security issue, check that both the Discovery Service and Catalog are running with the https scheme and that security is configured properly."
text: "Could not retrieve information about service %s from the Discovery Service. Requested URL: %s. Response received: status code: %s, body: %s"
reason: "The response from The Discovery Service about the registered service instances returned an error or empty body."
action: "Make sure the Discovery Service and requested service are up and running. If the HTTP response error code refers to a security issue, make sure that security configuration is correct."

- key: org.zowe.apiml.apicatalog.serviceRetrievalParsingFailed
number: ZWEAC101
Expand Down

0 comments on commit b1df6f0

Please sign in to comment.