Skip to content

Commit 1ea6028

Browse files
psx95otelbot[bot]
andauthored
Add metrics support to auth extension (#1891)
Co-authored-by: otelbot <[email protected]>
1 parent d718549 commit 1ea6028

File tree

4 files changed

+686
-30
lines changed

4 files changed

+686
-30
lines changed

gcp-auth-extension/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ Here is a list of required and optional configuration available for the extensio
4747

4848
- Can also be configured using `google.cloud.quota.project` system property.
4949

50+
- `GOOGLE_OTEL_AUTH_TARGET_SIGNALS`: Environment variable that specifies a comma-separated list of OpenTelemetry signals for which this authentication extension should be active. Valid values contain - `metrics`, `traces` or `all`. If left unspecified, `all` is assumed meaning the extension will attempt to apply authentication to exports for all signals.
51+
52+
- Can also be configured using `google.otel.auth.target.signals` system property.
53+
5054
## Usage
5155

5256
### With OpenTelemetry Java agent

gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,27 @@ public enum ConfigurableOption {
3030
* href="https://cloud.google.com/docs/quotas/set-quota-project">official GCP client
3131
* libraries</a>.
3232
*/
33-
GOOGLE_CLOUD_QUOTA_PROJECT("Google Cloud Quota Project ID");
33+
GOOGLE_CLOUD_QUOTA_PROJECT("Google Cloud Quota Project ID"),
34+
35+
/**
36+
* Specifies a comma-separated list of OpenTelemetry signals for which this authentication
37+
* extension should be active. The authentication mechanisms provided by this extension will only
38+
* be applied to the listed signals. If not set, {@code all} is assumed to be set which means
39+
* authentication is enabled for all supported signals.
40+
*
41+
* <p>Valid signal values are:
42+
*
43+
* <ul>
44+
* <li>{@code metrics} - Enables authentication for metric exports.
45+
* <li>{@code traces} - Enables authentication for trace exports.
46+
* <li>{@code all} - Enables authentication for all exports.
47+
* </ul>
48+
*
49+
* <p>The values are case-sensitive. Whitespace around commas and values is ignored. Can be
50+
* configured using the environment variable `GOOGLE_OTEL_AUTH_TARGET_SIGNALS` or the system
51+
* property `google.otel.auth.target.signals`.
52+
*/
53+
GOOGLE_OTEL_AUTH_TARGET_SIGNALS("Target Signals for Google Auth Extension");
3454

3555
private final String userReadableName;
3656
private final String environmentVariableName;

gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,28 @@
1010
import io.opentelemetry.api.common.AttributeKey;
1111
import io.opentelemetry.api.common.Attributes;
1212
import io.opentelemetry.contrib.gcp.auth.GoogleAuthException.Reason;
13+
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
14+
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder;
1315
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
1416
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder;
17+
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
18+
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder;
1519
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
1620
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
1721
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
1822
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
1923
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
24+
import io.opentelemetry.sdk.metrics.export.MetricExporter;
2025
import io.opentelemetry.sdk.resources.Resource;
2126
import io.opentelemetry.sdk.trace.export.SpanExporter;
2227
import java.io.IOException;
28+
import java.util.Arrays;
2329
import java.util.List;
2430
import java.util.Map;
2531
import java.util.Objects;
2632
import java.util.Optional;
2733
import java.util.stream.Collectors;
34+
import javax.annotation.Nonnull;
2835

2936
/**
3037
* An AutoConfigurationCustomizerProvider for Google Cloud Platform (GCP) OpenTelemetry (OTLP)
@@ -46,13 +53,29 @@ public class GcpAuthAutoConfigurationCustomizerProvider
4653
static final String QUOTA_USER_PROJECT_HEADER = "x-goog-user-project";
4754
static final String GCP_USER_PROJECT_ID_KEY = "gcp.project_id";
4855

56+
static final String SIGNAL_TYPE_TRACES = "traces";
57+
static final String SIGNAL_TYPE_METRICS = "metrics";
58+
static final String SIGNAL_TYPE_ALL = "all";
59+
4960
/**
50-
* Customizes the provided {@link AutoConfigurationCustomizer}.
61+
* Customizes the provided {@link AutoConfigurationCustomizer} such that authenticated exports to
62+
* GCP Telemetry API are possible from the configured OTLP exporter.
5163
*
5264
* <p>This method attempts to retrieve Google Application Default Credentials (ADC) and performs
53-
* the following: - Adds authorization headers to the configured {@link SpanExporter} based on the
54-
* retrieved credentials. - Adds default properties for OTLP endpoint and resource attributes for
55-
* GCP integration.
65+
* the following:
66+
*
67+
* <ul>
68+
* <li>Verifies whether the configured OTLP endpoint (base or signal specific) is a known GCP
69+
* endpoint.
70+
* <li>If the configured base OTLP endpoint is a known GCP Telemetry API endpoint, customizes
71+
* both the configured OTLP {@link SpanExporter} and {@link MetricExporter}.
72+
* <li>If the configured signal specific endpoint is a known GCP Telemetry API endpoint,
73+
* customizes only the signal specific exporter.
74+
* </ul>
75+
*
76+
* The 'customization' performed includes customizing the exporters by adding required headers to
77+
* the export calls made and customizing the resource by adding required resource attributes to
78+
* enable GCP integration.
5679
*
5780
* @param autoConfiguration the AutoConfigurationCustomizer to customize.
5881
* @throws GoogleAuthException if there's an error retrieving Google Application Default
@@ -61,7 +84,7 @@ public class GcpAuthAutoConfigurationCustomizerProvider
6184
* not configured through environment variables or system properties.
6285
*/
6386
@Override
64-
public void customize(AutoConfigurationCustomizer autoConfiguration) {
87+
public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) {
6588
GoogleCredentials credentials;
6689
try {
6790
credentials = GoogleCredentials.getApplicationDefault();
@@ -70,7 +93,10 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) {
7093
}
7194
autoConfiguration
7295
.addSpanExporterCustomizer(
73-
(exporter, configProperties) -> addAuthorizationHeaders(exporter, credentials))
96+
(spanExporter, configProperties) -> customizeSpanExporter(spanExporter, credentials))
97+
.addMetricExporterCustomizer(
98+
(metricExporter, configProperties) ->
99+
customizeMetricExporter(metricExporter, credentials))
74100
.addResourceCustomizer(GcpAuthAutoConfigurationCustomizerProvider::customizeResource);
75101
}
76102

@@ -79,6 +105,34 @@ public int order() {
79105
return Integer.MAX_VALUE - 1;
80106
}
81107

108+
private static SpanExporter customizeSpanExporter(
109+
SpanExporter exporter, GoogleCredentials credentials) {
110+
if (isSignalTargeted(SIGNAL_TYPE_TRACES)) {
111+
return addAuthorizationHeaders(exporter, credentials);
112+
}
113+
return exporter;
114+
}
115+
116+
private static MetricExporter customizeMetricExporter(
117+
MetricExporter exporter, GoogleCredentials credentials) {
118+
if (isSignalTargeted(SIGNAL_TYPE_METRICS)) {
119+
return addAuthorizationHeaders(exporter, credentials);
120+
}
121+
return exporter;
122+
}
123+
124+
// Checks if the auth extension is configured to target the passed signal for authentication.
125+
private static boolean isSignalTargeted(String checkSignal) {
126+
String userSpecifiedTargetedSignals =
127+
ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValueWithFallback(
128+
() -> SIGNAL_TYPE_ALL);
129+
return Arrays.stream(userSpecifiedTargetedSignals.split(","))
130+
.map(String::trim)
131+
.anyMatch(
132+
targetedSignal ->
133+
targetedSignal.equals(checkSignal) || targetedSignal.equals(SIGNAL_TYPE_ALL));
134+
}
135+
82136
// Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and
83137
// OtlpHttpSpanExporter.
84138
private static SpanExporter addAuthorizationHeaders(
@@ -97,6 +151,24 @@ private static SpanExporter addAuthorizationHeaders(
97151
return exporter;
98152
}
99153

154+
// Adds authorization headers to the calls made by the OtlpGrpcMetricExporter and
155+
// OtlpHttpMetricExporter.
156+
private static MetricExporter addAuthorizationHeaders(
157+
MetricExporter exporter, GoogleCredentials credentials) {
158+
if (exporter instanceof OtlpHttpMetricExporter) {
159+
OtlpHttpMetricExporterBuilder builder =
160+
((OtlpHttpMetricExporter) exporter)
161+
.toBuilder().setHeaders(() -> getRequiredHeaderMap(credentials));
162+
return builder.build();
163+
} else if (exporter instanceof OtlpGrpcMetricExporter) {
164+
OtlpGrpcMetricExporterBuilder builder =
165+
((OtlpGrpcMetricExporter) exporter)
166+
.toBuilder().setHeaders(() -> getRequiredHeaderMap(credentials));
167+
return builder.build();
168+
}
169+
return exporter;
170+
}
171+
100172
private static Map<String, String> getRequiredHeaderMap(GoogleCredentials credentials) {
101173
Map<String, List<String>> gcpHeaders;
102174
try {

0 commit comments

Comments
 (0)