com.netflix.zuul.niws.RequestAttempt Maven / Gradle / Ivy
/*
* Copyright 2018 Netflix, Inc.
*
* 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 com.netflix.zuul.niws;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.netflix.appinfo.AmazonInfo;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.client.config.IClientConfig;
import com.netflix.client.config.IClientConfigKey;
import com.netflix.zuul.discovery.DiscoveryResult;
import com.netflix.zuul.discovery.SimpleMetaInfo;
import com.netflix.zuul.exception.OutboundException;
import com.netflix.zuul.netty.connectionpool.OriginConnectException;
import io.netty.handler.timeout.ReadTimeoutException;
import java.net.InetAddress;
import javax.net.ssl.SSLHandshakeException;
/**
* User: [email protected]
* Date: 9/2/14
* Time: 2:52 PM
*/
public class RequestAttempt {
private static final ObjectMapper JACKSON_MAPPER = new ObjectMapper();
private int attempt;
private int status;
private long duration;
private String cause;
private String error;
private String exceptionType;
private String app;
private String asg;
private String instanceId;
private String host;
private int port;
private String ipAddress;
private String vip;
private String region;
private String availabilityZone;
private long readTimeout;
private int connectTimeout;
private int maxRetries;
public RequestAttempt(
int attemptNumber,
InstanceInfo server,
InetAddress serverAddr,
String targetVip,
String chosenWarmupLB,
int status,
String error,
String exceptionType,
int readTimeout,
int connectTimeout,
int maxRetries) {
if (attemptNumber < 1) {
throw new IllegalArgumentException("Attempt number must be greater than 0! - " + attemptNumber);
}
this.attempt = attemptNumber;
this.vip = targetVip;
if (server != null) {
this.app = server.getAppName().toLowerCase();
this.asg = server.getASGName();
this.instanceId = server.getInstanceId();
this.host = server.getHostName();
this.port = server.getPort();
// If targetVip is null, then try to use the actual server's vip.
if (targetVip == null) {
this.vip = server.getVIPAddress();
}
if (server.getDataCenterInfo() instanceof AmazonInfo) {
this.availabilityZone =
((AmazonInfo) server.getDataCenterInfo()).getMetadata().get("availability-zone");
// HACK - get region by just removing the last char from zone.
String az = getAvailabilityZone();
if (az != null && az.length() > 0) {
this.region = az.substring(0, az.length() - 1);
}
}
}
if (serverAddr != null) {
ipAddress = serverAddr.getHostAddress();
}
this.status = status;
this.error = error;
this.exceptionType = exceptionType;
this.readTimeout = readTimeout;
this.connectTimeout = connectTimeout;
this.maxRetries = maxRetries;
}
public RequestAttempt(
final DiscoveryResult server,
InetAddress serverAddr,
final IClientConfig clientConfig,
int attemptNumber,
int readTimeout) {
this.status = -1;
this.attempt = attemptNumber;
this.readTimeout = readTimeout;
if (server != null && server != DiscoveryResult.EMPTY) {
this.host = server.getHost();
this.port = server.getPort();
this.availabilityZone = server.getZone();
if (server.isDiscoveryEnabled()) {
this.app = server.getAppName().toLowerCase();
this.asg = server.getASGName();
this.instanceId = server.getServerId();
this.host = server.getHost();
this.port = server.getPort();
this.vip = server.getTarget();
this.availabilityZone = server.getAvailabilityZone();
} else {
SimpleMetaInfo metaInfo = server.getMetaInfo();
if (metaInfo != null) {
this.asg = metaInfo.getServerGroup();
this.vip = metaInfo.getServiceIdForDiscovery();
this.instanceId = metaInfo.getInstanceId();
}
}
// HACK - get region by just removing the last char from zone.
if (availabilityZone != null && availabilityZone.length() > 0) {
region = availabilityZone.substring(0, availabilityZone.length() - 1);
}
}
if (serverAddr != null) {
ipAddress = serverAddr.getHostAddress();
}
if (clientConfig != null) {
this.connectTimeout = clientConfig.get(IClientConfigKey.Keys.ConnectTimeout);
}
}
private RequestAttempt() {}
public void complete(int responseStatus, long durationMs, Throwable exception) {
if (responseStatus > -1) {
setStatus(responseStatus);
}
this.duration = durationMs;
if (exception != null) {
setException(exception);
}
}
public int getAttempt() {
return attempt;
}
public String getVip() {
return vip;
}
public int getStatus() {
return this.status;
}
public long getDuration() {
return this.duration;
}
public String getCause() {
return cause;
}
public String getError() {
return error;
}
public String getApp() {
return app;
}
public String getAsg() {
return asg;
}
public String getInstanceId() {
return instanceId;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getIpAddress() {
return ipAddress;
}
public String getRegion() {
return region;
}
public String getAvailabilityZone() {
return availabilityZone;
}
public String getExceptionType() {
return exceptionType;
}
public long getReadTimeout() {
return readTimeout;
}
public int getConnectTimeout() {
return connectTimeout;
}
public int getMaxRetries() {
return maxRetries;
}
public void setStatus(int status) {
this.status = status;
}
public void setError(String error) {
this.error = error;
}
public void setExceptionType(String exceptionType) {
this.exceptionType = exceptionType;
}
public void setApp(String app) {
this.app = app;
}
public void setAsg(String asg) {
this.asg = asg;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public void setHost(String host) {
this.host = host;
}
public void setPort(int port) {
this.port = port;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public void setVip(String vip) {
this.vip = vip;
}
public void setRegion(String region) {
this.region = region;
}
public void setAvailabilityZone(String availabilityZone) {
this.availabilityZone = availabilityZone;
}
public void setReadTimeout(long readTimeout) {
this.readTimeout = readTimeout;
}
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public void setException(Throwable t) {
if (t != null) {
if (t instanceof ReadTimeoutException) {
error = "READ_TIMEOUT";
exceptionType = t.getClass().getSimpleName();
} else if (t instanceof OriginConnectException oce) {
if (oce.getErrorType() != null) {
error = oce.getErrorType().toString();
} else {
error = "ORIGIN_CONNECT_ERROR";
}
Throwable oceCause = oce.getCause();
// unwrap ssl handshake exceptions to emit the underlying handshake failure causes
if (oceCause instanceof SSLHandshakeException sslHandshakeException
&& sslHandshakeException.getCause() != null) {
oceCause = sslHandshakeException.getCause();
}
if (oceCause != null) {
exceptionType = oce.getCause().getClass().getSimpleName();
cause = oceCause.getMessage();
} else {
exceptionType = oce.getClass().getSimpleName();
}
} else if (t instanceof OutboundException obe) {
error = obe.getOutboundErrorType().toString();
exceptionType = OutboundException.class.getSimpleName();
} else if (t instanceof SSLHandshakeException) {
error = t.getMessage();
exceptionType = t.getClass().getSimpleName();
cause = t.getCause().getMessage();
} else {
error = t.getMessage();
exceptionType = t.getClass().getSimpleName();
// for unexpected exceptions, just capture the first line of the stacktrace
// otherwise we risk large stacktraces in memory and metrics systems
StackTraceElement[] stackTraceElements = t.getStackTrace();
if (stackTraceElements.length > 0) {
cause = stackTraceElements[0].toString();
}
}
}
}
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
@Override
public String toString() {
try {
return JACKSON_MAPPER.writeValueAsString(toJsonNode());
} catch (JsonProcessingException e) {
throw new RuntimeException("Error serializing RequestAttempt!", e);
}
}
public ObjectNode toJsonNode() {
ObjectNode root = JACKSON_MAPPER.createObjectNode();
root.put("status", status);
root.put("duration", duration);
root.put("attempt", attempt);
putNullableAttribute(root, "error", error);
putNullableAttribute(root, "cause", cause);
putNullableAttribute(root, "exceptionType", exceptionType);
putNullableAttribute(root, "region", region);
putNullableAttribute(root, "availabilityZone", availabilityZone);
putNullableAttribute(root, "asg", asg);
putNullableAttribute(root, "instanceId", instanceId);
putNullableAttribute(root, "vip", vip);
putNullableAttribute(root, "ipAddress", ipAddress);
if (port > 0) {
root.put("port", port);
}
if (status < 1) {
root.put("readTimeout", readTimeout);
root.put("connectTimeout", connectTimeout);
}
return root;
}
private static ObjectNode putNullableAttribute(ObjectNode node, String name, String value) {
if (value != null) {
node.put(name, value);
}
return node;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy