Skip to content

Commit f2d334f

Browse files
authored
Add hooks for performance logging. (#664)
By default it will use a NoOp logger that does not log anything.
1 parent 9a91654 commit f2d334f

9 files changed

Lines changed: 176 additions & 18 deletions

src/main/java/com/google/maps/GaeRequestHandler.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.maps.internal.ExceptionsAllowedToRetry;
3030
import com.google.maps.internal.GaePendingResult;
3131
import com.google.maps.internal.HttpHeaders;
32+
import com.google.maps.metrics.RequestMetrics;
3233
import java.net.MalformedURLException;
3334
import java.net.Proxy;
3435
import java.net.URL;
@@ -57,7 +58,8 @@ public <T, R extends ApiResponse<T>> PendingResult<T> handle(
5758
FieldNamingPolicy fieldNamingPolicy,
5859
long errorTimeout,
5960
Integer maxRetries,
60-
ExceptionsAllowedToRetry exceptionsAllowedToRetry) {
61+
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
62+
RequestMetrics metrics) {
6163
FetchOptions fetchOptions = FetchOptions.Builder.withDeadline(10);
6264
HTTPRequest req;
6365
try {
@@ -72,7 +74,14 @@ public <T, R extends ApiResponse<T>> PendingResult<T> handle(
7274
}
7375

7476
return new GaePendingResult<>(
75-
req, client, clazz, fieldNamingPolicy, errorTimeout, maxRetries, exceptionsAllowedToRetry);
77+
req,
78+
client,
79+
clazz,
80+
fieldNamingPolicy,
81+
errorTimeout,
82+
maxRetries,
83+
exceptionsAllowedToRetry,
84+
metrics);
7685
}
7786

7887
@Override
@@ -86,7 +95,8 @@ public <T, R extends ApiResponse<T>> PendingResult<T> handlePost(
8695
FieldNamingPolicy fieldNamingPolicy,
8796
long errorTimeout,
8897
Integer maxRetries,
89-
ExceptionsAllowedToRetry exceptionsAllowedToRetry) {
98+
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
99+
RequestMetrics metrics) {
90100
FetchOptions fetchOptions = FetchOptions.Builder.withDeadline(10);
91101
HTTPRequest req = null;
92102
try {
@@ -103,7 +113,14 @@ public <T, R extends ApiResponse<T>> PendingResult<T> handlePost(
103113
}
104114

105115
return new GaePendingResult<>(
106-
req, client, clazz, fieldNamingPolicy, errorTimeout, maxRetries, exceptionsAllowedToRetry);
116+
req,
117+
client,
118+
clazz,
119+
fieldNamingPolicy,
120+
errorTimeout,
121+
maxRetries,
122+
exceptionsAllowedToRetry,
123+
metrics);
107124
}
108125

109126
@Override

src/main/java/com/google/maps/GeoApiContext.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
import com.google.maps.internal.HttpHeaders;
2525
import com.google.maps.internal.StringJoin;
2626
import com.google.maps.internal.UrlSigner;
27+
import com.google.maps.metrics.NoOpRequestMetricsReporter;
28+
import com.google.maps.metrics.RequestMetrics;
29+
import com.google.maps.metrics.RequestMetricsReporter;
2730
import java.io.UnsupportedEncodingException;
2831
import java.net.Proxy;
2932
import java.net.URLEncoder;
@@ -64,6 +67,7 @@ public class GeoApiContext {
6467
private final Integer maxRetries;
6568
private final UrlSigner urlSigner;
6669
private String experienceIdHeaderValue;
70+
private final RequestMetricsReporter requestMetricsReporter;
6771

6872
/* package */
6973
GeoApiContext(
@@ -76,6 +80,7 @@ public class GeoApiContext {
7680
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
7781
Integer maxRetries,
7882
UrlSigner urlSigner,
83+
RequestMetricsReporter requestMetricsReporter,
7984
String... experienceIdHeaderValue) {
8085
this.requestHandler = requestHandler;
8186
this.apiKey = apiKey;
@@ -86,6 +91,7 @@ public class GeoApiContext {
8691
this.exceptionsAllowedToRetry = exceptionsAllowedToRetry;
8792
this.maxRetries = maxRetries;
8893
this.urlSigner = urlSigner;
94+
this.requestMetricsReporter = requestMetricsReporter;
8995
setExperienceId(experienceIdHeaderValue);
9096
}
9197

@@ -108,7 +114,8 @@ <T, R extends ApiResponse<T>> PendingResult<T> handle(
108114
FieldNamingPolicy fieldNamingPolicy,
109115
long errorTimeout,
110116
Integer maxRetries,
111-
ExceptionsAllowedToRetry exceptionsAllowedToRetry);
117+
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
118+
RequestMetrics metrics);
112119

113120
<T, R extends ApiResponse<T>> PendingResult<T> handlePost(
114121
String hostName,
@@ -120,7 +127,8 @@ <T, R extends ApiResponse<T>> PendingResult<T> handlePost(
120127
FieldNamingPolicy fieldNamingPolicy,
121128
long errorTimeout,
122129
Integer maxRetries,
123-
ExceptionsAllowedToRetry exceptionsAllowedToRetry);
130+
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
131+
RequestMetrics metrics);
124132

125133
void shutdown();
126134

@@ -206,7 +214,8 @@ <T, R extends ApiResponse<T>> PendingResult<T> get(
206214
config.hostName,
207215
config.path,
208216
config.supportsClientId,
209-
query.toString());
217+
query.toString(),
218+
requestMetricsReporter.newRequest(config.path));
210219
}
211220

212221
<T, R extends ApiResponse<T>> PendingResult<T> get(
@@ -245,7 +254,8 @@ <T, R extends ApiResponse<T>> PendingResult<T> get(
245254
config.hostName,
246255
config.path,
247256
config.supportsClientId,
248-
query.toString());
257+
query.toString(),
258+
requestMetricsReporter.newRequest(config.path));
249259
}
250260

251261
<T, R extends ApiResponse<T>> PendingResult<T> post(
@@ -280,7 +290,8 @@ <T, R extends ApiResponse<T>> PendingResult<T> post(
280290
config.fieldNamingPolicy,
281291
errorTimeout,
282292
maxRetries,
283-
exceptionsAllowedToRetry);
293+
exceptionsAllowedToRetry,
294+
requestMetricsReporter.newRequest(config.path));
284295
}
285296

286297
private <T, R extends ApiResponse<T>> PendingResult<T> getWithPath(
@@ -289,7 +300,8 @@ private <T, R extends ApiResponse<T>> PendingResult<T> getWithPath(
289300
String hostName,
290301
String path,
291302
boolean canUseClientId,
292-
String encodedPath) {
303+
String encodedPath,
304+
RequestMetrics metrics) {
293305
checkContext(canUseClientId);
294306
if (!encodedPath.startsWith("&")) {
295307
throw new IllegalArgumentException("encodedPath must start with &");
@@ -321,7 +333,8 @@ private <T, R extends ApiResponse<T>> PendingResult<T> getWithPath(
321333
fieldNamingPolicy,
322334
errorTimeout,
323335
maxRetries,
324-
exceptionsAllowedToRetry);
336+
exceptionsAllowedToRetry,
337+
metrics);
325338
}
326339

327340
private void checkContext(boolean canUseClientId) {
@@ -349,6 +362,7 @@ public static class Builder {
349362
private ExceptionsAllowedToRetry exceptionsAllowedToRetry = new ExceptionsAllowedToRetry();
350363
private Integer maxRetries;
351364
private UrlSigner urlSigner;
365+
private RequestMetricsReporter requestMetricsReporter = new NoOpRequestMetricsReporter();
352366
private String[] experienceIdHeaderValue;
353367

354368
/** Builder pattern for the enclosing {@code GeoApiContext}. */
@@ -584,6 +598,11 @@ public Builder experienceId(String... experienceId) {
584598
return this;
585599
}
586600

601+
public Builder requestMetricsReporter(RequestMetricsReporter requestMetricsReporter) {
602+
this.requestMetricsReporter = requestMetricsReporter;
603+
return this;
604+
}
605+
587606
/**
588607
* Converts this builder into a {@code GeoApiContext}.
589608
*
@@ -600,6 +619,7 @@ public GeoApiContext build() {
600619
exceptionsAllowedToRetry,
601620
maxRetries,
602621
urlSigner,
622+
requestMetricsReporter,
603623
experienceIdHeaderValue);
604624
}
605625
}

src/main/java/com/google/maps/OkHttpRequestHandler.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.maps.internal.HttpHeaders;
2323
import com.google.maps.internal.OkHttpPendingResult;
2424
import com.google.maps.internal.RateLimitExecutorService;
25+
import com.google.maps.metrics.RequestMetrics;
2526
import java.io.IOException;
2627
import java.net.Proxy;
2728
import java.util.concurrent.ExecutorService;
@@ -61,15 +62,23 @@ public <T, R extends ApiResponse<T>> PendingResult<T> handle(
6162
FieldNamingPolicy fieldNamingPolicy,
6263
long errorTimeout,
6364
Integer maxRetries,
64-
ExceptionsAllowedToRetry exceptionsAllowedToRetry) {
65+
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
66+
RequestMetrics metrics) {
6567
Request.Builder builder = new Request.Builder().get().header("User-Agent", userAgent);
6668
if (experienceIdHeaderValue != null) {
6769
builder = builder.header(HttpHeaders.X_GOOG_MAPS_EXPERIENCE_ID, experienceIdHeaderValue);
6870
}
6971
Request req = builder.url(hostName + url).build();
7072

7173
return new OkHttpPendingResult<>(
72-
req, client, clazz, fieldNamingPolicy, errorTimeout, maxRetries, exceptionsAllowedToRetry);
74+
req,
75+
client,
76+
clazz,
77+
fieldNamingPolicy,
78+
errorTimeout,
79+
maxRetries,
80+
exceptionsAllowedToRetry,
81+
metrics);
7382
}
7483

7584
@Override
@@ -83,7 +92,8 @@ public <T, R extends ApiResponse<T>> PendingResult<T> handlePost(
8392
FieldNamingPolicy fieldNamingPolicy,
8493
long errorTimeout,
8594
Integer maxRetries,
86-
ExceptionsAllowedToRetry exceptionsAllowedToRetry) {
95+
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
96+
RequestMetrics metrics) {
8797
RequestBody body = RequestBody.create(JSON, payload);
8898
Request.Builder builder = new Request.Builder().post(body).header("User-Agent", userAgent);
8999

@@ -93,7 +103,14 @@ public <T, R extends ApiResponse<T>> PendingResult<T> handlePost(
93103
Request req = builder.url(hostName + url).build();
94104

95105
return new OkHttpPendingResult<>(
96-
req, client, clazz, fieldNamingPolicy, errorTimeout, maxRetries, exceptionsAllowedToRetry);
106+
req,
107+
client,
108+
clazz,
109+
fieldNamingPolicy,
110+
errorTimeout,
111+
maxRetries,
112+
exceptionsAllowedToRetry,
113+
metrics);
97114
}
98115

99116
@Override

src/main/java/com/google/maps/internal/GaePendingResult.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.maps.PendingResult;
2929
import com.google.maps.errors.ApiException;
3030
import com.google.maps.errors.UnknownErrorException;
31+
import com.google.maps.metrics.RequestMetrics;
3132
import com.google.maps.model.AddressComponentType;
3233
import com.google.maps.model.AddressType;
3334
import com.google.maps.model.Distance;
@@ -66,6 +67,7 @@ public class GaePendingResult<T, R extends ApiResponse<T>> implements PendingRes
6667
private final FieldNamingPolicy fieldNamingPolicy;
6768
private final Integer maxRetries;
6869
private final ExceptionsAllowedToRetry exceptionsAllowedToRetry;
70+
private final RequestMetrics metrics;
6971

7072
private long errorTimeOut;
7173
private int retryCounter = 0;
@@ -90,15 +92,18 @@ public GaePendingResult(
9092
FieldNamingPolicy fieldNamingPolicy,
9193
long errorTimeOut,
9294
Integer maxRetries,
93-
ExceptionsAllowedToRetry exceptionsAllowedToRetry) {
95+
ExceptionsAllowedToRetry exceptionsAllowedToRetry,
96+
RequestMetrics metrics) {
9497
this.request = request;
9598
this.client = client;
9699
this.responseClass = responseClass;
97100
this.fieldNamingPolicy = fieldNamingPolicy;
98101
this.errorTimeOut = errorTimeOut;
99102
this.maxRetries = maxRetries;
100103
this.exceptionsAllowedToRetry = exceptionsAllowedToRetry;
104+
this.metrics = metrics;
101105

106+
metrics.startNetwork();
102107
this.call = client.fetchAsync(request);
103108
}
104109

@@ -110,7 +115,9 @@ public void setCallback(Callback<T> callback) {
110115
@Override
111116
public T await() throws ApiException, IOException, InterruptedException {
112117
try {
113-
return parseResponse(this, call.get());
118+
HTTPResponse result = call.get();
119+
metrics.endNetwork();
120+
return parseResponse(this, result);
114121
} catch (ExecutionException e) {
115122
if (e.getCause() instanceof IOException) {
116123
throw (IOException) e.getCause();
@@ -140,6 +147,19 @@ public void cancel() {
140147
@SuppressWarnings("unchecked")
141148
private T parseResponse(GaePendingResult<T, R> request, HTTPResponse response)
142149
throws IOException, ApiException, InterruptedException {
150+
try {
151+
T result = parseResponseInternal(request, response);
152+
metrics.endRequest(null, response.getResponseCode(), retryCounter);
153+
return result;
154+
} catch (Exception e) {
155+
metrics.endRequest(e, response.getResponseCode(), retryCounter);
156+
throw e;
157+
}
158+
}
159+
160+
@SuppressWarnings("unchecked")
161+
private T parseResponseInternal(GaePendingResult<T, R> request, HTTPResponse response)
162+
throws IOException, ApiException, InterruptedException {
143163
if (shouldRetry(response)) {
144164
// Retry is a blocking method, but that's OK. If we're here, we're either in an await()
145165
// call, which is blocking anyway, or we're handling a callback in a separate thread.
@@ -225,6 +245,7 @@ private T parseResponse(GaePendingResult<T, R> request, HTTPResponse response)
225245
private T retry() throws IOException, ApiException, InterruptedException {
226246
retryCounter++;
227247
LOG.info("Retrying request. Retry #{}", retryCounter);
248+
metrics.startNetwork();
228249
this.call = client.fetchAsync(request);
229250
return this.await();
230251
}

0 commit comments

Comments
 (0)