gemini-code-assist[bot] commented on code in PR #38773: URL: https://github.com/apache/beam/pull/38773#discussion_r3342182156
########## sdks/java/extensions/opentelemetry-gcp-auth-extension/src/main/java/org/apache/beam/sdk/extensions/opentelemetry/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java: ########## @@ -0,0 +1,276 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.beam.sdk.extensions.opentelemetry.gcp.auth; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toMap; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auto.service.AutoService; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; +import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder; +import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; +import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder; +import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; +import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder; +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; +import io.opentelemetry.sdk.metrics.export.MetricExporter; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nonnull; +import org.apache.beam.sdk.extensions.opentelemetry.gcp.auth.GoogleAuthException.Reason; + +/** + * An AutoConfigurationCustomizerProvider for Google Cloud Platform (GCP) OpenTelemetry (OTLP) + * integration. + * + * <p>This class is registered as a service provider using {@link AutoService} and is responsible + * for customizing the OpenTelemetry configuration for GCP specific behavior. It retrieves Google + * Application Default Credentials (ADC) and adds them as authorization headers to the configured + * {@link SpanExporter}. It also sets default properties and resource attributes for GCP + * integration. + * + * <p>Copied from + * https://github.com/open-telemetry/opentelemetry-java-contrib/blob/main/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java + * + * @see AutoConfigurationCustomizerProvider + * @see GoogleCredentials + */ +@AutoService(AutoConfigurationCustomizerProvider.class) +public class GcpAuthAutoConfigurationCustomizerProvider + implements AutoConfigurationCustomizerProvider { + + private static final Logger logger = + Logger.getLogger(GcpAuthAutoConfigurationCustomizerProvider.class.getName()); + private static final String SIGNAL_TARGET_WARNING_FIX_SUGGESTION = + String.format( + "You may safely ignore this warning if it is intentional, otherwise please configure the '%s' by exporting valid values to environment variable: %s or by setting valid values in system property: %s.", + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getUserReadableName(), + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getEnvironmentVariable(), + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty()); + + static final String QUOTA_USER_PROJECT_HEADER = "x-goog-user-project"; + static final String GCP_USER_PROJECT_ID_KEY = "gcp.project_id"; + + static final String SIGNAL_TYPE_TRACES = "traces"; + static final String SIGNAL_TYPE_METRICS = "metrics"; + static final String SIGNAL_TYPE_ALL = "all"; + + /** + * Customizes the provided {@link AutoConfigurationCustomizer} such that authenticated exports to + * GCP Telemetry API are possible from the configured OTLP exporter. + * + * <p>This method attempts to retrieve Google Application Default Credentials (ADC) and performs + * the following: + * + * <ul> + * <li>Verifies whether the configured OTLP endpoint (base or signal specific) is a known GCP + * endpoint. + * <li>If the configured base OTLP endpoint is a known GCP Telemetry API endpoint, customizes + * both the configured OTLP {@link SpanExporter} and {@link MetricExporter}. + * <li>If the configured signal specific endpoint is a known GCP Telemetry API endpoint, + * customizes only the signal specific exporter. + * </ul> + * + * The 'customization' performed includes customizing the exporters by adding required headers to + * the export calls made and customizing the resource by adding required resource attributes to + * enable GCP integration. + * + * @param autoConfiguration the AutoConfigurationCustomizer to customize. + * @throws GoogleAuthException if there's an error retrieving Google Application Default + * Credentials. + * @throws io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException if required options are + * not configured through environment variables or system properties. + */ + @Override + public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { + GoogleCredentials credentials; + try { + credentials = GoogleCredentials.getApplicationDefault(); + } catch (IOException e) { + throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e); + } + autoConfiguration + .addSpanExporterCustomizer( + (spanExporter, configProperties) -> + customizeSpanExporter(spanExporter, credentials, configProperties)) + .addMetricExporterCustomizer( + (metricExporter, configProperties) -> + customizeMetricExporter(metricExporter, credentials, configProperties)) + .addResourceCustomizer( + (resource, configProperties) -> + customizeResource(resource, credentials, configProperties)); + } Review Comment:  Unconditionally calling `GoogleCredentials.getApplicationDefault()` during autoconfiguration initialization will throw a `GoogleAuthException` and crash the application startup if Application Default Credentials (ADC) are not configured, even if the OTLP exporter is not targeting GCP. To prevent this, retrieve the credentials lazily using a `Supplier` and only evaluate it when a GCP endpoint is actually targeted. ```java @Override public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { java.util.function.Supplier<GoogleCredentials> credentialsSupplier = new java.util.function.Supplier<GoogleCredentials>() { private GoogleCredentials credentials; @Override public synchronized GoogleCredentials get() { if (credentials == null) { try { credentials = GoogleCredentials.getApplicationDefault(); } catch (IOException e) { throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e); } } return credentials; } }; autoConfiguration .addSpanExporterCustomizer( (spanExporter, configProperties) -> customizeSpanExporter(spanExporter, credentialsSupplier, configProperties)) .addMetricExporterCustomizer( (metricExporter, configProperties) -> customizeMetricExporter(metricExporter, credentialsSupplier, configProperties)) .addResourceCustomizer( (resource, configProperties) -> customizeResource(resource, credentialsSupplier, configProperties)); } ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
