Skip to content

Commit

Permalink
Fix gRPC Retry Mechanism for Unsuccessful HTTP Responses (#6829)
Browse files Browse the repository at this point in the history
  • Loading branch information
JiwonKKang authored Oct 29, 2024
1 parent 74579aa commit 740dd14
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,12 @@ public CompletableResultCode shutdown() {

/** Whether response is retriable or not. */
public static boolean isRetryable(Response response) {
// Only retry on gRPC codes which will always come with an HTTP success
if (!response.isSuccessful()) {
return false;
}

// We don't check trailers for retry since retryable error codes always come with response
// headers, not trailers, in practice.
String grpcStatus = response.header(GRPC_STATUS);
if (grpcStatus == null) {
return false;
}
return RetryUtil.retryableGrpcStatusCodes().contains(grpcStatus);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.exporter.sender.okhttp.internal;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import io.opentelemetry.exporter.internal.RetryUtil;
import io.opentelemetry.exporter.internal.grpc.GrpcExporterUtil;
import java.util.Set;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

class OkHttpGrpcSenderTest {

private static final String GRPC_STATUS = "grpc-status";
private static final MediaType TEXT_PLAIN = MediaType.get("text/plain");

static Set<String> provideRetryableGrpcStatusCodes() {
return RetryUtil.retryableGrpcStatusCodes();
}

@ParameterizedTest(name = "isRetryable should return true for GRPC status code: {0}")
@MethodSource("provideRetryableGrpcStatusCodes")
void isRetryable_RetryableGrpcStatus(String retryableGrpcStatus) {
Response response = createResponse(503, retryableGrpcStatus, "Retryable");
boolean isRetryable = OkHttpGrpcSender.isRetryable(response);
assertTrue(isRetryable);
}

@Test
void isRetryable_NonRetryableGrpcStatus() {
String nonRetryableGrpcStatus =
Integer.valueOf(GrpcExporterUtil.GRPC_STATUS_UNKNOWN).toString(); // INVALID_ARGUMENT
Response response = createResponse(503, nonRetryableGrpcStatus, "Non-retryable");
boolean isRetryable = OkHttpGrpcSender.isRetryable(response);
assertFalse(isRetryable);
}

private static Response createResponse(int httpCode, String grpcStatus, String message) {
return new Response.Builder()
.request(new Request.Builder().url("http://localhost/").build())
.protocol(Protocol.HTTP_2)
.code(httpCode)
.body(ResponseBody.create("body", TEXT_PLAIN))
.message(message)
.header(GRPC_STATUS, grpcStatus)
.build();
}
}

0 comments on commit 740dd14

Please sign in to comment.