8000 Add OpenCensus tracing instrument. · monical1/google-http-java-client@2f67205 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2f67205

Browse files
HailongWenmattwhisenhunt
authored andcommitted
Add OpenCensus tracing instrument.
1 parent d2d73b1 commit 2f67205

File tree

4 files changed

+386
-0
lines changed

4 files changed

+386
-0
lines changed

google-http-client/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,15 @@
164164
<artifactId>commons-codec</artifactId>
165165
<scope>provided</scope>
166166
</dependency>
167+
<dependency>
168+
<groupId>io.opencensus</groupId>
169+
<artifactId>opencensus-api</artifactId>
170+
<version>0.11.1</version>
171+
</dependency>
172+
<dependency>
173+
<groupId>io.opencensus</groupId>
174+
<artifactId>opencensus-contrib-http-util</artifactId>
175+
<version>0.11.1</version>
176+
</dependency>
167177
</dependencies>
168178
</project>

google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,16 @@
1818
import com.google.api.client.util.IOUtils;
1919
import com.google.api.client.util.LoggingStreamingContent;
2020
import com.google.api.client.util.ObjectParser;
21+
import com.google.api.client.util.OpenCensusUtils;
2122
import com.google.api.client.util.Preconditions;
2223
import com.google.api.client.util.Sleeper;
2324
import com.google.api.client.util.StreamingContent;
2425
import com.google.api.client.util.StringUtils;
2526

27+
import io.opencensus.common.Scope;
28+
import io.opencensus.trace.Span;
29+
import io.opencensus.trace.Tracer;
30+
2631
import java.io.IOException;
2732
import java.io.InputStream;
2833
import java.util.concurrent.Callable;
@@ -210,6 +215,12 @@ static String executeAndGetValueOfSomeCustomHeader(HttpRequest request) {
210215
/** Sleeper. */
211216
private Sleeper sleeper = Sleeper.DEFAULT;
212217

218+
/** OpenCensus tracing component. */
219+
private Tracer tracer = OpenCensusUtils.getTracer();
220+
221+
/** Prefix for tracing span name. */
222+
private static final String traceSpanNamePrefix = "Sent." + HttpRequest.class.getName() + ".";
223+
213224
/**
214225
* @param transport HTTP transport
215226
* @param requestMethod HTTP request method or {@code null} for none
@@ -854,7 +865,9 @@ public HttpResponse execute() throws IOException {
854865
Preconditions.checkNotNull(requestMethod);
855866
Preconditions.checkNotNull(url);
856867

868+
Span span = tracer.spanBuilder(traceSpanNamePrefix + "execute").startSpan();
857869
do {
870+
span.addAnnotation("retry #" + numRetries);
858871
// Cleanup any unneeded response from a previous iteration
859872
if (response != null) {
860873
response.ignore();
@@ -898,6 +911,8 @@ public HttpResponse execute() throws IOException {
898911
headers.setUserAgent(originalUserAgent + " " + USER_AGENT_SUFFIX);
899912
}
900913
}
914+
OpenCensusUtils.propagateTracingContext(headers);
915+
901916
// headers
902917
HttpHeaders.serializeHeaders(headers, logbuf, curlbuf, logger, lowLevelHttpRequest);
903918
if (!suppressUserAgentSuffix) {
@@ -977,6 +992,8 @@ public HttpResponse execute() throws IOException {
977992

978993
// execute
979994
lowLevelHttpRequest.setTimeout(connectTimeout, readTimeout);
995+
// switch tracing scope to current span
996+
Scope ws = tracer.withSpan(span);
980997
try {
981998
LowLevelHttpResponse lowLevelHttpResponse = lowLevelHttpRequest.execute();
982999
// Flag used to indicate if an exception is thrown before the response is constructed.
@@ -1002,6 +1019,8 @@ public HttpResponse execute() throws IOException {
10021019
if (loggable) {
10031020
logger.log(Level.WARNING, "exception thrown while executing request", e);
10041021
}
1022+
} finally {
1023+
ws.close();
10051024
}
10061025

10071026
// Flag used to indicate if an exception is thrown before the response has completed
@@ -1057,6 +1076,7 @@ public HttpResponse execute() throws IOException {
10571076
}
10581077
}
10591078
} while (retryRequest);
1079+
span.end(OpenCensusUtils.getEndSpanOptions(response == null ? null : response.getStatusCode()));
10601080

10611081
if (response == null) {
10621082
// Retries did not help resolve the execute exception, re-throw it.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* Copyright (c) 2018 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.google.api.client.util;
16+
17+
import com.google.api.client.http.HttpHeaders;
18+
import com.google.api.client.http.HttpResponse;
19+
import com.google.api.client.http.HttpStatusCodes;
20+
21+
import io.opencensus.contrib.http.util.HttpPropagationUtil;
22+
import io.opencensus.trace.BlankSpan;
23+
import io.opencensus.trace.EndSpanOptions;
24+
import io.opencensus.trace.Span;
25+
import io.opencensus.trace.Status;
26+
import io.opencensus.trace.Tracer;
27+
import io.opencensus.trace.Tracing;
28+
import io.opencensus.trace.propagation.TextFormat;
29+
30+
import java.io.IOException;
31+
import java.util.logging.Level;
32+
import java.util.logging.Logger;
33+
import javax.annotation.Nullable;
34+
35+
/**
36+
* Utilities for Census monitoring and tracing.
37+
*
38+
* @since 1.24
39+
* @author Hailong Wen
40+
*/
41+
public class OpenCensusUtils {
42+
43+
private static final Logger LOGGER = Logger.getLogger(OpenCensusUtils.class.getName());
44+
45+
/**
46+
* OpenCensus tracing component.
47+
* When no OpenCensus implementation is provided, it will return a no-op tracer.
48+
*/
49+
static Tracer tracer = Tracing.getTracer();
50+
51+
/**
52+
* {@link TextFormat} used in tracing context propagation.
53+
*/
54+
@Nullable
55+
static TextFormat propagationTextFormat = null;
56+
57+
/**
58+
* {@link TextFormat.Setter} for {@link activeTextFormat}.
59+
*/
60+
@Nullable
61+
static TextFormat.Setter propagationTextFormatSetter = null;
62+
63+
/**
64+
* Sets the {@link TextFormat} used in context propagation.
65+
* @param textFormat the text format.
66+
*/
67+
public static void setPropagationTextFormat(@Nullable TextFormat textFormat) {
68+
propagationTextFormat = textFormat;
69+
}
70+
71+
/**
72+
* Sets the {@link TextFormat.Setter} used in context propagation.
73+
* @param textFormatSetter the {@code TextFormat.Setter} for the text format.
74+
*/
75+
public static void setPropagationTextFormatSetter(@Nullable TextFormat.Setter textFormatSetter) {
76+
propagationTextFormatSetter = textFormatSetter;
77+
}
78+
79+
/**
80+
* Returns the tracing component of OpenCensus.
81+
*
82+
* @return the tracing component of OpenCensus.
83+
*/
84+
public static Tracer getTracer() {
85+
return tracer;
86+
}
87+
88+
/**
89+
* Propagate information of current tracing context. This information will be injected into HTTP
90+
* header.
91+
*/
92+
public static void propagateTracingContext(HttpHeaders headers) {
93+
Preconditions.checkNotNull(headers);
94+
if (propagationTextFormat != null && propagationTextFormatSetter != null) {
95+
Span span = tracer.getCurrentSpan();
96+
if (span != null && !span.equals(BlankSpan.INSTANCE)) {
97+
propagationTextFormat.inject(span.getContext(), headers, propagationTextFormatSetter);
98+
}
99+
}
100+
}
101+
102+
/**
103+
* Returns an {@link EndSpanOptions} to end a http span according to the status code.
104+
*
105+
* @param statusCode the status code, can be null to represent no valid response is returned.
106+
* @return an {@code EndSpanOptions} that best suits the status code.
107+
*/
108+
public static EndSpanOptions getEndSpanOptions(@Nullable Integer statusCode) {
109+
// Always sample the span, but optionally export it.
110+
EndSpanOptions.Builder builder = EndSpanOptions.builder().setSampleToLocalSpanStore(true);
111+
if (statusCode == null) {
112+
builder.setStatus(Status.UNKNOWN);
113+
} else if (!HttpStatusCodes.isSuccess(statusCode)) {
114+
switch (statusCode) {
115+
case HttpStatusCodes.STATUS_CODE_BAD_REQUEST:
116+
builder.setStatus(Status.INVALID_ARGUMENT);
117+
break;
118+
case HttpStatusCodes.STATUS_CODE_UNAUTHORIZED:
119+
builder.setStatus(Status.UNAUTHENTICATED);
120+
break;
121+
case HttpStatusCodes.STATUS_CODE_FORBIDDEN:
122+
builder.setStatus(Status.PERMISSION_DENIED);
123+
break;
124+
case HttpStatusCodes.STATUS_CODE_NOT_FOUND:
125+
builder.setStatus(Status.NOT_FOUND);
126+
break;
127+
case HttpStatusCodes.STATUS_CODE_PRECONDITION_FAILED:
128+
builder.setStatus(Status.FAILED_PRECONDITION);
129+
break;
130+
case HttpStatusCodes.STATUS_CODE_SERVER_ERROR:
131+
builder.setStatus(Status.UNAVAILABLE);
132+
break;
133+
default:
134+
builder.setStatus(Status.UNKNOWN);
135+
}
136+
} else {
137+
builder.setStatus(Status.OK);
138+
}
139+
return builder.build();
140+
}
141+
142+
static {
143+
try {
144+
propagationTextFormat = HttpPropagationUtil.getCloudTraceFormat();
145+
propagationTextFormatSetter = new TextFormat.Setter<HttpHeaders>() {
146+
@Override
147+
public void put(HttpHeaders carrier, String key, String value) {
148+
carrier.set(key, value);
149+
}
150+
};
151+
} catch (Exception e) {
152+
LOGGER.log(Level.WARNING, "Cannot initiate OpenCensus modules, tracing disabled", e);
153+
}
154+
}
155+
156+
private OpenCensusUtils() {}
157+
}

0 commit comments

Comments
 (0)
0