diff --git a/.travis.yml b/.travis.yml
index 207ffd00..f144445e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,7 +18,10 @@ before_install:
# Encrypted service account file for integration testing
# This file is referenced via GOOGLE_APPLICATION_CREDENTIALS env var
# Ex. travis encrypt-file travis/zipkin-gcp-ci-0d7917f58da7.json
- - openssl aes-256-cbc -K $encrypted_0d0e64b78c84_key -iv $encrypted_0d0e64b78c84_iv -in travis/zipkin-gcp-ci-0d7917f58da7.json.enc -out travis/zipkin-gcp-ci-0d7917f58da7.json -d
+ # Only attempt to decrypt secret when it's not a PR and has access to secure env var
+ - if [ "$TRAVIS_SECURE_ENV_VARS" == "true" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
+ openssl aes-256-cbc -K $encrypted_0d0e64b78c84_key -iv $encrypted_0d0e64b78c84_iv -in travis/zipkin-gcp-ci-0d7917f58da7.json.enc -out travis/zipkin-gcp-ci-0d7917f58da7.json -d;
+ fi;
# Override default travis to use the maven wrapper; skip license on travis due to #1512
install: ./mvnw install -DskipTests=true -Dlicense.skip=true -Dmaven.javadoc.skip=true -B -V
diff --git a/autoconfigure/storage-stackdriver/pom.xml b/autoconfigure/storage-stackdriver/pom.xml
index dd0eee0e..8f844da2 100644
--- a/autoconfigure/storage-stackdriver/pom.xml
+++ b/autoconfigure/storage-stackdriver/pom.xml
@@ -68,5 +68,49 @@
hamcrest-core
test
+
+
+ io.zipkin.zipkin2
+ zipkin-tests
+ test
+
+
+
+
+ io.grpc
+ grpc-core
+ ${grpc.version}
+ test
+
+
+ io.grpc
+ grpc-protobuf
+ ${grpc.version}
+ test
+
+
+ io.grpc
+ grpc-auth
+ ${grpc.version}
+ test
+
+
+ io.grpc
+ grpc-netty-shaded
+ ${grpc.version}
+ test
+
+
+ com.google.api.grpc
+ grpc-google-cloud-trace-v1
+ ${grpc-google-cloud-trace.version}
+ test
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
diff --git a/autoconfigure/storage-stackdriver/src/test/java/zipkin2/storage/stackdriver/ITZipkinStackdriverStorage.java b/autoconfigure/storage-stackdriver/src/test/java/zipkin2/storage/stackdriver/ITZipkinStackdriverStorage.java
new file mode 100644
index 00000000..72530cda
--- /dev/null
+++ b/autoconfigure/storage-stackdriver/src/test/java/zipkin2/storage/stackdriver/ITZipkinStackdriverStorage.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2016-2019 The OpenZipkin Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package zipkin2.storage.stackdriver;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.devtools.cloudtrace.v1.GetTraceRequest;
+import com.google.devtools.cloudtrace.v1.Trace;
+import com.google.devtools.cloudtrace.v1.TraceServiceGrpc;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
+import io.grpc.auth.MoreCallCredentials;
+import org.awaitility.Duration;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.test.util.TestPropertyValues;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import zipkin.autoconfigure.storage.stackdriver.ZipkinStackdriverStorageAutoConfiguration;
+import zipkin.autoconfigure.storage.stackdriver.ZipkinStackdriverStorageProperties;
+import zipkin2.Span;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Random;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assumptions.assumeThat;
+import static org.assertj.core.api.Assumptions.assumeThatCode;
+import static org.awaitility.Awaitility.await;
+import static zipkin2.TestObjects.*;
+import static zipkin2.TestObjects.TODAY;
+
+/** Integration test against Stackdriver Trace on a real GCP project */
+public class ITZipkinStackdriverStorage {
+ final String projectId = "zipkin-gcp-ci";
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ StackdriverStorage storage;
+ ZipkinStackdriverStorageProperties storageProperties;
+ ManagedChannel channel;
+ TraceServiceGrpc.TraceServiceBlockingStub traceServiceGrpcV1;
+
+ @BeforeEach
+ public void init() throws IOException {
+ // Application Default credential is configured using the GOOGLE_APPLICATION_CREDENTIALS env var
+ // See: https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
+
+ String credentialsPath = System.getenv("GOOGLE_APPLICATION_CREDENTIALS");
+ assumeThat(credentialsPath).isNotBlank();
+ assumeThat(new File(credentialsPath)).exists();
+ assumeThatCode(GoogleCredentials::getApplicationDefault).doesNotThrowAnyException();
+
+ TestPropertyValues.of(
+ "zipkin.storage.type:stackdriver",
+ "zipkin.storage.stackdriver.project-id:" + projectId).applyTo(context);
+ context.register(
+ PropertyPlaceholderAutoConfiguration.class,
+ ZipkinStackdriverStorageAutoConfiguration.class);
+ context.refresh();
+ storage = context.getBean(StackdriverStorage.class);
+ storageProperties = context.getBean(ZipkinStackdriverStorageProperties.class);
+
+ GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
+ .createScoped("https://www.googleapis.com/auth/cloud-platform");
+
+ channel = ManagedChannelBuilder.forTarget("cloudtrace.googleapis.com")
+ .build();
+ traceServiceGrpcV1 = TraceServiceGrpc.newBlockingStub(channel)
+ .withCallCredentials(MoreCallCredentials.from(credentials));
+
+ }
+
+ @AfterEach
+ public void close() {
+ context.close();
+
+ if (channel != null) {
+ channel.shutdownNow();
+ }
+ }
+
+ @Test
+ public void healthCheck() {
+ assertThat(storage.check().ok()).isTrue();
+ }
+
+ @Test
+ public void spanConsumer() throws IOException {
+ Random random = new Random();
+ Span span = Span.newBuilder()
+ .traceId(random.nextLong(), random.nextLong())
+ .parentId("1")
+ .id("2")
+ .name("get")
+ .kind(Span.Kind.CLIENT)
+ .localEndpoint(FRONTEND)
+ .remoteEndpoint(BACKEND)
+ .timestamp((TODAY + 50L) * 1000L)
+ .duration(200000L)
+ .addAnnotation((TODAY + 100L) * 1000L, "foo")
+ .putTag("http.path", "/api")
+ .putTag("clnt/finagle.version", "6.45.0")
+ .build();
+
+
+ storage.spanConsumer().accept(asList(span)).execute();
+
+ Trace trace = await()
+ .atLeast(Duration.ONE_SECOND)
+ .atMost(Duration.TEN_SECONDS)
+ .pollInterval(Duration.ONE_SECOND)
+ .ignoreExceptionsMatching(e ->
+ e instanceof StatusRuntimeException &&
+ ((StatusRuntimeException) e).getStatus().getCode() == Status.Code.NOT_FOUND
+ )
+ .until(() -> traceServiceGrpcV1.getTrace(GetTraceRequest.newBuilder()
+ .setProjectId(projectId)
+ .setTraceId(span.traceId())
+ .build()), t -> t.getSpansCount() == 1);
+
+ assertThat(trace.getSpans(0).getSpanId()).isEqualTo(2);
+ assertThat(trace.getSpans(0).getParentSpanId()).isEqualTo(1);
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 7cd0df4c..37522270 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,9 +49,10 @@
2.16.2
2.10.2
5.6.10
- 1.22.1
+ 1.22.2
28.0-jre
3.7.1
+ 3.1.6
0.69.0
diff --git a/sender-stackdriver/pom.xml b/sender-stackdriver/pom.xml
index b6020a43..b147ccc3 100644
--- a/sender-stackdriver/pom.xml
+++ b/sender-stackdriver/pom.xml
@@ -98,7 +98,7 @@
org.awaitility
awaitility
- 3.1.6
+ ${awaitility.version}
test
diff --git a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java
index 6decceed..4a03cda9 100644
--- a/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java
+++ b/sender-stackdriver/src/test/java/zipkin2/reporter/stackdriver/ITStackdriverSender.java
@@ -37,6 +37,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
+import static org.assertj.core.api.Assumptions.assumeThatCode;
import static org.awaitility.Awaitility.await;
import static zipkin2.TestObjects.FRONTEND;
import static zipkin2.TestObjects.BACKEND;
@@ -60,6 +61,7 @@ public void setUp() throws IOException {
String credentialsPath = System.getenv("GOOGLE_APPLICATION_CREDENTIALS");
assumeThat(credentialsPath).isNotBlank();
assumeThat(new File(credentialsPath)).exists();
+ assumeThatCode(GoogleCredentials::getApplicationDefault).doesNotThrowAnyException();
credentials = GoogleCredentials.getApplicationDefault()
.createScoped(Collections.singletonList("https://www.googleapis.com/auth/trace.append"));
@@ -137,8 +139,8 @@ public void sendSpans() {
.setTraceId(span.traceId())
.build()), t -> t.getSpansCount() == 1);
- assertThat(span.id()).isEqualTo("0000000000000002");
- assertThat(span.parentId()).isEqualTo("0000000000000001");
+ assertThat(trace.getSpans(0).getSpanId()).isEqualTo(2);
+ assertThat(trace.getSpans(0).getParentSpanId()).isEqualTo(1);
}
@Test