Skip to content

Commit c927bbe

Browse files
Cf ray improvements (#74)
* Enhance logging to include CF-RAY ID in error messages for fetch failures. * Bump version to 9.4.5 in Constants.java and gradle.properties * Add tests to verify CF-RAY ID inclusion in timeout and unexpected error responses * Fixes based on review * Retrieve CF-RAY ID from response header in onResponse method
1 parent 16a6e4e commit c927bbe

5 files changed

Lines changed: 95 additions & 16 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version=9.4.4
1+
version=9.4.5
22
SONATYPE_CONNECT_TIMEOUT_SECONDS=120

src/main/java/com/configcat/ConfigCatLogMessages.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ final class ConfigCatLogMessages {
2020
* Log message for Config Service Cache Read error. The log eventId is 2200.
2121
*/
2222
public static final String CONFIG_SERVICE_CACHE_READ_ERROR = "Error occurred while reading the cache.";
23-
/**
24-
* Log message for Fetch Failed Due To Unexpected error. The log eventId is 1103.
25-
*/
26-
public static final String FETCH_FAILED_DUE_TO_UNEXPECTED_ERROR = "Unexpected error occurred while trying to fetch config JSON. It is most likely due to a local network issue. Please make sure your application can reach the ConfigCat CDN servers (or your proxy server) over HTTP.";
2723

2824
/**
2925
* Log message for Fetch Failed Due To Invalid Sdk Key error. The log eventId is 1100.
3026
*/
3127
private static final String FETCH_FAILED_DUE_TO_INVALID_SDK_KEY_ERROR = "Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey";
28+
29+
/**
30+
* Log message for Fetch Failed Due To Unexpected error. The log eventId is 1103.
31+
*/
32+
private static final String FETCH_FAILED_DUE_TO_UNEXPECTED_ERROR = "Unexpected error occurred while trying to fetch config JSON. It is most likely due to a local network issue. Please make sure your application can reach the ConfigCat CDN servers (or your proxy server) over HTTP.";
33+
3234
/**
3335
* Log message for Fetch Failed Due To Redirect Loop error. The log eventId is 1104.
3436
*/
@@ -167,12 +169,29 @@ public static FormattableLogMessage getFetchFailedDueToUnexpectedHttpResponse(fi
167169
* @param connectTimeoutMillis Connect timeout in milliseconds.
168170
* @param readTimeoutMillis Read timeout in milliseconds.
169171
* @param writeTimeoutMillis Write timeout in milliseconds.
172+
* @param cfRayId The http response CF-RAY header value.
170173
* @return The formattable log message.
171174
*/
172-
public static FormattableLogMessage getFetchFailedDueToRequestTimeout(final Integer connectTimeoutMillis, final Integer readTimeoutMillis, final Integer writeTimeoutMillis) {
175+
public static FormattableLogMessage getFetchFailedDueToRequestTimeout(final Integer connectTimeoutMillis, final Integer readTimeoutMillis, final Integer writeTimeoutMillis, final String cfRayId) {
176+
if (cfRayId != null) {
177+
return new FormattableLogMessage("Request timed out while trying to fetch config JSON. Timeout values: [connect: %dms, read: %dms, write: %dms] %s", connectTimeoutMillis, readTimeoutMillis, writeTimeoutMillis, ConfigCatLogMessages.getCFRayIdPostFix(cfRayId));
178+
}
173179
return new FormattableLogMessage("Request timed out while trying to fetch config JSON. Timeout values: [connect: %dms, read: %dms, write: %dms]", connectTimeoutMillis, readTimeoutMillis, writeTimeoutMillis);
174180
}
175181

182+
/**
183+
* Log message for Fetch Failed Due To Unexpected error. The log eventId is 1103.
184+
*
185+
* @param cfRayId The http response CF-RAY header value.
186+
* @return The formattable log message.
187+
*/
188+
public static FormattableLogMessage getFetchFailedDueToUnexpectedError(final String cfRayId) {
189+
if (cfRayId != null) {
190+
return new FormattableLogMessage(FETCH_FAILED_DUE_TO_UNEXPECTED_ERROR + " %s", ConfigCatLogMessages.getCFRayIdPostFix(cfRayId));
191+
}
192+
return new FormattableLogMessage(FETCH_FAILED_DUE_TO_UNEXPECTED_ERROR);
193+
}
194+
176195
/**
177196
* Log message for Fetch Failed Due To Redirect Loop error. The log eventId is 1104.
178197
*

src/main/java/com/configcat/ConfigFetcher.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ private CompletableFuture<FetchResponse> executeFetchAsync(int executionCount, S
8282
}
8383

8484
} catch (Exception exception) {
85-
this.logger.error(1103, ConfigCatLogMessages.FETCH_FAILED_DUE_TO_UNEXPECTED_ERROR, exception);
85+
this.logger.error(1103, ConfigCatLogMessages.getFetchFailedDueToUnexpectedError(fetchResponse.cfRayId()), exception);
8686
return CompletableFuture.completedFuture(fetchResponse);
8787
}
8888

@@ -98,11 +98,11 @@ private CompletableFuture<FetchResponse> getResponseAsync(final String eTag) {
9898
@Override
9999
public void onFailure(@NotNull Call call, @NotNull IOException e) {
100100
int logEventId = 1103;
101-
Object message = ConfigCatLogMessages.FETCH_FAILED_DUE_TO_UNEXPECTED_ERROR;
101+
Object message = ConfigCatLogMessages.getFetchFailedDueToUnexpectedError(null);
102102
if (!isClosed.get()) {
103103
if (e instanceof SocketTimeoutException) {
104104
logEventId = 1102;
105-
message = ConfigCatLogMessages.getFetchFailedDueToRequestTimeout(httpClient.connectTimeoutMillis(), httpClient.readTimeoutMillis(), httpClient.writeTimeoutMillis());
105+
message = ConfigCatLogMessages.getFetchFailedDueToRequestTimeout(httpClient.connectTimeoutMillis(), httpClient.readTimeoutMillis(), httpClient.writeTimeoutMillis(), null);
106106
}
107107
logger.error(logEventId, message, e);
108108
}
@@ -111,8 +111,9 @@ public void onFailure(@NotNull Call call, @NotNull IOException e) {
111111

112112
@Override
113113
public void onResponse(@NotNull Call call, @NotNull Response response) {
114+
String cfRayId = null;
114115
try (ResponseBody body = response.body()) {
115-
String cfRayId = response.header("CF-RAY");
116+
cfRayId = response.header("CF-RAY");
116117
if (response.code() == 200) {
117118
String content = body != null ? body.string() : null;
118119
String eTag = response.header("ETag");
@@ -140,13 +141,13 @@ public void onResponse(@NotNull Call call, @NotNull Response response) {
140141
future.complete(FetchResponse.failed(formattableLogMessage, false, cfRayId));
141142
}
142143
} catch (SocketTimeoutException e) {
143-
FormattableLogMessage formattableLogMessage = ConfigCatLogMessages.getFetchFailedDueToRequestTimeout(httpClient.connectTimeoutMillis(), httpClient.readTimeoutMillis(), httpClient.writeTimeoutMillis());
144+
FormattableLogMessage formattableLogMessage = ConfigCatLogMessages.getFetchFailedDueToRequestTimeout(httpClient.connectTimeoutMillis(), httpClient.readTimeoutMillis(), httpClient.writeTimeoutMillis(), cfRayId);
144145
logger.error(1102, formattableLogMessage, e);
145-
future.complete(FetchResponse.failed(formattableLogMessage, false, null));
146+
future.complete(FetchResponse.failed(formattableLogMessage, false, cfRayId));
146147
} catch (Exception e) {
147-
String message = ConfigCatLogMessages.FETCH_FAILED_DUE_TO_UNEXPECTED_ERROR;
148-
logger.error(1103, message, e);
149-
future.complete(FetchResponse.failed(message, false, null));
148+
FormattableLogMessage formattableLogMessage = ConfigCatLogMessages.getFetchFailedDueToUnexpectedError(cfRayId);
149+
logger.error(1103, formattableLogMessage, e);
150+
future.complete(FetchResponse.failed(formattableLogMessage, false, cfRayId));
150151
}
151152
}
152153
});

src/main/java/com/configcat/Constants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ private Constants() { /* prevent from instantiation*/ }
77
static final long DISTANT_PAST = 0;
88
static final String CONFIG_JSON_NAME = "config_v6.json";
99
static final String SERIALIZATION_FORMAT_VERSION = "v2";
10-
static final String VERSION = "9.4.4";
10+
static final String VERSION = "9.4.5";
1111

1212
static final String SDK_KEY_PROXY_PREFIX = "configcat-proxy/";
1313
static final String SDK_KEY_PREFIX = "configcat-sdk-1";

src/test/java/com/configcat/ConfigFetcherTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import okhttp3.OkHttpClient;
66
import okhttp3.mockwebserver.MockResponse;
77
import okhttp3.mockwebserver.MockWebServer;
8+
import okhttp3.mockwebserver.SocketPolicy;
89
import org.junit.jupiter.api.AfterEach;
910
import org.junit.jupiter.api.BeforeEach;
1011
import org.junit.jupiter.api.Test;
@@ -85,6 +86,64 @@ public void fetchException() throws IOException, ExecutionException, Interrupted
8586
fetch.close();
8687
}
8788

89+
@Test
90+
public void fetchTimeOutExceptionContainsCFRayIdIfPresented() throws IOException, ExecutionException, InterruptedException {
91+
92+
ConfigFetcher fetch = new ConfigFetcher(new OkHttpClient.Builder()
93+
.readTimeout(1, TimeUnit.SECONDS)
94+
.build(),
95+
logger,
96+
"",
97+
this.server.url("/").toString(),
98+
false,
99+
PollingModes.manualPoll().getPollingIdentifier());
100+
101+
this.server.enqueue(new MockResponse().setBody("test").setHeader("CF-RAY", "12345").setBodyDelay(2, TimeUnit.SECONDS));
102+
FetchResponse response = fetch.fetchAsync(null).get();
103+
assertTrue(response.isFailed());
104+
assertTrue(response.entry().isEmpty());
105+
assertTrue(response.entry().getConfig().isEmpty());
106+
107+
assertTrue(response.error().toString().contains("Request timed out while trying to fetch config JSON."));
108+
assertTrue(response.error().toString().contains("(Ray ID: 12345)"));
109+
assertEquals("12345", response.cfRayId());
110+
111+
fetch.close();
112+
}
113+
114+
@Test
115+
public void fetchUnexpectedErrorExceptionContainsCFRayIdIfPresented() throws IOException, ExecutionException, InterruptedException {
116+
117+
ConfigFetcher fetch = new ConfigFetcher(
118+
new OkHttpClient
119+
.Builder()
120+
.readTimeout(1, TimeUnit.SECONDS)
121+
.build(),
122+
logger,
123+
"",
124+
this.server.url("/").toString(),
125+
false,
126+
PollingModes.manualPoll().getPollingIdentifier());
127+
128+
this.server.enqueue(
129+
new MockResponse()
130+
.setResponseCode(200)
131+
.setHeader("CF-RAY", "12345")
132+
.setBody("test")
133+
.setSocketPolicy(SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY));
134+
135+
FetchResponse response = fetch.fetchAsync(null).get();
136+
assertTrue(response.isFailed());
137+
assertTrue(response.entry().isEmpty());
138+
assertTrue(response.entry().getConfig().isEmpty());
139+
140+
assertTrue(response.error().toString().contains("Unexpected error occurred while trying to fetch config JSON."));
141+
assertTrue(response.error().toString().contains("(Ray ID: 12345)"));
142+
assertEquals("12345", response.cfRayId());
143+
144+
fetch.close();
145+
}
146+
88147
@Test
89148
public void fetchedETagNotUpdatesCache() throws Exception {
90149
this.server.enqueue(new MockResponse().setResponseCode(200).setBody(TEST_JSON).setHeader("ETag", "fakeETag"));

0 commit comments

Comments
 (0)