diff --git a/spanner/opentelemetry_traces/src/main/java/com/example/spanner/OpenTelemetryUsage.java b/spanner/opentelemetry_traces/src/main/java/com/example/spanner/OpenTelemetryUsage.java index 729207ed64b..f43040362e6 100644 --- a/spanner/opentelemetry_traces/src/main/java/com/example/spanner/OpenTelemetryUsage.java +++ b/spanner/opentelemetry_traces/src/main/java/com/example/spanner/OpenTelemetryUsage.java @@ -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; @@ -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; @@ -46,11 +51,23 @@ 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) { + 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(); @@ -58,8 +75,8 @@ public static void main(String[] args) { spanner = getSpannerWithOtlpExporter(); } - DatabaseClient dbClient = spanner - .getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + DatabaseClient dbClient = + spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); try (ResultSet resultSet = dbClient @@ -74,74 +91,72 @@ 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")) { + GoogleCredentials credentials = + GoogleCredentials.getApplicationDefault() + .createScoped(Collections.singleton("https://www.googleapis.com/auth/trace.append")); + credentials.refreshIfExpired(); + Map> 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)) .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(); @@ -149,9 +164,7 @@ public static Spanner getSpannerWithCloudTraceExporter() { // 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(); Spanner spanner = options.getService(); // [END spanner_opentelemetry_traces_cloudtrace_usage]