Skip to content

Commit db970b5

Browse files
HailongWenpongad
authored andcommitted
---
yaml --- r: 8711 b: refs/heads/master c: 8121f07 h: refs/heads/master i: 8709: a09e498 8707: 2518505 8703: 95fc0ab
1 parent efee99d commit db970b5

8 files changed

Lines changed: 772 additions & 7 deletions

File tree

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: ea5c83cb694461724269c9555c136db237800c9d
2+
refs/heads/master: 8121f07ceb34d87d87051731167bba06ab19757a
33
refs/heads/travis: 47e4fee4fd5af9b2a8ce46f23c72ec95f9b195b2
44
refs/heads/gh-pages: 6daca92127d91b7c2c99490080ecf8a13fa94cde
55
refs/tags/0.0.9: 22f1839238f66c39e67ed4dfdcd273b1ae2e8444

trunk/google-cloud-bom/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@
138138
<guava.version>20.0</guava.version>
139139
<http-client.version>1.23.0</http-client.version>
140140
<protobuf.version>3.5.1</protobuf.version>
141-
<opencensus.version>0.10.0</opencensus.version>
141+
<opencensus.version>0.11.1</opencensus.version>
142142

143143
<cloud.version>0.34.1-alpha-SNAPSHOT</cloud.version>
144144
<bigtable.version>0.34.1-beta-SNAPSHOT</bigtable.version>
@@ -1052,6 +1052,11 @@
10521052
<artifactId>opencensus-contrib-grpc-util</artifactId>
10531053
<version>${opencensus.version}</version>
10541054
</dependency>
1055+
<dependency>
1056+
<groupId>io.opencensus</groupId>
1057+
<artifactId>opencensus-contrib-http-util</artifactId>
1058+
<version>${opencensus.version}</version>
1059+
</dependency>
10551060

10561061
<!-- testlib deps. Only put testlib dependencies here, which are testlib packages
10571062
that correspond to another non-test package. Put pure test dependencies (e.g.

trunk/google-cloud-core-http/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,13 @@
123123
<artifactId>guava-testlib</artifactId>
124124
<scope>test</scope>
125125
</dependency>
126+
<dependency>
127+
<groupId>io.opencensus</groupId>
128+
<artifactId>opencensus-api</artifactId>
129+
</dependency>
130+
<dependency>
131+
<groupId>io.opencensus</groupId>
132+
<artifactId>opencensus-contrib-http-util</artifactId>
133+
</dependency>
126134
</dependencies>
127135
</project>
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/*
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.http;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
import com.google.api.client.http.HttpExecuteInterceptor;
21+
import com.google.api.client.http.HttpHeaders;
22+
import com.google.api.client.http.HttpRequest;
23+
import com.google.api.client.http.HttpRequestInitializer;
24+
import com.google.common.annotations.VisibleForTesting;
25+
import io.opencensus.contrib.http.util.HttpPropagationUtil;
26+
import io.opencensus.trace.SpanContext;
27+
import io.opencensus.trace.Tracer;
28+
import io.opencensus.trace.propagation.TextFormat;
29+
import java.io.IOException;
30+
import javax.annotation.Nullable;
31+
32+
/**
33+
* Provides utilities for Open Census to record http stats/trace information and propagate tracing
34+
* context.
35+
*/
36+
public final class CensusHttpModule {
37+
38+
/**
39+
* OpenCensus tracing component.
40+
* When no OpenCensus implementation is provided, it will return a no-op tracer.
41+
*/
42+
private final Tracer tracer;
43+
44+
/**
45+
* {@link TextFormat} used in tracing context propagation.
46+
*/
47+
@Nullable
48+
private final TextFormat propagationTextFormat;
49+
50+
/**
51+
* {@link TextFormat.Setter} for {@link #propagationTextFormat}.
52+
*/
53+
@Nullable
54+
private final TextFormat.Setter<HttpHeaders> propagationTextFormatSetter;
55+
56+
/**
57+
* Whether spans are stored locally.
58+
*/
59+
private final boolean isRecordEvents;
60+
61+
/**
62+
* Default HTTP propagation text formatter.
63+
*/
64+
@VisibleForTesting
65+
final static class DefaultPropagationTextFormatSetter extends TextFormat.Setter<HttpHeaders> {
66+
static final TextFormat.Setter<HttpHeaders> INSTANCE = new DefaultPropagationTextFormatSetter();
67+
68+
@Override
69+
public void put(HttpHeaders carrier, String key, String value) {
70+
carrier.set(key, value);
71+
}
72+
}
73+
74+
/**
75+
* An {@link HttpExecuteInterceptor} implementation to inject HTTP request and add getContext
76+
* information before it is executed.
77+
*/
78+
@VisibleForTesting
79+
final class CensusHttpExecuteInterceptor implements HttpExecuteInterceptor {
80+
@Nullable
81+
HttpExecuteInterceptor interceptor;
82+
83+
CensusHttpExecuteInterceptor(HttpExecuteInterceptor interceptor) {
84+
this.interceptor = interceptor;
85+
}
86+
87+
@Override
88+
public void intercept(HttpRequest request) throws IOException {
89+
checkNotNull(request);
90+
if (this.interceptor != null) {
91+
this.interceptor.intercept(request);
92+
}
93+
if (propagationTextFormat != null && propagationTextFormatSetter != null) {
94+
SpanContext spanContext = tracer.getCurrentSpan().getContext();
95+
if (!SpanContext.INVALID.equals(spanContext)) {
96+
propagationTextFormat.inject(
97+
spanContext, request.getHeaders(), propagationTextFormatSetter);
98+
}
99+
}
100+
}
101+
}
102+
103+
/**
104+
* An {@link HttpRequestInitializer} implementation to set {@link CensusHttpExecuteInterceptor} as
105+
* interceptor.
106+
*/
107+
@VisibleForTesting
108+
final class CensusHttpRequestInitializer implements HttpRequestInitializer {
109+
@Nullable
110+
HttpRequestInitializer initializer;
111+
112+
CensusHttpRequestInitializer(HttpRequestInitializer initializer) {
113+
this.initializer = initializer;
114+
}
115+
116+
@Override
117+
public void initialize(HttpRequest request) throws IOException {
118+
checkNotNull(request);
119+
if (this.initializer != null) {
120+
this.initializer.initialize(request);
121+
}
122+
request.setInterceptor(new CensusHttpExecuteInterceptor(request.getInterceptor()));
123+
}
124+
}
125+
126+
/**
127+
* Creates a {@link CensusHttpModule} with given parameters.
128+
*
129+
* @param tracer the OpenCensus {@code Tracer}.
130+
* @param isRecordEvents whether spans are stored locally.
131+
*/
132+
public CensusHttpModule(Tracer tracer, boolean isRecordEvents) {
133+
checkNotNull(tracer, "tracer");
134+
this.tracer = tracer;
135+
this.isRecordEvents = isRecordEvents;
136+
this.propagationTextFormat = HttpPropagationUtil.getCloudTraceFormat();
137+
this.propagationTextFormatSetter = DefaultPropagationTextFormatSetter.INSTANCE;
138+
}
139+
140+
/**
141+
* Returns the tracing component of OpenCensus.
142+
*
143+
* @return the tracing component of OpenCensus.
144+
*/
145+
public Tracer getTracer() {
146+
return tracer;
147+
}
148+
149+
/**
150+
* Returns whether spans are stored locally.
151+
*
152+
* @return whether spans are stored locally.
153+
*/
154+
public boolean isRecordEvents() {
155+
return isRecordEvents;
156+
}
157+
158+
/**
159+
* Returns the {@link HttpExecuteInterceptor} used when initializing the {@link HttpRequest}.
160+
*
161+
* @param initializer the original initializer which will be executed before this initializer.
162+
* @return the {@code HttpExecuteInterceptor}.
163+
*/
164+
public HttpRequestInitializer getHttpRequestInitializer(HttpRequestInitializer initializer) {
165+
return new CensusHttpRequestInitializer(initializer);
166+
}
167+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.http;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
21+
import static org.easymock.EasyMock.createMock;
22+
import static org.easymock.EasyMock.createMockBuilder;
23+
import static org.easymock.EasyMock.replay;
24+
import static org.easymock.EasyMock.verify;
25+
26+
import com.google.api.client.http.HttpExecuteInterceptor;
27+
import com.google.api.client.http.GenericUrl;
28+
import com.google.api.client.http.HttpHeaders;
29+
import com.google.api.client.http.HttpRequest;
30+
import com.google.api.client.http.HttpRequestInitializer;
31+
import com.google.api.client.http.javanet.NetHttpTransport;
32+
33+
import io.opencensus.common.Scope;
34+
import io.opencensus.trace.Span;
35+
import io.opencensus.trace.SpanContext;
36+
import io.opencensus.trace.SpanId;
37+
import io.opencensus.trace.TraceId;
38+
import io.opencensus.trace.TraceOptions;
39+
import io.opencensus.trace.Tracer;
40+
import io.opencensus.trace.Tracing;
41+
import io.opencensus.trace.propagation.TextFormat;
42+
43+
import java.io.IOException;
44+
import java.util.EnumSet;
45+
import java.util.Random;
46+
47+
import org.junit.Before;
48+
import org.junit.Rule;
49+
import org.junit.Test;
50+
import org.junit.rules.ExpectedException;
51+
import org.junit.runner.RunWith;
52+
import org.junit.runners.JUnit4;
53+
54+
/** Tests for {@link CensusHttpModule}. */
55+
@RunWith(JUnit4.class)
56+
public class CensusHttpModuleTest {
57+
58+
@Rule public final ExpectedException thrown = ExpectedException.none();
59+
60+
private final Tracer tracer = Tracing.getTracer();
61+
private final CensusHttpModule censusHttpModule = new CensusHttpModule(tracer, false);
62+
private HttpRequest httpRequest;
63+
64+
@Before
65+
public void setUp() throws IOException {
66+
httpRequest = new NetHttpTransport().createRequestFactory().buildRequest(
67+
"GET", new GenericUrl("https://www.google.com"), null);
68+
}
69+
70+
@Test
71+
public void tracerShouldNotBeNull() {
72+
assertThat(censusHttpModule.getTracer()).isNotNull();
73+
}
74+
75+
@Test
76+
public void isRecordEventsShouldBeSet() {
77+
assertThat(censusHttpModule.isRecordEvents()).isEqualTo(false);
78+
}
79+
80+
@Test
81+
public void getHttpRequestInitializerShouldReturnCorrectClass() {
82+
HttpRequestInitializer initializer = censusHttpModule.getHttpRequestInitializer(null);
83+
assertThat(initializer).isInstanceOf(CensusHttpModule.CensusHttpRequestInitializer.class);
84+
}
85+
86+
@Test
87+
public void implementationOfDefaultTextFormatSetter() {
88+
String testKey = "testKey";
89+
String testValue = "testValue";
90+
TextFormat.Setter<HttpHeaders> setter =
91+
CensusHttpModule.DefaultPropagationTextFormatSetter.INSTANCE;
92+
setter.put(httpRequest.getHeaders(), testKey, testValue);
93+
assertThat(httpRequest.getHeaders().get(testKey)).isEqualTo(testValue);
94+
}
95+
96+
@Test
97+
public void censusHttpExecuteInterceptorDisallowNullRequest() throws IOException {
98+
HttpExecuteInterceptor interceptor = censusHttpModule.new CensusHttpExecuteInterceptor(null);
99+
thrown.expect(NullPointerException.class);
100+
interceptor.intercept(null);
101+
}
102+
103+
@Test
104+
public void censusHttpExecuteInterceptorShouldExecuteOriginal() throws IOException {
105+
HttpExecuteInterceptor mockInterceptor = createMock(HttpExecuteInterceptor.class);
106+
HttpExecuteInterceptor censusInterceptor = censusHttpModule.new CensusHttpExecuteInterceptor(
107+
mockInterceptor);
108+
mockInterceptor.intercept(httpRequest);
109+
replay(mockInterceptor);
110+
censusInterceptor.intercept(httpRequest);
111+
verify(mockInterceptor);
112+
}
113+
114+
@Test
115+
public void censusHttpExecuteInterceptorShouldInjectHeader() throws IOException {
116+
Random random = new Random();
117+
SpanContext spanContext = SpanContext.create(
118+
TraceId.generateRandomId(random),
119+
SpanId.generateRandomId(random),
120+
TraceOptions.DEFAULT);
121+
Span mockSpan = createMockBuilder(Span.class)
122+
.withConstructor(SpanContext.class, EnumSet.class)
123+
.withArgs(spanContext, null)
124+
.createMock();
125+
Scope scope = tracer.withSpan(mockSpan);
126+
try {
127+
HttpExecuteInterceptor interceptor = censusHttpModule.new CensusHttpExecuteInterceptor(null);
128+
interceptor.intercept(httpRequest);
129+
assertThat(httpRequest.getHeaders().get("X-Cloud-Trace-Context")).isNotNull();
130+
} finally {
131+
scope.close();
132+
}
133+
}
134+
135+
@Test
136+
public void censusHttpRequestInitializerDisallowNullRequest() throws IOException {
137+
HttpRequestInitializer initializer = censusHttpModule.getHttpRequestInitializer(null);
138+
thrown.expect(NullPointerException.class);
139+
initializer.initialize(null);
140+
}
141+
142+
@Test
143+
public void censusHttpRequestInitializerShouldExecuteOriginal() throws IOException {
144+
HttpRequestInitializer mockOriginalInitializer = createMock(HttpRequestInitializer.class);
145+
HttpRequestInitializer censusInitializer = censusHttpModule.getHttpRequestInitializer(
146+
mockOriginalInitializer);
147+
mockOriginalInitializer.initialize(httpRequest);
148+
replay(mockOriginalInitializer);
149+
censusInitializer.initialize(httpRequest);
150+
verify(mockOriginalInitializer);
151+
}
152+
153+
@Test
154+
public void censusHttpRequestInitializerShouldSetInterceptor() throws IOException {
155+
censusHttpModule.getHttpRequestInitializer(null).initialize(httpRequest);
156+
assertThat(httpRequest.getInterceptor()).isInstanceOf(
157+
CensusHttpModule.CensusHttpExecuteInterceptor.class);
158+
}
159+
}

0 commit comments

Comments
 (0)