Skip to content

Commit 727e383

Browse files
feat(spanner): New Sample for OpenTelemetry Traces (#9400)
* feat(spanner): New Sample for OpenTelemetry Traces * Improved documentation as per comments * Apply suggestions from code review Co-authored-by: Knut Olav Løite <[email protected]> * review comments --------- Co-authored-by: Knut Olav Løite <[email protected]>
1 parent 9086741 commit 727e383

File tree

3 files changed

+300
-0
lines changed

3 files changed

+300
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Cloud Spanner OpenTelemetry Traces
2+
3+
## Setup
4+
5+
This sample requires [Java](https://www.java.com/en/download/) and [Maven](http://maven.apache.org/).
6+
7+
1. **Follow the set-up instructions in [the documentation](https://cloud.google.com/java/docs/setup).**
8+
9+
2. Enable APIs for your project.
10+
11+
a. [Click here](https://console.cloud.google.com/flows/enableapi?apiid=spanner.googleapis.com&showconfirmation=true)
12+
to visit Cloud Platform Console and enable the Google Cloud Spanner API.
13+
14+
b. [Click here](https://console.cloud.google.com/flows/enableapi?apiid=cloudtrace.googleapis.com&showconfirmation=true)
15+
to visit Cloud Platform Console and enable the Cloud Trace API.
16+
17+
3. Create a Cloud Spanner instance and database via the Cloud Plaform Console's
18+
[Cloud Spanner section](http://console.cloud.google.com/spanner).
19+
20+
4. Enable application default credentials by running the command `gcloud auth application-default login`.
21+
22+
## Run the Example
23+
24+
1. Set up database configuration in the `OpenTelemetryUsage.java` class:
25+
````
26+
String projectId = "my-project";
27+
String instanceId = "my-instance";
28+
String databaseId = "my-database";
29+
````
30+
31+
2. Configure trace data export. You can use either the OpenTelemetry [Collector](https://opentelemetry.io/docs/collector/quick-start/ with the OTLP Exporter or the Cloud Trace Exporter. By default, the Cloud Trace Exporter is used.
32+
33+
- To use OTLP Exporter, Set up the OpenTelemetry [Collector](https://opentelemetry.io/docs/collector/quick-start/) and update the OTLP endpoint in `OpenTelemetryUsage.java` class
34+
````
35+
boolean useCloudTraceExporter = true; // Replace to false for OTLP
36+
String otlpEndpoint = "http://localhost:4317"; // Replace with your OTLP endpoint
37+
````
38+
39+
3. You can also enable API Tracing and SQL Statement Tracing by setting below options. Refer [Traces](https://github.com/googleapis/java-spanner?tab=readme-ov-file#traces) for more details.
40+
````
41+
SpannerOptions options = SpannerOptions.newBuilder()
42+
.setOpenTelemetry(openTelemetry)
43+
.setEnableExtendedTracing(true)
44+
.setEnableApiTracing(true)
45+
.build();
46+
````
47+
48+
4. Then run the application from command line, after switching to this directory:
49+
````
50+
mvn exec:java -Dexec.mainClass="com.example.spanner.OpenTelemetryUsage"
51+
````
52+
53+
You should start seeing traces in Cloud Trace .
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.example.spanner</groupId>
8+
<artifactId>opentelemetry_traces</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<properties>
12+
<maven.compiler.source>1.8</maven.compiler.source>
13+
<maven.compiler.target>1.8</maven.compiler.target>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
17+
<!--
18+
The parent pom defines common style checks and testing strategies for our samples.
19+
Removing or replacing it should not affect the execution of the samples in anyway.
20+
-->
21+
<parent>
22+
<groupId>com.google.cloud.samples</groupId>
23+
<artifactId>shared-configuration</artifactId>
24+
<version>1.2.0</version>
25+
</parent>
26+
27+
<dependencyManagement>
28+
<dependencies>
29+
<dependency>
30+
<groupId>com.google.cloud</groupId>
31+
<artifactId>libraries-bom</artifactId>
32+
<version>26.34.0</version>
33+
<type>pom</type>
34+
<scope>import</scope>
35+
</dependency>
36+
<dependency>
37+
<groupId>io.opentelemetry</groupId>
38+
<artifactId>opentelemetry-bom</artifactId>
39+
<version>1.38.0</version>
40+
<type>pom</type>
41+
<scope>import</scope>
42+
</dependency>
43+
</dependencies>
44+
</dependencyManagement>
45+
46+
<dependencies>
47+
<!-- [START spanner_opentelemetry_traces_otlp_dependencies] -->
48+
<dependency>
49+
<groupId>com.google.cloud</groupId>
50+
<artifactId>google-cloud-spanner</artifactId>
51+
</dependency>
52+
<dependency>
53+
<groupId>io.opentelemetry</groupId>
54+
<artifactId>opentelemetry-sdk</artifactId>
55+
</dependency>
56+
<dependency>
57+
<groupId>io.opentelemetry</groupId>
58+
<artifactId>opentelemetry-sdk-trace</artifactId>
59+
</dependency>
60+
<dependency>
61+
<groupId>io.opentelemetry</groupId>
62+
<artifactId>opentelemetry-exporter-otlp</artifactId>
63+
</dependency>
64+
<!-- [END spanner_opentelemetry_traces_otlp_dependencies] -->
65+
66+
<!-- [START spanner_opentelemetry_traces_cloudtrace_dependencies] -->
67+
<dependency>
68+
<groupId>com.google.cloud</groupId>
69+
<artifactId>google-cloud-spanner</artifactId>
70+
</dependency>
71+
<dependency>
72+
<groupId>io.opentelemetry</groupId>
73+
<artifactId>opentelemetry-sdk</artifactId>
74+
</dependency>
75+
<dependency>
76+
<groupId>io.opentelemetry</groupId>
77+
<artifactId>opentelemetry-sdk-trace</artifactId>
78+
</dependency>
79+
<dependency>
80+
<groupId>com.google.cloud.opentelemetry</groupId>
81+
<artifactId>exporter-trace</artifactId>
82+
<version>0.30.0</version>
83+
</dependency>
84+
<!-- [END spanner_opentelemetry_traces_cloudtrace_dependencies] -->
85+
</dependencies>
86+
87+
</project>
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright 2024 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.example.spanner;
18+
19+
import com.google.cloud.opentelemetry.trace.TraceConfiguration;
20+
import com.google.cloud.opentelemetry.trace.TraceExporter;
21+
import com.google.cloud.spanner.DatabaseClient;
22+
import com.google.cloud.spanner.DatabaseId;
23+
import com.google.cloud.spanner.ResultSet;
24+
import com.google.cloud.spanner.Spanner;
25+
import com.google.cloud.spanner.SpannerOptions;
26+
import com.google.cloud.spanner.Statement;
27+
import io.opentelemetry.api.OpenTelemetry;
28+
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
29+
import io.opentelemetry.sdk.OpenTelemetrySdk;
30+
import io.opentelemetry.sdk.resources.Resource;
31+
import io.opentelemetry.sdk.trace.SdkTracerProvider;
32+
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
33+
import io.opentelemetry.sdk.trace.export.SpanExporter;
34+
import io.opentelemetry.sdk.trace.samplers.Sampler;
35+
36+
/**
37+
* This sample demonstrates how to configure OpenTelemetry and inject via Spanner Options.
38+
*/
39+
public class OpenTelemetryUsage {
40+
41+
static SdkTracerProvider sdkTracerProvider;
42+
static Spanner spanner;
43+
44+
// TODO(developer): Replace these variables before running the sample.
45+
static String projectId = "my-project";
46+
static String instanceId = "my-instance";
47+
static String databaseId = "my-database";
48+
49+
// Replace these variables to use OTLP Exporter
50+
static boolean useCloudTraceExporter = true; // Replace to false for OTLP
51+
static String otlpEndpoint = "http://localhost:4317"; // Replace with your OTLP endpoint
52+
53+
public static void main(String[] args) {
54+
55+
if (useCloudTraceExporter) {
56+
spanner = getSpannerWithCloudTraceExporter();
57+
} else {
58+
spanner = getSpannerWithOtlpExporter();
59+
}
60+
61+
DatabaseClient dbClient = spanner
62+
.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
63+
64+
try (ResultSet resultSet =
65+
dbClient
66+
.singleUse() // Execute a single read or query against Cloud Spanner.
67+
.executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) {
68+
while (resultSet.next()) {
69+
System.out.printf(
70+
"%d %d %s", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2));
71+
}
72+
}
73+
74+
sdkTracerProvider.forceFlush();
75+
}
76+
77+
public static Spanner getSpannerWithOtlpExporter() {
78+
// [START spanner_opentelemetry_traces_otlp_usage]
79+
Resource resource = Resource
80+
.getDefault().merge(Resource.builder().put("service.name", "My App").build());
81+
82+
OtlpGrpcSpanExporter otlpGrpcSpanExporter =
83+
OtlpGrpcSpanExporter
84+
.builder()
85+
.setEndpoint(otlpEndpoint) // Replace with your OTLP endpoint
86+
.build();
87+
88+
// Using a batch span processor
89+
// You can use `.setScheduleDelay()`, `.setExporterTimeout()`,
90+
// `.setMaxQueueSize`(), and `.setMaxExportBatchSize()` to further customize.
91+
BatchSpanProcessor otlpGrpcSpanProcessor =
92+
BatchSpanProcessor.builder(otlpGrpcSpanExporter).build();
93+
94+
// Create a new tracer provider
95+
sdkTracerProvider = SdkTracerProvider.builder()
96+
// Use Otlp exporter or any other exporter of your choice.
97+
.addSpanProcessor(otlpGrpcSpanProcessor)
98+
.setResource(resource)
99+
.setSampler(Sampler.traceIdRatioBased(0.1))
100+
.build();
101+
102+
// Export to a collector that is expecting OTLP using gRPC.
103+
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
104+
.setTracerProvider(sdkTracerProvider).build();
105+
106+
// Enable OpenTelemetry traces before Injecting OpenTelemetry
107+
SpannerOptions.enableOpenTelemetryTraces();
108+
109+
// Inject OpenTelemetry object via Spanner options or register as GlobalOpenTelemetry.
110+
SpannerOptions options = SpannerOptions.newBuilder()
111+
.setOpenTelemetry(openTelemetry)
112+
.build();
113+
Spanner spanner = options.getService();
114+
// [END spanner_opentelemetry_traces_otlp_usage]
115+
116+
return spanner;
117+
}
118+
119+
public static Spanner getSpannerWithCloudTraceExporter() {
120+
// [START spanner_opentelemetry_traces_cloudtrace_usage]
121+
Resource resource = Resource
122+
.getDefault().merge(Resource.builder().put("service.name", "My App").build());
123+
124+
SpanExporter traceExporter = TraceExporter.createWithConfiguration(
125+
TraceConfiguration.builder().setProjectId(projectId).build()
126+
);
127+
128+
// Using a batch span processor
129+
// You can use `.setScheduleDelay()`, `.setExporterTimeout()`,
130+
// `.setMaxQueueSize`(), and `.setMaxExportBatchSize()` to further customize.
131+
BatchSpanProcessor otlpGrpcSpanProcessor =
132+
BatchSpanProcessor.builder(traceExporter).build();
133+
134+
// Create a new tracer provider
135+
sdkTracerProvider = SdkTracerProvider.builder()
136+
// Use Otlp exporter or any other exporter of your choice.
137+
.addSpanProcessor(otlpGrpcSpanProcessor)
138+
.setResource(resource)
139+
.setSampler(Sampler.traceIdRatioBased(0.1))
140+
.build();
141+
142+
// Export to a collector that is expecting OTLP using gRPC.
143+
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
144+
.setTracerProvider(sdkTracerProvider).build();
145+
146+
// Enable OpenTelemetry traces before Injecting OpenTelemetry
147+
SpannerOptions.enableOpenTelemetryTraces();
148+
149+
// Inject OpenTelemetry object via Spanner options or register it as global object.
150+
// To register as the global OpenTelemetry object,
151+
// use "OpenTelemetrySdk.builder()....buildAndRegisterGlobal()".
152+
SpannerOptions options = SpannerOptions.newBuilder()
153+
.setOpenTelemetry(openTelemetry)
154+
.build();
155+
Spanner spanner = options.getService();
156+
// [END spanner_opentelemetry_traces_cloudtrace_usage]
157+
158+
return spanner;
159+
}
160+
}

0 commit comments

Comments
 (0)