10000 Enhance OpenCensus tracing instrumentation. · rchani99/google-http-java-client@d93eb99 · GitHub
[go: up one dir, main page]

Skip to content

Commit d93eb99

Browse files
HailongWenmattwhisenhunt
authored andcommitted
Enhance OpenCensus tracing instrumentation.
* Add method and instrumentation to record message events with content-length when sending/receiving request/response. * Refine API, add `volatile` modifiers to internal attributes. * Use `registerSpanNamesForCollection` to replace `setSampleToLocalSpanStore`. * Add get/set method for recordEvent so users can controll whether to expose collected spans. * Add more tests and rewrite/fix test cases with JUnit 3 style. * Fix/refine javadoc and messages.
1 parent 2f67205 commit d93eb99

File tree

3 files changed

+226
-74
lines changed

3 files changed

+226
-74
lines changed

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,6 @@ static String executeAndGetValueOfSomeCustomHeader(HttpRequest request) {
218218
/** OpenCensus tracing component. */
219219
private Tracer tracer = OpenCensusUtils.getTracer();
220220

221-
/** Prefix for tracing span name. */
222-
private static final String traceSpanNamePrefix = "Sent." + HttpRequest.class.getName() + ".";
223-
224221
/**
225222
* @param transport HTTP transport
226223
* @param requestMethod HTTP request method or {@code null} for none
@@ -865,9 +862,12 @@ public HttpResponse execute() throws IOException {
865862
Preconditions.checkNotNull(requestMethod);
866863
Preconditions.checkNotNull(url);
867864

868-
Span span = tracer.spanBuilder(traceSpanNamePrefix + "execute").startSpan();
865+
Span span = tracer
866+
.spanBuilder(OpenCensusUtils.SPAN_NAME_HTTP_REQUEST_EXECUTE)
867+
.setRecordEvents(OpenCensusUtils.isRecordEvent())
868+
.startSpan();
869869
do {
870-
span.addAnnotation("retry #" + numRetries);
870+
span.addAnnotation("retry #" + (numRetries - retriesRemaining));
871871
// Cleanup any unneeded response from a previous iteration
872872
if (response != null) {
873873
response.ignore();
@@ -911,7 +911,7 @@ public HttpResponse execute() throws IOException {
911911
headers.setUserAgent(originalUserAgent + " " + USER_AGENT_SUFFIX);
912912
}
913913
}
914-
OpenCensusUtils.propagateTracingContext(headers);
914+
OpenCensusUtils.propagateTracingContext(span, headers);
915915

916916
// headers
917917
HttpHeaders.serializeHeaders(headers, logbuf, curlbuf, logger, lowLevelHttpRequest);
@@ -994,8 +994,12 @@ public HttpResponse execute() throws IOException {
994994
lowLevelHttpRequest.setTimeout(connectTimeout, readTimeout);
995995
// switch tracing scope to current span
996996
Scope ws = tracer.withSpan(span);
997+
OpenCensusUtils.recordSentMessageEvent(span, lowLevelHttpRequest.getContentLength());
997998
try {
998999
LowLevelHttpResponse lowLevelHttpResponse = lowLevelHttpRequest.execute();
1000+
if (lowLevelHttpResponse != null) {
1001+
OpenCensusUtils.recordReceivedMessageEvent(span, lowLevelHttpResponse.getContentLength());
1002+
}
9991003
// Flag used to indicate if an exception is thrown before the response is constructed.
10001004
boolean responseConstructed = false;
10011005
try {

google-http-client/src/main/java/com/google/api/client/util/OpenCensusUtils.java

Lines changed: 118 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,25 @@
1515
package com.google.api.client.util;
1616

1717
import com.google.api.client.http.HttpHeaders;
18+
import com.google.api.client.http.HttpRequest;
1819
import com.google.api.client.http.HttpResponse;
1920
import com.google.api.client.http.HttpStatusCodes;
21+
import com.google.common.annotations.VisibleForTesting;
2022

2123
import io.opencensus.contrib.http.util.HttpPropagationUtil;
2224
import io.opencensus.trace.BlankSpan;
2325
import io.opencensus.trace.EndSpanOptions;
26+
import io.opencensus.trace.NetworkEvent;
27+
import io.opencensus.trace.NetworkEvent.Type;
2428
import io.opencensus.trace.Span;
2529
import io.opencensus.trace.Status;
2630
import io.opencensus.trace.Tracer;
2731
import io.opencensus.trace.Tracing;
2832
import io.opencensus.trace.propagation.TextFormat;
2933

3034
import java.io.IOException;
35+
import java.util.Collections;
36+
import java.util.concurrent.atomic.AtomicLong;
3137
import java.util.logging.Level;
3238
import java.util.logging.Logger;
3339
import javax.annotation.Nullable;
@@ -42,26 +48,49 @@ public class OpenCensusUtils {
4248

4349
private static final Logger LOGGER = Logger.getLogger(OpenCensusUtils.class.getName());
4450

51+
/**
52+
* Span name for tracing {@link HttpRequest#execute()}.
53+
*/
54+
public static final String SPAN_NAME_HTTP_REQUEST_EXECUTE =
55+
"Sent." + HttpRequest.class.getName() + ".execute";
56+
4557
/**
4658
* OpenCensus tracing component.
4759
* When no OpenCensus implementation is provided, it will return a no-op tracer.
4860
*/
49-
static Tracer tracer = Tracing.getTracer();
61+
private static Tracer tracer = Tracing.getTracer();
62+
63+
/**
64+
* Sequence id generator for message event.
65+
*/
66+
private static AtomicLong idGenerator = new AtomicLong();
67+
68+
/**
69+
* Whether spans should be recorded locally. Defaults to true.
70+
*/
71+
private static volatile boolean isRecordEvent = true;
5072

5173
/**
5274
* {@link TextFormat} used in tracing context propagation.
5375
*/
5476
@Nullable
55-
static TextFormat propagationTextFormat = null;
77+
@VisibleForTesting
78+
static volatile TextFormat propagationTextFormat = null;
5679

5780
/**
58-
* {@link TextFormat.Setter} for {@link activeTextFormat}.
81+
* {@link TextFormat.Setter} for {@link #propagationTextFormat}.
5982
*/
6083
@Nullable
61-
static TextFormat.Setter propagationTextFormatSetter = null;
84+
@VisibleForTesting
85+
static volatile TextFormat.Setter propagationTextFormatSetter = null;
6286

6387
/**
6488
* Sets the {@link TextFormat} used in context propagation.
89+
*
90+
* <p>This API allows users of google-http-client to specify other text format, or disable context
91+
* propagation by setting it to {@code null}. It should be used along with {@link
92+
* #setPropagationTextFormatSetter} for setting purpose. </p>
93+
*
6594
* @param textFormat the text format.
6695
*/
6796
public static void setPropagationTextFormat(@Nullable TextFormat textFormat) {
@@ -70,12 +99,28 @@ public static void setPropagationTextFormat(@Nullable TextFormat textFormat) {
7099

71100
/**
72101
* Sets the {@link TextFormat.Setter} used in context propagation.
102+
*
103+
* <p>This API allows users of google-http-client to specify other text format setter, or disable
104+
* context propagation by setting it to {@code null}. It should be used along with {@link
105+
* #setPropagationTextFormat} for setting purpose. </p>
106+
*
73107
* @param textFormatSetter the {@code TextFormat.Setter} for the text format.
74108
*/
75109
public static void setPropagationTextFormatSetter(@Nullable TextFormat.Setter textFormatSetter) {
76110
propagationTextFormatSetter = textFormatSetter;
77111
}
78112

113+
/**
114+
* Sets whether spans should be recorded locally.
115+
*
116+
* <p> This API allows users of google-http-client to turn on/off local span collection. </p>
117+
*
118+
* @param recordEvent record span locally if true.
119+
*/
120+
public static void setIsRecordEvent(boolean recordEvent) {
121+
isRecordEvent = recordEvent;
122+
}
123+
79124
/**
80125
* Returns the tracing component of OpenCensus.
81126
*
@@ -85,15 +130,27 @@ public static Tracer getTracer() {
85130
return tracer;
86131
}
87132

133+
/**
134+
* Returns whether spans should be recorded locally.
135+
*
136+
* @return whether spans should be recorded locally.
137+
*/
138+
public static boolean isRecordEvent() {
139+
return isRecordEvent;
140+
}
141+
88142
/**
89143
* Propagate information of current tracing context. This information will be injected into HTTP
90144
* header.
145+
*
146+
* @param span the span to be propagated.
147+
* @param headers the headers used in propagation.
91148
*/
92-
public static void propagateTracingContext(HttpHeaders headers) {
93-
Preconditions.checkNotNull(headers);
149+
public static void propagateTracingContext(Span span, HttpHeaders headers) {
150+
Preconditions.checkArgument(span != null, "span should not be null.");
151+
Preconditions.checkArgument(headers != null, "headers should not be null.");
94152
if (propagationTextFormat != null && propagationTextFormatSetter != null) {
95-
Span span = tracer.getCurrentSpan();
96-
if (span != null && !span.equals(BlankSpan.INSTANCE)) {
153+
if (!span.equals(BlankSpan.INSTANCE)) {
97154
propagationTextFormat.inject(span.getContext(), headers, propagationTextFormatSetter);
98155
}
99156
}
@@ -107,7 +164,7 @@ public static void propagateTracingContext(HttpHeaders headers) {
107164
*/
108165
public static EndSpanOptions getEndSpanOptions(@Nullable Integer statusCode) {
109166
// Always sample the span, but optionally export it.
110-
EndSpanOptions.Builder builder = EndSpanOptions.builder().setSampleToLocalSpanStore(true);
167+
EndSpanOptions.Builder builder = EndSpanOptions.builder();
111168
if (statusCode == null) {
112169
builder.setStatus(Status.UNKNOWN);
113170
} else if (!HttpStatusCodes.isSuccess(statusCode)) {
@@ -139,6 +196,48 @@ public static EndSpanOptions getEndSpanOptions(@Nullable Integer statusCode) {
139196
return builder.build();
140197
}
141198

199+
/**
200+
* Records a new message event which contains the size of the request content.
201+
* Note that the size represents the message size in application layer, i.e., content-length.
202+
*
203+
* @param span The {@code span} in which the send event occurs.
204+
* @param size Size of the request.
205+
*/
206+
public static void recordSentMessageEvent(Span span, long size) {
207+
recordMessageEvent(span, size, Type.SENT);
208+
}
209+
210+
/**
211+
* Records a new message event which contains the size of the response content.
212+
* Note that the size represents the message size in application layer, i.e., content-length.
213+
*
214+
* @param span The {@code span} in which the receive event occurs.
215+
* @param size Size of the response.
216+
*/
217+
public static void recordReceivedMessageEvent(Span span, long size) {
218+
recordMessageEvent(span, size, Type.RECV);
219+
}
220+
221+
/**
222+
* Records a message event of a certain {@link NetowrkEvent.Type}.
223+
* This method is package protected since {@link NetworkEvent} might be deprecated in future
224+
* releases.
225+
*
226+
* @param span The {@code span} in which the event occurs.
227+
* @param size Size of the message.
228+
* @param eventType The {@code NetworkEvent.Type} of the message event.
229+
*/
230+
@VisibleForTesting
231+
static void recordMessageEvent(Span span, long size, Type eventType) {
232+
Preconditions.checkArgument(span != null, "span should not be null.");
233+
if (size < 0) size = 0;
234+
NetworkEvent event = NetworkEvent
235+
.builder(eventType, idGenerator.getAndIncrement())
236+
.setUncompressedMessageSize(size)
237+
.build();
238+
span.addNetworkEvent(event);
239+
}
240+
142241
static {
143242
try {
144243
propagationTextFormat = HttpPropagationUtil.getCloudTraceFormat();
@@ -149,7 +248,16 @@ public void put(HttpHeaders carrier, String key, String value) {
149248
}
150249
};
151250
} catch (Exception e) {
152-
LOGGER.log(Level.WARNING, "Cannot initiate OpenCensus modules, tracing disabled", e);
251+
LOGGER.log(
252+
Level.WARNING, "Cannot initialize default OpenCensus HTTP propagation text format.", e);
253+
}
254+
255+
try {
256+
Tracing.getExportComponent().getSampledSpanStore().registerSpanNamesForCollection(
257+
Collections.<String>singletonList(SPAN_NAME_HTTP_REQUEST_EXECUTE));
258+
} catch (Exception e) {
259+
LOGGER.log(
260+
Level.WARNING, "Cannot register default OpenCensus span names for collection.", e);
153261
}
154262
}
155263

0 commit comments

Comments
 (0)
0