Skip to content

Commit cce0f6a

Browse files
authored
Demonstrate OTLP exporter programmatic authentication (#565)
1 parent 7ff9118 commit cce0f6a

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package otel;
2+
3+
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
4+
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
5+
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
6+
import java.time.Duration;
7+
import java.time.Instant;
8+
import java.util.Collections;
9+
import java.util.Map;
10+
import java.util.function.Supplier;
11+
12+
public class OtlpAuthenticationConfig {
13+
public static void staticAuthenticationHeader(String endpoint) {
14+
// If the OTLP destination accepts a static, long-lived authentication header like an API key,
15+
// set it as a header.
16+
// This reads the API key from the OTLP_API_KEY env var to avoid hard coding the secret in
17+
// source code.
18+
String apiKeyHeaderName = "api-key";
19+
String apiKeyHeaderValue = System.getenv("OTLP_API_KEY");
20+
21+
// Initialize OTLP Span, Metric, and LogRecord exporters using a similar pattern
22+
OtlpHttpSpanExporter spanExporter =
23+
OtlpHttpSpanExporter.builder()
24+
.setEndpoint(endpoint)
25+
.addHeader(apiKeyHeaderName, apiKeyHeaderValue)
26+
.build();
27+
OtlpHttpMetricExporter metricExporter =
28+
OtlpHttpMetricExporter.builder()
29+
.setEndpoint(endpoint)
30+
.addHeader(apiKeyHeaderName, apiKeyHeaderValue)
31+
.build();
32+
OtlpHttpLogRecordExporter logRecordExporter =
33+
OtlpHttpLogRecordExporter.builder()
34+
.setEndpoint(endpoint)
35+
.addHeader(apiKeyHeaderName, apiKeyHeaderValue)
36+
.build();
37+
}
38+
39+
public static void dynamicAuthenticationHeader(String endpoint) {
40+
// If the OTLP destination requires a dynamic authentication header, such as a JWT which needs
41+
// to be periodically refreshed, use a header supplier.
42+
// Here we implement a simple supplier which adds a header of the form "Authorization: Bearer
43+
// <token>", where <token> is fetched from refreshBearerToken every 10 minutes.
44+
String username = System.getenv("OTLP_USERNAME");
45+
String password = System.getenv("OTLP_PASSWORD");
46+
Supplier<Map<String, String>> supplier =
47+
new AuthHeaderSupplier(() -> refreshToken(username, password), Duration.ofMinutes(10));
48+
49+
// Initialize OTLP Span, Metric, and LogRecord exporters using a similar pattern
50+
OtlpHttpSpanExporter spanExporter =
51+
OtlpHttpSpanExporter.builder().setEndpoint(endpoint).setHeaders(supplier).build();
52+
OtlpHttpMetricExporter metricExporter =
53+
OtlpHttpMetricExporter.builder().setEndpoint(endpoint).setHeaders(supplier).build();
54+
OtlpHttpLogRecordExporter logRecordExporter =
55+
OtlpHttpLogRecordExporter.builder().setEndpoint(endpoint).setHeaders(supplier).build();
56+
}
57+
58+
private static class AuthHeaderSupplier implements Supplier<Map<String, String>> {
59+
private final Supplier<String> tokenRefresher;
60+
private final Duration tokenRefreshInterval;
61+
private Instant refreshedAt = Instant.ofEpochMilli(0);
62+
private String currentTokenValue;
63+
64+
private AuthHeaderSupplier(Supplier<String> tokenRefresher, Duration tokenRefreshInterval) {
65+
this.tokenRefresher = tokenRefresher;
66+
this.tokenRefreshInterval = tokenRefreshInterval;
67+
}
68+
69+
@Override
70+
public Map<String, String> get() {
71+
return Collections.singletonMap("Authorization", "Bearer " + getToken());
72+
}
73+
74+
private synchronized String getToken() {
75+
Instant now = Instant.now();
76+
if (currentTokenValue == null || now.isAfter(refreshedAt.plus(tokenRefreshInterval))) {
77+
currentTokenValue = tokenRefresher.get();
78+
refreshedAt = now;
79+
}
80+
return currentTokenValue;
81+
}
82+
}
83+
84+
private static String refreshToken(String username, String password) {
85+
// For a production scenario, this would be replaced with out-of-band request to exchange
86+
// username / password for bearer token.
87+
return "abc123";
88+
}
89+
}

0 commit comments

Comments
 (0)