2727import static org .junit .Assume .assumeFalse ;
2828import static org .junit .Assume .assumeTrue ;
2929
30+ import com .google .api .gax .core .FixedCredentialsProvider ;
3031import com .google .cloud .ByteArray ;
3132import com .google .cloud .Date ;
3233import com .google .cloud .Timestamp ;
3738import com .google .cloud .spanner .IntegrationTestEnv ;
3839import com .google .cloud .spanner .Mutation ;
3940import com .google .cloud .spanner .ParallelIntegrationTest ;
41+ import com .google .cloud .opentelemetry .trace .TraceConfiguration ;
42+ import com .google .cloud .opentelemetry .trace .TraceExporter ;
4043import com .google .cloud .spanner .ReadContext .QueryAnalyzeMode ;
4144import com .google .cloud .spanner .ResultSet ;
4245import com .google .cloud .spanner .SpannerException ;
46+ import com .google .cloud .spanner .SpannerOptions ;
47+ import com .google .cloud .spanner .SpannerOptionsHelper ;
4348import com .google .cloud .spanner .Statement ;
4449import com .google .cloud .spanner .Struct ;
4550import com .google .cloud .spanner .TimestampBound ;
4853import com .google .cloud .spanner .Value ;
4954import com .google .cloud .spanner .connection .ConnectionOptions ;
5055import com .google .cloud .spanner .testing .EmulatorSpannerHelper ;
56+ import com .google .cloud .trace .v1 .TraceServiceClient ;
57+ import com .google .cloud .trace .v1 .TraceServiceClient .ListTracesPagedResponse ;
58+ import com .google .cloud .trace .v1 .TraceServiceSettings ;
5159import com .google .common .base .Joiner ;
5260import com .google .common .collect .Iterables ;
61+ import com .google .devtools .cloudtrace .v1 .ListTracesRequest ;
62+ import com .google .devtools .cloudtrace .v1 .Trace ;
5363import com .google .spanner .v1 .ResultSetStats ;
64+ import io .opentelemetry .api .incubator .trace .ExtendedTracer ;
65+ import io .opentelemetry .api .trace .Span ;
66+ import io .opentelemetry .api .trace .Tracer ;
67+ import io .opentelemetry .api .trace .propagation .W3CTraceContextPropagator ;
68+ import io .opentelemetry .context .Scope ;
69+ import io .opentelemetry .context .propagation .ContextPropagators ;
70+ import io .opentelemetry .sdk .OpenTelemetrySdk ;
71+ import io .opentelemetry .sdk .resources .Resource ;
72+ import io .opentelemetry .sdk .trace .SdkTracerProvider ;
73+ import io .opentelemetry .sdk .trace .export .BatchSpanProcessor ;
74+ import io .opentelemetry .sdk .trace .export .SpanExporter ;
75+ import io .opentelemetry .sdk .trace .samplers .Sampler ;
76+ import java .io .IOException ;
5477import java .math .BigDecimal ;
5578import java .util .ArrayList ;
5679import java .util .Arrays ;
5780import java .util .Collections ;
5881import java .util .List ;
82+ import java .util .concurrent .ThreadLocalRandom ;
5983import org .junit .AfterClass ;
6084import org .junit .Before ;
6185import org .junit .BeforeClass ;
7094@ Category (ParallelIntegrationTest .class )
7195@ RunWith (Parameterized .class )
7296public class ITQueryTest {
97+ static {
98+ SpannerOptionsHelper .resetActiveTracingFramework ();
99+ SpannerOptions .enableOpenTelemetryMetrics ();
100+ SpannerOptions .enableOpenTelemetryTraces ();
101+ }
102+
73103 @ ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv ();
74104 private static DatabaseClient googleStandardSQLClient ;
75105 private static DatabaseClient postgreSQLClient ;
106+ private static OpenTelemetrySdk openTelemetry ;
76107 private String selectValueQuery ;
77108
78109 @ BeforeClass
@@ -87,6 +118,38 @@ public static void setUpDatabase() {
87118 }
88119 }
89120
121+ @ BeforeClass
122+ public static void setupOpenTelemetry () {
123+ assumeFalse ("This test requires credentials" , EmulatorSpannerHelper .isUsingEmulator ());
124+
125+ SpannerOptions options = env .getTestHelper ().getOptions ();
126+ TraceConfiguration .Builder traceConfigurationBuilder = TraceConfiguration .builder ();
127+ if (options .getCredentials () != null ) {
128+ traceConfigurationBuilder .setCredentials (options .getCredentials ());
129+ }
130+ TraceConfiguration traceConfiguration =
131+ traceConfigurationBuilder .setProjectId (options .getProjectId ()).build ();
132+ SpanExporter traceExporter = TraceExporter .createWithConfiguration (traceConfiguration );
133+
134+ String serviceName =
135+ "java-spanner-jdbc-integration-tests-" + ThreadLocalRandom .current ().nextInt ();
136+ openTelemetry =
137+ OpenTelemetrySdk .builder ()
138+ .setTracerProvider (
139+ SdkTracerProvider .builder ()
140+ // Always sample in this test to ensure we know what we get.
141+ .setSampler (Sampler .alwaysOn ())
142+ .setResource (Resource .builder ().put ("service.name" , serviceName ).build ())
143+ .addSpanProcessor (BatchSpanProcessor .builder (traceExporter ).build ())
144+ .build ())
145+ .setPropagators (ContextPropagators .create (W3CTraceContextPropagator .getInstance ()))
146+ .build ();
147+ options .toBuilder ().setOpenTelemetry (openTelemetry ).setEnableEndToEndTracing (true ).build ();
148+ // TODO: Remove when the bug in OpenTelemetry that has SdkTracer implement ExtendedTracer,
149+ // which is only available in the incubator project.
150+ ExtendedTracer ignore = (ExtendedTracer ) openTelemetry .getTracer ("foo" );
151+ }
152+
90153 @ AfterClass
91154 public static void teardown () {
92155 ConnectionOptions .closeSpanner ();
@@ -122,11 +185,46 @@ private DatabaseClient getClient(Dialect dialect) {
122185 }
123186
124187 @ Test
125- public void simple () {
126- Struct row = execute (Statement .of ("SELECT 1" ), Type .int64 ());
188+ public void simple () throws InterruptedException , IOException {
189+ String sql = "SELECT 1" ;
190+ Struct row = execute (Statement .of (sql ), Type .int64 ());
127191 assertThat (row .getLong (0 )).isEqualTo (1 );
128192 }
129193
194+ private void assertTrace () throws IOException , InterruptedException {
195+ com .google .protobuf .Timestamp timestamp = Timestamp .now ().toProto ();
196+ TraceServiceSettings settings =
197+ env .getTestHelper ().getOptions ().getCredentials () == null
198+ ? TraceServiceSettings .newBuilder ().build ()
199+ : TraceServiceSettings .newBuilder ()
200+ .setCredentialsProvider (
201+ FixedCredentialsProvider .create (
202+ env .getTestHelper ().getOptions ().getCredentials ()))
203+ .build ();
204+ TraceServiceClient client = TraceServiceClient .create (settings );
205+ // It can take a few seconds before the trace is visible.
206+ Thread .sleep (5000L );
207+ boolean foundTrace = false ;
208+ for (int attempts = 0 ; attempts < 2 ; attempts ++) {
209+ ListTracesPagedResponse response =
210+ client .listTraces (
211+ ListTracesRequest .newBuilder ()
212+ .setProjectId (env .getTestHelper ().getInstanceId ().getProject ())
213+ .setFilter ("span:arrayOfStruct" )
214+ // .setStartTime(timestamp)
215+ .build ());
216+ int size = Iterables .size (response .iterateAll ());
217+ if (size != 0 ) {
218+ assertEquals (1 , size );
219+ foundTrace = true ;
220+ break ;
221+ } else {
222+ Thread .sleep (5000L );
223+ }
224+ }
225+ assertTrue (foundTrace );
226+ }
227+
130228 @ Test
131229 public void badQuery () {
132230 try {
@@ -143,7 +241,10 @@ public void badQuery() {
143241 }
144242
145243 @ Test
146- public void arrayOfStruct () {
244+ public void arrayOfStruct () throws IOException , InterruptedException {
245+ Tracer tracer = openTelemetry .getTracer (ITQueryTest .class .getName ());
246+ Span span = tracer .spanBuilder ("arrayOfStruct" ).startSpan ();
247+ Scope scope = span .makeCurrent ();
147248 assumeFalse ("structs are not supported on POSTGRESQL" , dialect .dialect == Dialect .POSTGRESQL );
148249 Type structType =
149250 Type .struct (StructField .of ("C1" , Type .string ()), StructField .of ("C2" , Type .int64 ()));
@@ -154,6 +255,8 @@ public void arrayOfStruct() {
154255 + "FROM (SELECT 'a' AS C1, 1 AS C2 UNION ALL SELECT 'b' AS C1, 2 AS C2) "
155256 + "ORDER BY C1 ASC)" ),
156257 Type .array (structType ));
258+ scope .close ();
259+ span .end ();
157260 assertThat (row .isNull (0 )).isFalse ();
158261 List <Struct > value = row .getStructList (0 );
159262 assertThat (value .size ()).isEqualTo (2 );
@@ -178,6 +281,7 @@ public void arrayOfStruct() {
178281 Struct .newBuilder ().set ("C1" ).to ("b" ).set ("C2" ).to (2 ).build ()))
179282 .build ();
180283 assertThat (row ).isEqualTo (expectedRow );
284+ assertTrace ();
181285 }
182286
183287 @ Test
0 commit comments