Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.example.spanner;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.opentelemetry.trace.TraceConfiguration;
import com.google.cloud.opentelemetry.trace.TraceExporter;
import com.google.cloud.spanner.DatabaseClient;
Expand All @@ -26,16 +27,20 @@
import com.google.cloud.spanner.Statement;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
* This sample demonstrates how to configure OpenTelemetry and inject via Spanner Options.
*/
/** This sample demonstrates how to configure OpenTelemetry and inject via Spanner Options. */
public class OpenTelemetryUsage {

static SdkTracerProvider sdkTracerProvider;
Expand All @@ -46,20 +51,32 @@ public class OpenTelemetryUsage {
static String instanceId = "my-instance";
static String databaseId = "my-database";

// Replace these variables to use OTLP Exporter
static boolean useCloudTraceExporter = true; // Replace to false for OTLP
static String otlpEndpoint = "http://localhost:4317"; // Replace with your OTLP endpoint
// Use the OTLP exporter by default. Set to true to use the Cloud Trace exporter instead.
static boolean useCloudTraceExporter = false;

// The OTLP endpoint to send traces to.
// It is recommended to use environment variables (OTEL_EXPORTER_OTLP_ENDPOINT) for configuration.
static String otlpEndpoint = System.getenv("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT");

static {
if (otlpEndpoint == null) {
otlpEndpoint = System.getenv("OTEL_EXPORTER_OTLP_ENDPOINT");
}
if (otlpEndpoint == null) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if "OTEL_EXPORTER" or "OTEL_TRACES_EXPORTER" are set to "gcp" or if environment variable "GOOGLE_CLOUD_TRACING_ENABLED" is set to "true", then you can fallback like this.

Otherwise, I think you should fallback to the default behavior of Open Telemetry. If "OTEL_EXPORTER" or "OTEL_TRACES_EXPORTER" is set to "otlp" and neither "OTEL_EXPORTER_OTLP_ENDPOINT" nor "OTEL_OTLP_EXPORTER_TRACES_ENDPOINT" are set, then the default is to use "http://localhost:4317" for gRPC and "http://localhost:4318" for HTTP. See:

https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/

otlpEndpoint = "https://telemetry.googleapis.com"; // Google OTLP gRPC endpoint
}
}

public static void main(String[] args) {
public static void main(String[] args) throws IOException {

if (useCloudTraceExporter) {
spanner = getSpannerWithCloudTraceExporter();
} else {
spanner = getSpannerWithOtlpExporter();
}

DatabaseClient dbClient = spanner
.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
DatabaseClient dbClient =
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));

try (ResultSet resultSet =
dbClient
Expand All @@ -74,84 +91,80 @@ public static void main(String[] args) {
sdkTracerProvider.forceFlush();
}

public static Spanner getSpannerWithOtlpExporter() {
public static Spanner getSpannerWithOtlpExporter() throws IOException {
// [START spanner_opentelemetry_traces_otlp_usage]
Resource resource = Resource
.getDefault().merge(Resource.builder().put("service.name", "My App").build());
Resource resource =
Resource.getDefault().merge(Resource.builder().put("gcp.project_id", projectId).build());

OtlpGrpcSpanExporterBuilder exporterBuilder =
OtlpGrpcSpanExporter.builder().setEndpoint(otlpEndpoint);

// Add authentication only if the endpoint is the Google Cloud Telemetry API.
// The standard endpoint is telemetry.googleapis.com
if (otlpEndpoint.contains("telemetry.googleapis.com")) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that you also need to match regionalized addresses:

telemetry.googleapis.com (global)
telemetry.us-central1.rep.googleapis.com (regionalized in cloud region us-central1)
telemetry.us-east1.rep.googleapis.com (regionalized in us-east1)
...

Prefixed with "https://" or suffixed with ":443" (optionally with "dns:// " as a prefix). Ex:

telemetry.googleapis.com
https://telemetry.googleapis.com
telemetry.googleapis.com:443
dns://telemetry.googleapis.com:443
https://telemetry.us-central1.rep.googleapis.com
telemetry.us-central1.rep.googleapis.com:443
...

However, you also want this match to apply only to the domain (it would be a mistake to match "otherdomain.com/proxy/telemetry.googleapis.com").

GoogleCredentials credentials =
GoogleCredentials.getApplicationDefault()
.createScoped(Collections.singleton("https://www.googleapis.com/auth/trace.append"));
credentials.refreshIfExpired();
Map<String, List<String>> metadata = credentials.getRequestMetadata(URI.create(otlpEndpoint));
if (metadata != null) {
metadata.forEach((key, values) -> exporterBuilder.addHeader(key, String.join(",", values)));
}
}

OtlpGrpcSpanExporter otlpGrpcSpanExporter =
OtlpGrpcSpanExporter
.builder()
.setEndpoint(otlpEndpoint) // Replace with your OTLP endpoint
sdkTracerProvider =
SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(exporterBuilder.build()).build())
.setResource(resource)
.setSampler(Sampler.traceIdRatioBased(0.1))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the OTEL_TRACES_SAMPLER flag to control sampling behavior?

https://opentelemetry.io/docs/languages/sdk-configuration/general/#otel_traces_sampler

.build();

// Using a batch span processor
// You can use `.setScheduleDelay()`, `.setExporterTimeout()`,
// `.setMaxQueueSize`(), and `.setMaxExportBatchSize()` to further customize.
BatchSpanProcessor otlpGrpcSpanProcessor =
BatchSpanProcessor.builder(otlpGrpcSpanExporter).build();

// Create a new tracer provider
sdkTracerProvider = SdkTracerProvider.builder()
// Use Otlp exporter or any other exporter of your choice.
.addSpanProcessor(otlpGrpcSpanProcessor)
.setResource(resource)
.setSampler(Sampler.traceIdRatioBased(0.1))
.build();

// Export to a collector that is expecting OTLP using gRPC.
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider).build();
OpenTelemetry openTelemetry =
OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider).build();

// Enable OpenTelemetry traces before Injecting OpenTelemetry
SpannerOptions.enableOpenTelemetryTraces();

// Inject OpenTelemetry object via Spanner options or register as GlobalOpenTelemetry.
SpannerOptions options = SpannerOptions.newBuilder()
.setOpenTelemetry(openTelemetry)
.build();
Spanner spanner = options.getService();
SpannerOptions options = SpannerOptions.newBuilder().setOpenTelemetry(openTelemetry).build();
return options.getService();
// [END spanner_opentelemetry_traces_otlp_usage]

return spanner;
}

public static Spanner getSpannerWithCloudTraceExporter() {
// [START spanner_opentelemetry_traces_cloudtrace_usage]
Resource resource = Resource
.getDefault().merge(Resource.builder().put("service.name", "My App").build());
Resource resource =
Resource.getDefault().merge(Resource.builder().put("service.name", "My App").build());

SpanExporter traceExporter = TraceExporter.createWithConfiguration(
TraceConfiguration.builder().setProjectId(projectId).build()
);
SpanExporter traceExporter =
TraceExporter.createWithConfiguration(
TraceConfiguration.builder().setProjectId(projectId).build());

// Using a batch span processor
// You can use `.setScheduleDelay()`, `.setExporterTimeout()`,
// `.setMaxQueueSize`(), and `.setMaxExportBatchSize()` to further customize.
BatchSpanProcessor otlpGrpcSpanProcessor =
BatchSpanProcessor.builder(traceExporter).build();
BatchSpanProcessor otlpGrpcSpanProcessor = BatchSpanProcessor.builder(traceExporter).build();

// Create a new tracer provider
sdkTracerProvider = SdkTracerProvider.builder()
// Use Otlp exporter or any other exporter of your choice.
.addSpanProcessor(otlpGrpcSpanProcessor)
.setResource(resource)
.setSampler(Sampler.traceIdRatioBased(0.1))
.build();
sdkTracerProvider =
SdkTracerProvider.builder()
// Use Otlp exporter or any other exporter of your choice.
.addSpanProcessor(otlpGrpcSpanProcessor)
.setResource(resource)
.setSampler(Sampler.traceIdRatioBased(0.1))
.build();

// Export to a collector that is expecting OTLP using gRPC.
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider).build();
OpenTelemetry openTelemetry =
OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider).build();

// Enable OpenTelemetry traces before Injecting OpenTelemetry
SpannerOptions.enableOpenTelemetryTraces();

// Inject OpenTelemetry object via Spanner options or register it as global object.
// To register as the global OpenTelemetry object,
// use "OpenTelemetrySdk.builder()....buildAndRegisterGlobal()".
SpannerOptions options = SpannerOptions.newBuilder()
.setOpenTelemetry(openTelemetry)
.build();
SpannerOptions options = SpannerOptions.newBuilder().setOpenTelemetry(openTelemetry).build();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this change? This looks more cleaner

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similarly in other places.

Spanner spanner = options.getService();
// [END spanner_opentelemetry_traces_cloudtrace_usage]

Expand Down
Loading