-
Notifications
You must be signed in to change notification settings - Fork 2.9k
feat(spanner): Update OpenTelemetry OTLP trace sample to use Google C… #10251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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,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) { | ||
| 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 | ||
|
|
@@ -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")) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) Prefixed with "https://" or suffixed with ":443" (optionally with "dns:// " as a prefix). Ex: telemetry.googleapis.com 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)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the 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(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we remove this change? This looks more cleaner There was a problem hiding this comment. Choose a reason for hiding this commentThe 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] | ||
|
|
||
|
|
||
There was a problem hiding this comment.
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/