Skip to content

Commit bc2ff62

Browse files
committed
cleanup
1 parent de79589 commit bc2ff62

5 files changed

Lines changed: 198 additions & 166 deletions

File tree

sdks/java/extensions/opentelemetry-gcp-auth-extension/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dependencies {
2828
implementation enforcedPlatform(library.java.google_cloud_platform_libraries_bom)
2929
implementation platform(library.java.opentelemetry_bom)
3030
implementation library.java.google_auth_library_oauth2_http
31+
implementation library.java.vendored_guava_32_1_2_jre
3132
compileOnly library.java.opentelemetry_api
3233
compileOnly library.java.opentelemetry_extension_autoconfigure
3334
compileOnly library.java.opentelemetry_exporter_otlp

sdks/java/extensions/opentelemetry-gcp-auth-extension/src/main/java/org/apache/beam/sdk/extensions/opentelemetry/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java

Lines changed: 83 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,9 @@
2626
import com.google.auto.service.AutoService;
2727
import io.opentelemetry.api.common.Attributes;
2828
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
29-
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder;
3029
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
31-
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder;
3230
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
33-
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder;
3431
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
35-
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
3632
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
3733
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
3834
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
@@ -45,9 +41,8 @@
4541
import java.util.Map;
4642
import java.util.Objects;
4743
import java.util.Optional;
48-
import java.util.logging.Level;
49-
import java.util.logging.Logger;
5044
import javax.annotation.Nonnull;
45+
import javax.annotation.Nullable;
5146
import org.apache.beam.sdk.extensions.opentelemetry.gcp.auth.GoogleAuthException.Reason;
5247

5348
/**
@@ -70,28 +65,20 @@
7065
public class GcpAuthAutoConfigurationCustomizerProvider
7166
implements AutoConfigurationCustomizerProvider {
7267

73-
private static final Logger logger =
74-
Logger.getLogger(GcpAuthAutoConfigurationCustomizerProvider.class.getName());
75-
private static final String SIGNAL_TARGET_WARNING_FIX_SUGGESTION =
76-
String.format(
77-
"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.",
78-
ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getUserReadableName(),
79-
ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getEnvironmentVariable(),
80-
ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty());
81-
8268
static final String QUOTA_USER_PROJECT_HEADER = "x-goog-user-project";
8369
static final String GCP_USER_PROJECT_ID_KEY = "gcp.project_id";
8470

8571
static final String SIGNAL_TYPE_TRACES = "traces";
8672
static final String SIGNAL_TYPE_METRICS = "metrics";
8773
static final String SIGNAL_TYPE_ALL = "all";
8874

75+
private @Nullable GoogleCredentials credentials;
76+
8977
/**
9078
* Customizes the provided {@link AutoConfigurationCustomizer} such that authenticated exports to
9179
* GCP Telemetry API are possible from the configured OTLP exporter.
9280
*
93-
* <p>This method attempts to retrieve Google Application Default Credentials (ADC) and performs
94-
* the following:
81+
* <p>This method performs the following:
9582
*
9683
* <ul>
9784
* <li>Verifies whether the configured OTLP endpoint (base or signal specific) is a known GCP
@@ -107,60 +94,43 @@ public class GcpAuthAutoConfigurationCustomizerProvider
10794
* enable GCP integration.
10895
*
10996
* @param autoConfiguration the AutoConfigurationCustomizer to customize.
110-
* @throws GoogleAuthException if there's an error retrieving Google Application Default
111-
* Credentials.
112-
* @throws io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException if required options are
113-
* not configured through environment variables or system properties.
11497
*/
11598
@Override
11699
public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) {
117-
GoogleCredentials credentials;
118-
try {
119-
credentials = GoogleCredentials.getApplicationDefault();
120-
} catch (IOException e) {
121-
throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e);
122-
}
123100
autoConfiguration
124-
.addSpanExporterCustomizer(
125-
(spanExporter, configProperties) ->
126-
customizeSpanExporter(spanExporter, credentials, configProperties))
127-
.addMetricExporterCustomizer(
128-
(metricExporter, configProperties) ->
129-
customizeMetricExporter(metricExporter, credentials, configProperties))
130-
.addResourceCustomizer(
131-
(resource, configProperties) ->
132-
customizeResource(resource, credentials, configProperties));
101+
.addSpanExporterCustomizer(this::customizeSpanExporter)
102+
.addMetricExporterCustomizer(this::customizeMetricExporter)
103+
.addResourceCustomizer(this::customizeResource);
133104
}
134105

135106
@Override
136107
public int order() {
137108
return Integer.MAX_VALUE - 1;
138109
}
139110

140-
private static SpanExporter customizeSpanExporter(
141-
SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
111+
private synchronized GoogleCredentials getCredentials() {
112+
if (credentials == null) {
113+
try {
114+
credentials = GoogleCredentials.getApplicationDefault();
115+
} catch (IOException e) {
116+
throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e);
117+
}
118+
}
119+
return credentials;
120+
}
121+
122+
private SpanExporter customizeSpanExporter(
123+
SpanExporter exporter, ConfigProperties configProperties) {
142124
if (isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) {
143-
return addAuthorizationHeaders(exporter, credentials, configProperties);
144-
} else {
145-
String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION};
146-
logger.log(
147-
Level.WARNING,
148-
"GCP Authentication Extension is not configured for signal type: {0}. {1}",
149-
params);
125+
return addAuthorizationHeaders(exporter, configProperties);
150126
}
151127
return exporter;
152128
}
153129

154-
private static MetricExporter customizeMetricExporter(
155-
MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
130+
private MetricExporter customizeMetricExporter(
131+
MetricExporter exporter, ConfigProperties configProperties) {
156132
if (isSignalTargeted(SIGNAL_TYPE_METRICS, configProperties)) {
157-
return addAuthorizationHeaders(exporter, credentials, configProperties);
158-
} else {
159-
String[] params = {SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION};
160-
logger.log(
161-
Level.WARNING,
162-
"GCP Authentication Extension is not configured for signal type: {0}. {1}",
163-
params);
133+
return addAuthorizationHeaders(exporter, configProperties);
164134
}
165135
return exporter;
166136
}
@@ -171,11 +141,25 @@ private static boolean isSignalTargeted(String checkSignal, ConfigProperties con
171141
if (endpoint == null) {
172142
endpoint = configProperties.getString("otel.exporter.otlp.endpoint");
173143
}
174-
if (endpoint == null
175-
|| (!endpoint.startsWith("https://telemetry.googleapis.com")
176-
&& !endpoint.startsWith("https://telemetry.mtls.googleapis.com"))) {
144+
if (endpoint == null) {
177145
return false;
178146
}
147+
148+
try {
149+
java.net.URI uri = new java.net.URI(endpoint);
150+
String host = uri.getHost();
151+
String scheme = uri.getScheme();
152+
if (host == null
153+
|| scheme == null
154+
|| !scheme.equalsIgnoreCase("https")
155+
|| (!host.equalsIgnoreCase("telemetry.googleapis.com")
156+
&& !host.equalsIgnoreCase("telemetry.mtls.googleapis.com"))) {
157+
return false;
158+
}
159+
} catch (java.net.URISyntaxException e) {
160+
return false;
161+
}
162+
179163
String userSpecifiedTargetedSignals =
180164
ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValueWithFallback(
181165
configProperties, () -> SIGNAL_TYPE_ALL);
@@ -186,57 +170,74 @@ private static boolean isSignalTargeted(String checkSignal, ConfigProperties con
186170
targetedSignal.equals(checkSignal) || targetedSignal.equals(SIGNAL_TYPE_ALL));
187171
}
188172

173+
private boolean isAnySignalTargeted(ConfigProperties configProperties) {
174+
return isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)
175+
|| isSignalTargeted(SIGNAL_TYPE_METRICS, configProperties);
176+
}
177+
189178
// Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and
190179
// OtlpHttpSpanExporter.
191-
private static SpanExporter addAuthorizationHeaders(
192-
SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
180+
private SpanExporter addAuthorizationHeaders(
181+
SpanExporter exporter, ConfigProperties configProperties) {
193182
if (exporter instanceof OtlpHttpSpanExporter) {
194-
OtlpHttpSpanExporterBuilder builder =
183+
SpanExporter result =
195184
((OtlpHttpSpanExporter) exporter)
196185
.toBuilder()
197-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
198-
return builder.build();
186+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
187+
.build();
188+
exporter.shutdown();
189+
return result;
199190
} else if (exporter instanceof OtlpGrpcSpanExporter) {
200-
OtlpGrpcSpanExporterBuilder builder =
191+
SpanExporter result =
201192
((OtlpGrpcSpanExporter) exporter)
202193
.toBuilder()
203-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
204-
return builder.build();
194+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
195+
.build();
196+
exporter.shutdown();
197+
return result;
205198
}
206199
return exporter;
207200
}
208201

209202
// Adds authorization headers to the calls made by the OtlpGrpcMetricExporter and
210203
// OtlpHttpMetricExporter.
211-
private static MetricExporter addAuthorizationHeaders(
212-
MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
204+
private MetricExporter addAuthorizationHeaders(
205+
MetricExporter exporter, ConfigProperties configProperties) {
213206
if (exporter instanceof OtlpHttpMetricExporter) {
214-
OtlpHttpMetricExporterBuilder builder =
207+
MetricExporter result =
215208
((OtlpHttpMetricExporter) exporter)
216209
.toBuilder()
217-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
218-
return builder.build();
210+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
211+
.build();
212+
exporter.shutdown();
213+
return result;
219214
} else if (exporter instanceof OtlpGrpcMetricExporter) {
220-
OtlpGrpcMetricExporterBuilder builder =
215+
MetricExporter result =
221216
((OtlpGrpcMetricExporter) exporter)
222217
.toBuilder()
223-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
224-
return builder.build();
218+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
219+
.build();
220+
exporter.shutdown();
221+
return result;
225222
}
226223
return exporter;
227224
}
228225

229-
private static Map<String, String> getRequiredHeaderMap(
230-
GoogleCredentials credentials, ConfigProperties configProperties) {
226+
private Map<String, String> getRequiredHeaderMap(ConfigProperties configProperties) {
227+
GoogleCredentials creds = getCredentials();
231228
Map<String, List<String>> gcpHeaders;
232229
try {
233230
// this also refreshes the credentials, if required
234-
gcpHeaders = credentials.getRequestMetadata();
231+
gcpHeaders = creds.getRequestMetadata();
235232
} catch (IOException e) {
236233
throw new GoogleAuthException(Reason.FAILED_ADC_REFRESH, e);
237234
}
235+
if (gcpHeaders == null) {
236+
return Map.of();
237+
}
238238
Map<String, String> flattenedHeaders =
239239
gcpHeaders.entrySet().stream()
240+
.filter(entry -> entry.getKey() != null && entry.getValue() != null)
240241
.collect(
241242
toMap(
242243
Map.Entry::getKey,
@@ -259,13 +260,16 @@ private static Map<String, String> getRequiredHeaderMap(
259260
}
260261

261262
// Updates the current resource with the attributes required for ingesting OTLP data on GCP.
262-
private static Resource customizeResource(
263-
Resource resource, GoogleCredentials credentials, ConfigProperties configProperties) {
263+
private Resource customizeResource(Resource resource, ConfigProperties configProperties) {
264+
if (!isAnySignalTargeted(configProperties)) {
265+
return resource;
266+
}
267+
264268
String gcpProjectId;
265269
try {
266270
gcpProjectId = ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue(configProperties);
267271
} catch (ConfigurationException e) {
268-
gcpProjectId = credentials.getProjectId();
272+
gcpProjectId = getCredentials().getProjectId();
269273
if (gcpProjectId == null || gcpProjectId.isEmpty()) {
270274
throw e;
271275
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/** Google Cloud Platform (GCP) OpenTelemetry (OTLP) authentication extension. */
20+
package org.apache.beam.sdk.extensions.opentelemetry.gcp.auth;
Original file line numberDiff line numberDiff line change
@@ -1 +1,16 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. 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+
116
org.apache.beam.sdk.extensions.opentelemetry.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider

0 commit comments

Comments
 (0)