Skip to content

Commit bfb92d6

Browse files
committed
cleanup
1 parent de79589 commit bfb92d6

5 files changed

Lines changed: 201 additions & 166 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ 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
35+
implementation project(path: ":sdks:java:core", configuration: "shadow")
3436

3537
testImplementation library.java.junit
3638
testImplementation library.java.mockito_core

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

Lines changed: 85 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,9 @@
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;
46+
import org.apache.beam.sdk.annotations.Internal;
5147
import org.apache.beam.sdk.extensions.opentelemetry.gcp.auth.GoogleAuthException.Reason;
5248

5349
/**
@@ -67,31 +63,24 @@
6763
* @see GoogleCredentials
6864
*/
6965
@AutoService(AutoConfigurationCustomizerProvider.class)
66+
@Internal
7067
public class GcpAuthAutoConfigurationCustomizerProvider
7168
implements AutoConfigurationCustomizerProvider {
7269

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-
8270
static final String QUOTA_USER_PROJECT_HEADER = "x-goog-user-project";
8371
static final String GCP_USER_PROJECT_ID_KEY = "gcp.project_id";
8472

8573
static final String SIGNAL_TYPE_TRACES = "traces";
8674
static final String SIGNAL_TYPE_METRICS = "metrics";
8775
static final String SIGNAL_TYPE_ALL = "all";
8876

77+
private @Nullable GoogleCredentials credentials;
78+
8979
/**
9080
* Customizes the provided {@link AutoConfigurationCustomizer} such that authenticated exports to
9181
* GCP Telemetry API are possible from the configured OTLP exporter.
9282
*
93-
* <p>This method attempts to retrieve Google Application Default Credentials (ADC) and performs
94-
* the following:
83+
* <p>This method performs the following:
9584
*
9685
* <ul>
9786
* <li>Verifies whether the configured OTLP endpoint (base or signal specific) is a known GCP
@@ -107,60 +96,43 @@ public class GcpAuthAutoConfigurationCustomizerProvider
10796
* enable GCP integration.
10897
*
10998
* @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.
11499
*/
115100
@Override
116101
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-
}
123102
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));
103+
.addSpanExporterCustomizer(this::customizeSpanExporter)
104+
.addMetricExporterCustomizer(this::customizeMetricExporter)
105+
.addResourceCustomizer(this::customizeResource);
133106
}
134107

135108
@Override
136109
public int order() {
137110
return Integer.MAX_VALUE - 1;
138111
}
139112

140-
private static SpanExporter customizeSpanExporter(
141-
SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
113+
private synchronized GoogleCredentials getCredentials() {
114+
if (credentials == null) {
115+
try {
116+
credentials = GoogleCredentials.getApplicationDefault();
117+
} catch (IOException e) {
118+
throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e);
119+
}
120+
}
121+
return credentials;
122+
}
123+
124+
private SpanExporter customizeSpanExporter(
125+
SpanExporter exporter, ConfigProperties configProperties) {
142126
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);
127+
return addAuthorizationHeaders(exporter, configProperties);
150128
}
151129
return exporter;
152130
}
153131

154-
private static MetricExporter customizeMetricExporter(
155-
MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
132+
private MetricExporter customizeMetricExporter(
133+
MetricExporter exporter, ConfigProperties configProperties) {
156134
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);
135+
return addAuthorizationHeaders(exporter, configProperties);
164136
}
165137
return exporter;
166138
}
@@ -171,11 +143,25 @@ private static boolean isSignalTargeted(String checkSignal, ConfigProperties con
171143
if (endpoint == null) {
172144
endpoint = configProperties.getString("otel.exporter.otlp.endpoint");
173145
}
174-
if (endpoint == null
175-
|| (!endpoint.startsWith("https://telemetry.googleapis.com")
176-
&& !endpoint.startsWith("https://telemetry.mtls.googleapis.com"))) {
146+
if (endpoint == null) {
177147
return false;
178148
}
149+
150+
try {
151+
java.net.URI uri = new java.net.URI(endpoint);
152+
String host = uri.getHost();
153+
String scheme = uri.getScheme();
154+
if (host == null
155+
|| scheme == null
156+
|| !scheme.equalsIgnoreCase("https")
157+
|| (!host.equalsIgnoreCase("telemetry.googleapis.com")
158+
&& !host.equalsIgnoreCase("telemetry.mtls.googleapis.com"))) {
159+
return false;
160+
}
161+
} catch (java.net.URISyntaxException e) {
162+
return false;
163+
}
164+
179165
String userSpecifiedTargetedSignals =
180166
ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValueWithFallback(
181167
configProperties, () -> SIGNAL_TYPE_ALL);
@@ -186,57 +172,74 @@ private static boolean isSignalTargeted(String checkSignal, ConfigProperties con
186172
targetedSignal.equals(checkSignal) || targetedSignal.equals(SIGNAL_TYPE_ALL));
187173
}
188174

175+
private boolean isAnySignalTargeted(ConfigProperties configProperties) {
176+
return isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)
177+
|| isSignalTargeted(SIGNAL_TYPE_METRICS, configProperties);
178+
}
179+
189180
// Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and
190181
// OtlpHttpSpanExporter.
191-
private static SpanExporter addAuthorizationHeaders(
192-
SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
182+
private SpanExporter addAuthorizationHeaders(
183+
SpanExporter exporter, ConfigProperties configProperties) {
193184
if (exporter instanceof OtlpHttpSpanExporter) {
194-
OtlpHttpSpanExporterBuilder builder =
185+
SpanExporter result =
195186
((OtlpHttpSpanExporter) exporter)
196187
.toBuilder()
197-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
198-
return builder.build();
188+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
189+
.build();
190+
exporter.shutdown();
191+
return result;
199192
} else if (exporter instanceof OtlpGrpcSpanExporter) {
200-
OtlpGrpcSpanExporterBuilder builder =
193+
SpanExporter result =
201194
((OtlpGrpcSpanExporter) exporter)
202195
.toBuilder()
203-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
204-
return builder.build();
196+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
197+
.build();
198+
exporter.shutdown();
199+
return result;
205200
}
206201
return exporter;
207202
}
208203

209204
// Adds authorization headers to the calls made by the OtlpGrpcMetricExporter and
210205
// OtlpHttpMetricExporter.
211-
private static MetricExporter addAuthorizationHeaders(
212-
MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) {
206+
private MetricExporter addAuthorizationHeaders(
207+
MetricExporter exporter, ConfigProperties configProperties) {
213208
if (exporter instanceof OtlpHttpMetricExporter) {
214-
OtlpHttpMetricExporterBuilder builder =
209+
MetricExporter result =
215210
((OtlpHttpMetricExporter) exporter)
216211
.toBuilder()
217-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
218-
return builder.build();
212+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
213+
.build();
214+
exporter.shutdown();
215+
return result;
219216
} else if (exporter instanceof OtlpGrpcMetricExporter) {
220-
OtlpGrpcMetricExporterBuilder builder =
217+
MetricExporter result =
221218
((OtlpGrpcMetricExporter) exporter)
222219
.toBuilder()
223-
.setHeaders(() -> getRequiredHeaderMap(credentials, configProperties));
224-
return builder.build();
220+
.setHeaders(() -> getRequiredHeaderMap(configProperties))
221+
.build();
222+
exporter.shutdown();
223+
return result;
225224
}
226225
return exporter;
227226
}
228227

229-
private static Map<String, String> getRequiredHeaderMap(
230-
GoogleCredentials credentials, ConfigProperties configProperties) {
228+
private Map<String, String> getRequiredHeaderMap(ConfigProperties configProperties) {
229+
GoogleCredentials creds = getCredentials();
231230
Map<String, List<String>> gcpHeaders;
232231
try {
233232
// this also refreshes the credentials, if required
234-
gcpHeaders = credentials.getRequestMetadata();
233+
gcpHeaders = creds.getRequestMetadata();
235234
} catch (IOException e) {
236235
throw new GoogleAuthException(Reason.FAILED_ADC_REFRESH, e);
237236
}
237+
if (gcpHeaders == null) {
238+
return Map.of();
239+
}
238240
Map<String, String> flattenedHeaders =
239241
gcpHeaders.entrySet().stream()
242+
.filter(entry -> entry.getKey() != null && entry.getValue() != null)
240243
.collect(
241244
toMap(
242245
Map.Entry::getKey,
@@ -259,13 +262,16 @@ private static Map<String, String> getRequiredHeaderMap(
259262
}
260263

261264
// 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) {
265+
private Resource customizeResource(Resource resource, ConfigProperties configProperties) {
266+
if (!isAnySignalTargeted(configProperties)) {
267+
return resource;
268+
}
269+
264270
String gcpProjectId;
265271
try {
266272
gcpProjectId = ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue(configProperties);
267273
} catch (ConfigurationException e) {
268-
gcpProjectId = credentials.getProjectId();
274+
gcpProjectId = getCredentials().getProjectId();
269275
if (gcpProjectId == null || gcpProjectId.isEmpty()) {
270276
throw e;
271277
}
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)