Skip to content

Commit

Permalink
Support error message
Browse files Browse the repository at this point in the history
  • Loading branch information
hexiaofeng committed Dec 23, 2024
1 parent 19c508a commit dcec9ab
Show file tree
Hide file tree
Showing 20 changed files with 199 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package com.jd.live.agent.governance.exception;

import com.jd.live.agent.governance.policy.service.exception.CodePolicy;
import com.jd.live.agent.governance.policy.service.exception.ErrorParserPolicy;

import java.util.Set;

Expand All @@ -27,9 +27,9 @@ public interface ErrorPolicy {
/**
* Returns the code policy associated with this component.
*
* @return the code policy
* @return the error code parse policy
*/
CodePolicy getCodePolicy();
ErrorParserPolicy getCodePolicy();

/**
* Returns a set of error codes that are considered critical by this component.
Expand All @@ -38,6 +38,20 @@ public interface ErrorPolicy {
*/
Set<String> getErrorCodes();

/**
* Returns the error message policy associated with this component.
*
* @return the error message parse policy
*/
ErrorParserPolicy getMessagePolicy();

/**
* Returns a set of error messages that are considered critical by this component.
*
* @return a set of critical error messages
*/
Set<String> getErrorMessages();

/**
* Returns a set of exceptions that are considered critical by this component.
*
Expand Down Expand Up @@ -67,6 +81,16 @@ public interface ErrorPolicy {
* @return true if the error message is found, false otherwise
*/
default boolean containsErrorMessage(String errorMessage) {
if (errorMessage != null && !errorMessage.isEmpty()) {
Set<String> messages = getErrorMessages();
if (messages != null && !messages.isEmpty()) {
for (String message : messages) {
if (message.contains(errorMessage)) {
return true;
}
}
}
}
return false;
}

Expand All @@ -86,6 +110,33 @@ default boolean containsErrorMessage(String errorMessage) {
*/
boolean containsException(Set<String> classNames);

/**
* Checks if the response body is required for error parsing.
*
* @return true if the response body is required for error parsing, false otherwise
* @see ErrorParserPolicy#requireResponseBody()
*/
default boolean requireResponseBody() {
ErrorParserPolicy codePolicy = getCodePolicy();
ErrorParserPolicy messagePolicy = getMessagePolicy();
return codePolicy != null && codePolicy.requireResponseBody() || messagePolicy != null && messagePolicy.requireResponseBody();
}

/**
* Checks if the given status code and content type match the configured values.
*
* @param status the status code to check
* @param contentType the content type to check
* @param okStatus the OK status code to consider as a match
* @return true if the status code and content type match, false otherwise
*/
default boolean match(Integer status, String contentType, Integer okStatus) {
ErrorParserPolicy codePolicy = getCodePolicy();
ErrorParserPolicy messagePolicy = getMessagePolicy();
return codePolicy != null && codePolicy.match(status, contentType, okStatus)
|| messagePolicy != null && messagePolicy.match(status, contentType, okStatus);
}

/**
* Checks if any of the exception sources are present in the set of target exceptions.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import com.jd.live.agent.core.inject.annotation.Inject;
import com.jd.live.agent.core.inject.annotation.Injectable;
import com.jd.live.agent.governance.exception.ErrorCause;
import com.jd.live.agent.governance.exception.ErrorPolicy;
import com.jd.live.agent.governance.exception.RetryException.RetryExhaustedException;
import com.jd.live.agent.governance.exception.RetryException.RetryTimeoutException;
import com.jd.live.agent.governance.exception.ServiceError;
Expand All @@ -33,12 +32,10 @@
import com.jd.live.agent.governance.policy.service.ServicePolicy;
import com.jd.live.agent.governance.policy.service.cluster.ClusterPolicy;
import com.jd.live.agent.governance.policy.service.cluster.RetryPolicy;
import com.jd.live.agent.governance.policy.service.exception.CodeParser;
import com.jd.live.agent.governance.request.Request;
import com.jd.live.agent.governance.policy.service.exception.ErrorParser;
import com.jd.live.agent.governance.request.ServiceRequest.OutboundRequest;
import com.jd.live.agent.governance.response.ServiceResponse.OutboundResponse;

import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
Expand All @@ -61,7 +58,7 @@ public class FailoverClusterInvoker extends AbstractClusterInvoker {
private static final Logger logger = LoggerFactory.getLogger(CircuitBreakerFilter.class);

@Inject
private Map<String, CodeParser> codeParsers;
private Map<String, ErrorParser> codeParsers;

@Override
public <R extends OutboundRequest,
Expand All @@ -74,9 +71,7 @@ E extends Endpoint> CompletionStage<O> execute(LiveCluster<R, O, E> cluster,
RetryPolicy retryPolicy = clusterPolicy == null ? null : clusterPolicy.getRetryPolicy();
retryPolicy = retryPolicy == null && defaultPolicy != null ? defaultPolicy.getRetryPolicy() : retryPolicy;
R request = invocation.getRequest();
if (retryPolicy != null && request.isDependentOnResponseBody(retryPolicy)) {
request.getAttributeIfAbsent(Request.KEY_ERROR_POLICY, k -> new HashSet<ErrorPolicy>()).add(retryPolicy);
}
request.addErrorPolicy(retryPolicy);
RetryContext<R, O, E> retryContext = new RetryContext<>(codeParsers, retryPolicy, cluster);
Supplier<CompletionStage<O>> supplier = () -> invoke(cluster, invocation, retryContext.getCount());
cluster.onStart(request);
Expand Down Expand Up @@ -105,7 +100,7 @@ private static class RetryContext<R extends OutboundRequest,
O extends OutboundResponse,
E extends Endpoint> {

private final Map<String, CodeParser> errorParsers;
private final Map<String, ErrorParser> errorParsers;

/**
* The retry policy defining the rules for retrying the operation.
Expand Down Expand Up @@ -133,7 +128,7 @@ private static class RetryContext<R extends OutboundRequest,
* @param retryPolicy The {@link RetryPolicy} to govern retry behavior.
* @param cluster The {@link LiveCluster} managing the distribution and processing of the request
*/
RetryContext(Map<String, CodeParser> errorParsers, RetryPolicy retryPolicy, LiveCluster<R, O, E> cluster) {
RetryContext(Map<String, ErrorParser> errorParsers, RetryPolicy retryPolicy, LiveCluster<R, O, E> cluster) {
this.errorParsers = errorParsers;
this.retryPolicy = retryPolicy;
this.cluster = cluster;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
package com.jd.live.agent.governance.invoke.filter.route;

import com.jd.live.agent.bootstrap.exception.RejectException.RejectCircuitBreakException;
import com.jd.live.agent.bootstrap.logger.Logger;
import com.jd.live.agent.bootstrap.logger.LoggerFactory;
import com.jd.live.agent.core.extension.ExtensionInitializer;
import com.jd.live.agent.core.extension.annotation.ConditionalOnProperty;
import com.jd.live.agent.core.extension.annotation.Extension;
Expand All @@ -27,7 +25,6 @@
import com.jd.live.agent.governance.config.GovernanceConfig;
import com.jd.live.agent.governance.exception.CircuitBreakException;
import com.jd.live.agent.governance.exception.ErrorCause;
import com.jd.live.agent.governance.exception.ErrorPolicy;
import com.jd.live.agent.governance.instance.Endpoint;
import com.jd.live.agent.governance.invoke.OutboundInvocation;
import com.jd.live.agent.governance.invoke.OutboundListener;
Expand All @@ -42,13 +39,11 @@
import com.jd.live.agent.governance.policy.service.ServicePolicy;
import com.jd.live.agent.governance.policy.service.circuitbreak.CircuitBreakPolicy;
import com.jd.live.agent.governance.policy.service.circuitbreak.DegradeConfig;
import com.jd.live.agent.governance.policy.service.exception.CodeParser;
import com.jd.live.agent.governance.request.Request;
import com.jd.live.agent.governance.policy.service.exception.ErrorParser;
import com.jd.live.agent.governance.request.ServiceRequest.OutboundRequest;
import com.jd.live.agent.governance.response.ServiceResponse;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
Expand All @@ -66,13 +61,11 @@
@ConditionalOnProperty(value = GovernanceConfig.CONFIG_FLOW_CONTROL_ENABLED, matchIfMissing = true)
public class CircuitBreakerFilter implements RouteFilter, ExtensionInitializer {

private static final Logger logger = LoggerFactory.getLogger(CircuitBreakerFilter.class);

@Inject
private Map<String, CircuitBreakerFactory> factories;

@Inject
private Map<String, CodeParser> errorParsers;
private Map<String, ErrorParser> errorParsers;

@Inject(nullable = true)
private CircuitBreakerFactory defaultFactory;
Expand All @@ -98,9 +91,7 @@ public <T extends OutboundRequest> void filter(OutboundInvocation<T> invocation,
CircuitBreaker breaker;
T request = invocation.getRequest();
for (CircuitBreakPolicy policy : policies) {
if (request.isDependentOnResponseBody(policy)) {
request.getAttributeIfAbsent(Request.KEY_ERROR_POLICY, k -> new HashSet<ErrorPolicy>()).add(policy);
}
request.addErrorPolicy(policy);
switch (policy.getLevel()) {
case SERVICE:
breaker = getCircuitBreaker(policy, policy.getUri());
Expand Down Expand Up @@ -213,7 +204,7 @@ private static class CircuitBreakerListener implements OutboundListener {

private final CircuitBreakerFactory factory;

private final Map<String, CodeParser> errorParsers;
private final Map<String, ErrorParser> errorParsers;

private List<CircuitBreaker> circuitBreakers;

Expand All @@ -223,7 +214,7 @@ private static class CircuitBreakerListener implements OutboundListener {


CircuitBreakerListener(CircuitBreakerFactory factory,
Map<String, CodeParser> errorParsers,
Map<String, ErrorParser> errorParsers,
List<CircuitBreaker> circuitBreakers,
List<CircuitBreakPolicy> instancePolicies) {
this.factory = factory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.jd.live.agent.governance.exception.ErrorPolicy;
import com.jd.live.agent.governance.policy.PolicyId;
import com.jd.live.agent.governance.policy.PolicyInherit;
import com.jd.live.agent.governance.policy.service.exception.CodePolicy;
import com.jd.live.agent.governance.policy.service.exception.ErrorParserPolicy;
import lombok.Getter;
import lombok.Setter;

Expand All @@ -36,7 +36,6 @@
@Getter
public class CircuitBreakPolicy extends PolicyId implements PolicyInherit.PolicyInheritWithIdGen<CircuitBreakPolicy>, ErrorPolicy {

public static final String DEFAULT_CIRCUIT_BREAKER_TYPE = "Resilience4j";
public static final String SLIDING_WINDOW_TIME = "time";
public static final String SLIDING_WINDOW_COUNT = "count";
public static final int DEFAULT_FAILURE_RATE_THRESHOLD = 50;
Expand Down Expand Up @@ -80,13 +79,23 @@ public class CircuitBreakPolicy extends PolicyId implements PolicyInherit.Policy
/**
* Code policy
*/
private CodePolicy codePolicy;
private ErrorParserPolicy codePolicy;

/**
* Error code
*/
private Set<String> errorCodes;

/**
* Error message policy
*/
private ErrorParserPolicy messagePolicy;

/**
* Collection of error messages. This parameter specifies which status codes should be considered retryable.
*/
private Set<String> errorMessages;

/**
* Exception full class names.
*/
Expand Down Expand Up @@ -154,6 +163,10 @@ public void supplement(CircuitBreakPolicy source) {
if (errorCodes == null && source.getErrorCodes() != null) {
errorCodes = new HashSet<>(source.getErrorCodes());
}
messagePolicy = source.getMessagePolicy() == null ? null : source.getMessagePolicy().clone();
if (errorMessages == null && source.getErrorMessages() != null) {
errorMessages = new HashSet<>(source.getErrorMessages());
}
if (exceptions == null && source.getExceptions() != null) {
exceptions = new HashSet<>(source.getExceptions());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
import com.jd.live.agent.governance.policy.PolicyId;
import com.jd.live.agent.governance.policy.PolicyInherit.PolicyInheritWithId;
import com.jd.live.agent.governance.policy.service.annotation.Consumer;
import com.jd.live.agent.governance.policy.service.exception.CodePolicy;
import com.jd.live.agent.governance.policy.service.exception.ErrorParserPolicy;
import lombok.Getter;
import lombok.Setter;

import java.util.HashSet;
import java.util.Set;

/**
Expand Down Expand Up @@ -59,15 +60,25 @@ public class RetryPolicy extends PolicyId implements PolicyInheritWithId<RetryPo
private Long timeout;

/**
* Code policy
* Error code policy
*/
private CodePolicy codePolicy;
private ErrorParserPolicy codePolicy;

/**
* Collection of retry error codes. This parameter specifies which status codes should be considered retryable.
*/
private Set<String> errorCodes;

/**
* Error message policy
*/
private ErrorParserPolicy messagePolicy;

/**
* Collection of retry error messages. This parameter specifies which status codes should be considered retryable.
*/
private Set<String> errorMessages;

/**
* A collection of retryable exception class names.
*/
Expand Down Expand Up @@ -101,16 +112,22 @@ public void supplement(RetryPolicy source) {
codePolicy = source.codePolicy == null ? null : source.codePolicy.clone();
}
if ((errorCodes == null || errorCodes.isEmpty()) && source.errorCodes != null) {
errorCodes = source.errorCodes;
errorCodes = new HashSet<>(source.errorCodes);
}
if (messagePolicy == null) {
messagePolicy = source.messagePolicy == null ? null : source.messagePolicy.clone();
}
if ((errorMessages == null || errorMessages.isEmpty()) && source.errorMessages != null) {
errorMessages = new HashSet<>(source.errorMessages);
}
if ((exceptions == null || exceptions.isEmpty()) && source.exceptions != null) {
exceptions = source.exceptions;
exceptions = new HashSet<>(source.exceptions);
}
if ((methods == null || methods.isEmpty()) && source.methods != null) {
methods = source.methods;
methods = new HashSet<>(source.methods);
}
if ((methodPrefixes == null || methodPrefixes.isEmpty()) && source.methodPrefixes != null) {
methodPrefixes = source.methodPrefixes;
methodPrefixes = new HashSet<>(source.methodPrefixes);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
/**
* An interface for parsing code from service responses.
*/
@Extensible("CodeParser")
public interface CodeParser {
@Extensible("ErrorParser")
public interface ErrorParser {

/**
* Parses the error from a service response using the provided expression.
Expand All @@ -30,6 +30,6 @@ public interface CodeParser {
* @param response The service response to parse.
* @return The extracted error information as a string.
*/
String getCode(String expression, Object response);
String getValue(String expression, Object response);

}
Loading

0 comments on commit dcec9ab

Please sign in to comment.