Merge remote-tracking branch 'otel/HEAD' into span-processor-metrics
This commit is contained in:
commit
4b6cf9358c
|
|
@ -74,5 +74,12 @@
|
|||
'com.diffplug.spotless{/,}**',
|
||||
],
|
||||
},
|
||||
{
|
||||
// equals verifier v4+ requires java 17+
|
||||
groupName: 'nl.jqno.equalsverifier',
|
||||
matchPackageNames: [ 'equalsverifier'],
|
||||
matchUpdateTypes: [ 'major' ],
|
||||
enabled: false
|
||||
}
|
||||
],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ jobs:
|
|||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
- name: Run jmh
|
||||
run: ./gradlew jmhJar
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ jobs:
|
|||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
- name: Run jmh
|
||||
run: ./gradlew jmhJar
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ jobs:
|
|||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
- name: Build
|
||||
run: >
|
||||
./gradlew build
|
||||
|
|
@ -145,7 +145,7 @@ jobs:
|
|||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
# skipping release branches because the versions in those branches are not snapshots
|
||||
# (also this skips pull requests)
|
||||
if: ${{ github.ref_name == 'main' && github.repository == 'open-telemetry/opentelemetry-java' }}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ on:
|
|||
- release/*
|
||||
- benchmarks
|
||||
schedule:
|
||||
- cron: "29 13 * * 2" # weekly at 13:29 UTC on Tuesday
|
||||
- cron: "23 16 * * 2" # weekly at 16:23 UTC on Tuesday
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -23,32 +23,43 @@ jobs:
|
|||
contents: read
|
||||
actions: read # for github/codeql-action/init to get workflow details
|
||||
security-events: write # for github/codeql-action/analyze to upload SARIF results
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: actions
|
||||
- language: java
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Java 17
|
||||
if: matrix.language == 'java'
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
if: matrix.language == 'java'
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
|
||||
with:
|
||||
languages: java, actions
|
||||
languages: ${{ matrix.language }}
|
||||
# using "latest" helps to keep up with the latest Kotlin support
|
||||
# see https://github.com/github/codeql-action/issues/1555#issuecomment-1452228433
|
||||
tools: latest
|
||||
|
||||
- name: Assemble
|
||||
if: matrix.language == 'java'
|
||||
# --no-build-cache is required for codeql to analyze all modules
|
||||
# --no-daemon is required for codeql to observe the compilation
|
||||
# (see https://docs.github.com/en/code-security/codeql-cli/getting-started-with-the-codeql-cli/preparing-your-code-for-codeql-analysis#specifying-build-commands)
|
||||
run: ./gradlew assemble --no-build-cache --no-daemon
|
||||
|
||||
- name: Perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
|
@ -13,4 +13,4 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: gradle/actions/wrapper-validation@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
- uses: gradle/actions/wrapper-validation@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Run crawler
|
||||
run: ./gradlew :javadoc-crawler:crawl
|
||||
|
|
|
|||
|
|
@ -42,6 +42,6 @@ jobs:
|
|||
# Upload the results to GitHub's code scanning dashboard (optional).
|
||||
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Check dependencies
|
||||
run: ./gradlew dependencyCheckAnalyze
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
java-version: 17
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||
uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
|
||||
|
||||
- name: Build and publish artifacts
|
||||
run: ./gradlew assemble publishToSonatype closeAndReleaseSonatypeStagingRepository
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import io.opentelemetry.api.trace.TracerProvider;
|
|||
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
|
@ -116,6 +117,19 @@ public final class GlobalOpenTelemetry {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OpenTelemetry} that should be the global instance.
|
||||
*
|
||||
* <p>This method calls the given {@code supplier} and calls {@link #set(OpenTelemetry)}, all
|
||||
* while holding the {@link GlobalOpenTelemetry} mutex.
|
||||
*/
|
||||
public static void set(Supplier<OpenTelemetry> supplier) {
|
||||
synchronized (mutex) {
|
||||
OpenTelemetry openTelemetry = supplier.get();
|
||||
set(openTelemetry);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the globally registered {@link TracerProvider}. */
|
||||
public static TracerProvider getTracerProvider() {
|
||||
return get().getTracerProvider();
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ java {
|
|||
|
||||
checkstyle {
|
||||
configDirectory.set(file("$rootDir/buildscripts/"))
|
||||
toolVersion = "10.25.0"
|
||||
toolVersion = "10.26.0"
|
||||
isIgnoreFailures = false
|
||||
configProperties["rootDir"] = rootDir
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,8 @@ final class LazyStorage {
|
|||
}
|
||||
|
||||
List<ContextStorageProvider> providers = new ArrayList<>();
|
||||
for (ContextStorageProvider provider : ServiceLoader.load(ContextStorageProvider.class)) {
|
||||
for (ContextStorageProvider provider :
|
||||
ServiceLoader.load(ContextStorageProvider.class, LazyStorage.class.getClassLoader())) {
|
||||
if (provider
|
||||
.getClass()
|
||||
.getName()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ val DEPENDENCY_BOMS = listOf(
|
|||
// (which is EPL licensed) or armeria bom (which is Apache licensed but is getting flagged
|
||||
// by FOSSA for containing EPL-licensed)
|
||||
|
||||
"com.fasterxml.jackson:jackson-bom:2.19.0",
|
||||
"com.fasterxml.jackson:jackson-bom:2.19.1",
|
||||
"com.google.guava:guava-bom:33.4.8-jre",
|
||||
"com.google.protobuf:protobuf-bom:4.31.1",
|
||||
"com.squareup.okhttp3:okhttp-bom:4.12.0",
|
||||
|
|
@ -23,7 +23,7 @@ val DEPENDENCY_BOMS = listOf(
|
|||
"io.zipkin.brave:brave-bom:6.3.0",
|
||||
"io.zipkin.reporter2:zipkin-reporter-bom:3.5.1",
|
||||
"org.assertj:assertj-bom:3.27.3",
|
||||
"org.testcontainers:testcontainers-bom:1.21.1",
|
||||
"org.testcontainers:testcontainers-bom:1.21.2",
|
||||
"org.snakeyaml:snakeyaml-engine:2.9"
|
||||
)
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ val DEPENDENCIES = listOf(
|
|||
"io.prometheus:prometheus-metrics-exposition-formats-no-protobuf:${prometheusServerVersion}",
|
||||
"javax.annotation:javax.annotation-api:1.3.2",
|
||||
"com.github.stefanbirkner:system-rules:1.19.0",
|
||||
"com.google.api.grpc:proto-google-common-protos:2.58.0",
|
||||
"com.google.api.grpc:proto-google-common-protos:2.58.2",
|
||||
"com.google.code.findbugs:jsr305:3.0.2",
|
||||
"com.google.guava:guava-beta-checker:1.0",
|
||||
"com.sun.net.httpserver:http:20070405",
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
Comparing source compatibility of opentelemetry-api-1.52.0-SNAPSHOT.jar against opentelemetry-api-1.51.0.jar
|
||||
No changes.
|
||||
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.api.GlobalOpenTelemetry (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++ NEW METHOD: PUBLIC(+) STATIC(+) void set(java.util.function.Supplier<io.opentelemetry.api.OpenTelemetry>)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.13.4@sha256:eb120d016adcbc8bac194e15826bbb4f1d1569d298d8817bb5049ed5e59f41d9 AS build
|
||||
FROM python:3.13.5@sha256:5f69d22a88dd4cc4ee1576def19aef48c8faa1b566054c44291183831cbad13b AS build
|
||||
|
||||
# Main branch SHA as of April-1-2021
|
||||
ARG TRACECONTEXT_GIT_TAG="dcd3ad9b7d6ac36f70ff3739874b73c11b0302a1"
|
||||
|
|
@ -11,7 +11,7 @@ RUN unzip trace-context.zip
|
|||
RUN rm trace-context.zip
|
||||
RUN mv trace-context-${TRACECONTEXT_GIT_TAG}/test /tracecontext-testsuite
|
||||
|
||||
FROM python:3.13.4-slim@sha256:d97b595c5f4ac718102e5a5a91adaf04b22e852961a698411637c718d45867c8
|
||||
FROM python:3.13.5-slim@sha256:f2fdaec50160418e0c2867ba3e254755edd067171725886d5d303fd7057bbf81
|
||||
|
||||
RUN pip install aiohttp
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
|
@ -424,6 +426,25 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
* the settings of this {@link AutoConfiguredOpenTelemetrySdkBuilder}.
|
||||
*/
|
||||
public AutoConfiguredOpenTelemetrySdk build() {
|
||||
if (!setResultAsGlobal) {
|
||||
return buildImpl();
|
||||
}
|
||||
AtomicReference<AutoConfiguredOpenTelemetrySdk> autoConfiguredRef = new AtomicReference<>();
|
||||
GlobalOpenTelemetry.set(
|
||||
() -> {
|
||||
AutoConfiguredOpenTelemetrySdk sdk = buildImpl();
|
||||
autoConfiguredRef.set(sdk);
|
||||
return sdk.getOpenTelemetrySdk();
|
||||
});
|
||||
AutoConfiguredOpenTelemetrySdk sdk = Objects.requireNonNull(autoConfiguredRef.get());
|
||||
logger.log(
|
||||
Level.FINE,
|
||||
"Global OpenTelemetry set to {0} by autoconfiguration",
|
||||
sdk.getOpenTelemetrySdk());
|
||||
return sdk;
|
||||
}
|
||||
|
||||
private AutoConfiguredOpenTelemetrySdk buildImpl() {
|
||||
SpiHelper spiHelper = SpiHelper.create(componentLoader);
|
||||
if (!customized) {
|
||||
customized = true;
|
||||
|
|
@ -440,8 +461,10 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
maybeConfigureFromFile(config, componentLoader);
|
||||
if (fromFileConfiguration != null) {
|
||||
maybeRegisterShutdownHook(fromFileConfiguration.getOpenTelemetrySdk());
|
||||
maybeSetAsGlobal(
|
||||
fromFileConfiguration.getOpenTelemetrySdk(), fromFileConfiguration.getConfigProvider());
|
||||
Object configProvider = fromFileConfiguration.getConfigProvider();
|
||||
if (setResultAsGlobal && INCUBATOR_AVAILABLE && configProvider != null) {
|
||||
IncubatingUtil.setGlobalConfigProvider(configProvider);
|
||||
}
|
||||
return fromFileConfiguration;
|
||||
}
|
||||
|
||||
|
|
@ -467,7 +490,6 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
|
||||
OpenTelemetrySdk openTelemetrySdk = sdkBuilder.build();
|
||||
maybeRegisterShutdownHook(openTelemetrySdk);
|
||||
maybeSetAsGlobal(openTelemetrySdk, null);
|
||||
callAutoConfigureListeners(spiHelper, openTelemetrySdk);
|
||||
|
||||
return AutoConfiguredOpenTelemetrySdk.create(openTelemetrySdk, resource, config, null);
|
||||
|
|
@ -572,19 +594,6 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
Runtime.getRuntime().addShutdownHook(shutdownHook(openTelemetrySdk));
|
||||
}
|
||||
|
||||
private void maybeSetAsGlobal(
|
||||
OpenTelemetrySdk openTelemetrySdk, @Nullable Object configProvider) {
|
||||
if (!setResultAsGlobal) {
|
||||
return;
|
||||
}
|
||||
GlobalOpenTelemetry.set(openTelemetrySdk);
|
||||
if (INCUBATOR_AVAILABLE && configProvider != null) {
|
||||
IncubatingUtil.setGlobalConfigProvider(configProvider);
|
||||
}
|
||||
logger.log(
|
||||
Level.FINE, "Global OpenTelemetry set to {0} by autoconfiguration", openTelemetrySdk);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
void callAutoConfigureListeners(SpiHelper spiHelper, OpenTelemetrySdk openTelemetrySdk) {
|
||||
for (AutoConfigureListener listener : spiHelper.getListeners()) {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import io.opentelemetry.sdk.trace.data.SpanData;
|
|||
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
|
||||
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collections;
|
||||
|
|
@ -65,7 +66,13 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
|
@ -674,4 +681,66 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
|
||||
logs.assertContains("Error closing io.opentelemetry.sdk.trace.SdkTracerProvider: Error!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalOpenTelemetryLock() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
CountDownLatch autoconfigStarted = new CountDownLatch(1);
|
||||
CountDownLatch completeAutoconfig = new CountDownLatch(1);
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(2);
|
||||
|
||||
// Submit a future to autoconfigure the SDK and set the result as global. Add a customization
|
||||
// hook which blocks until we say so.
|
||||
CompletableFuture<OpenTelemetrySdk> autoConfiguredOpenTelemetryFuture =
|
||||
CompletableFuture.supplyAsync(
|
||||
() ->
|
||||
builder
|
||||
.addLoggerProviderCustomizer(
|
||||
(sdkLoggerProviderBuilder, configProperties) -> {
|
||||
autoconfigStarted.countDown();
|
||||
try {
|
||||
completeAutoconfig.await();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return sdkLoggerProviderBuilder;
|
||||
})
|
||||
.setResultAsGlobal()
|
||||
.build()
|
||||
.getOpenTelemetrySdk(),
|
||||
executorService);
|
||||
|
||||
// Wait for autoconfiguration to enter our callback, then try to get an instance of
|
||||
// GlobalOpenTelemetry. GlobalOpenTelemetry.get() should block until we release the
|
||||
// completeAutoconfig latch and allow autoconfiguration to complete.
|
||||
autoconfigStarted.await();
|
||||
CompletableFuture<OpenTelemetry> globalOpenTelemetryFuture =
|
||||
CompletableFuture.supplyAsync(GlobalOpenTelemetry::get, executorService);
|
||||
Thread.sleep(10);
|
||||
assertThat(globalOpenTelemetryFuture.isDone()).isFalse();
|
||||
assertThat(autoConfiguredOpenTelemetryFuture.isDone()).isFalse();
|
||||
|
||||
// Release the latch, allowing autoconfiguration to complete. Confirm that our
|
||||
// GlobalOpenTelemetry.get() future resolved to the same instance as autoconfiguration.
|
||||
completeAutoconfig.countDown();
|
||||
assertThat(unobfuscate(globalOpenTelemetryFuture.get(10, TimeUnit.SECONDS)))
|
||||
.isSameAs(autoConfiguredOpenTelemetryFuture.get(10, TimeUnit.SECONDS));
|
||||
|
||||
// Cleanup
|
||||
executorService.shutdown();
|
||||
autoConfiguredOpenTelemetryFuture.get().shutdown().join(10, TimeUnit.SECONDS);
|
||||
GlobalOpenTelemetry.resetForTest();
|
||||
}
|
||||
|
||||
private static OpenTelemetry unobfuscate(OpenTelemetry openTelemetry) {
|
||||
try {
|
||||
Field delegateField =
|
||||
Class.forName("io.opentelemetry.api.GlobalOpenTelemetry$ObfuscatedOpenTelemetry")
|
||||
.getDeclaredField("delegate");
|
||||
delegateField.setAccessible(true);
|
||||
Object delegate = delegateField.get(openTelemetry);
|
||||
return (OpenTelemetry) delegate;
|
||||
} catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
|
||||
throw new IllegalStateException("Error unobfuscating OpenTelemetry", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class DeclarativeConfigurationTest {
|
|||
@Test
|
||||
void configFile(@TempDir Path tempDir) throws IOException {
|
||||
String yaml =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "resource:\n"
|
||||
+ " attributes:\n"
|
||||
+ " - name: service.name\n"
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class DeclarativeConfigurationTest {
|
|||
@BeforeEach
|
||||
void setup() throws IOException {
|
||||
String yaml =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "resource:\n"
|
||||
+ " attributes:\n"
|
||||
+ " - name: service.name\n"
|
||||
|
|
@ -199,7 +199,7 @@ class DeclarativeConfigurationTest {
|
|||
@Test
|
||||
void configFile_Error(@TempDir Path tempDir) throws IOException {
|
||||
String yaml =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "resource:\n"
|
||||
+ " attributes:\n"
|
||||
+ " - name: service.name\n"
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ dependencies {
|
|||
// 7. deleteJs2pTmp - delete tmp directory
|
||||
// ... proceed with normal sourcesJar, compileJava, etc
|
||||
|
||||
val configurationTag = "0.4.0"
|
||||
val configurationTag = "1.0.0-rc.1"
|
||||
val configurationRef = "refs/tags/v$configurationTag" // Replace with commit SHA to point to experiment with a specific commit
|
||||
val configurationRepoZip = "https://github.com/open-telemetry/opentelemetry-configuration/archive/$configurationRef.zip"
|
||||
val buildDirectory = layout.buildDirectory.asFile.get()
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@ import io.opentelemetry.sdk.OpenTelemetrySdkBuilder;
|
|||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
final class OpenTelemetryConfigurationFactory
|
||||
implements Factory<OpenTelemetryConfigurationModel, OpenTelemetrySdk> {
|
||||
|
||||
private static final String CURRENT_SUPPORTED_FILE_FORMAT = "0.4";
|
||||
private static final Pattern SUPPORTED_FILE_FORMATS = Pattern.compile("^(0.4)|(1.0(-rc.\\d*)?)$");
|
||||
|
||||
private static final OpenTelemetryConfigurationFactory INSTANCE =
|
||||
new OpenTelemetryConfigurationFactory();
|
||||
|
|
@ -30,10 +31,13 @@ final class OpenTelemetryConfigurationFactory
|
|||
public OpenTelemetrySdk create(
|
||||
OpenTelemetryConfigurationModel model, DeclarativeConfigContext context) {
|
||||
OpenTelemetrySdkBuilder builder = OpenTelemetrySdk.builder();
|
||||
if (!CURRENT_SUPPORTED_FILE_FORMAT.equals(model.getFileFormat())) {
|
||||
String fileFormat = model.getFileFormat();
|
||||
if (fileFormat == null || !SUPPORTED_FILE_FORMATS.matcher(fileFormat).matches()) {
|
||||
throw new DeclarativeConfigException(
|
||||
"Unsupported file format. Supported formats include: " + CURRENT_SUPPORTED_FILE_FORMAT);
|
||||
"Unsupported file format. Supported formats include 0.4, 1.0*");
|
||||
}
|
||||
// TODO(jack-berg): log warning if version is not exact match, which may result in unexpected
|
||||
// behavior for experimental properties.
|
||||
|
||||
if (Objects.equals(Boolean.TRUE, model.getDisabled())) {
|
||||
return builder.build();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.sdk.resources.ResourceBuilder;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ServiceResourceDetector implements ComponentProvider<Resource> {
|
||||
|
||||
private static final AttributeKey<String> SERVICE_NAME = AttributeKey.stringKey("service.name");
|
||||
private static final AttributeKey<String> SERVICE_INSTANCE_ID =
|
||||
AttributeKey.stringKey("service.instance.id");
|
||||
|
||||
// multiple calls to this resource provider should return the same value
|
||||
private static final String RANDOM_SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
|
||||
|
||||
@Override
|
||||
public Class<Resource> getType() {
|
||||
return Resource.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "service";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource create(DeclarativeConfigProperties config) {
|
||||
ResourceBuilder builder = Resource.builder();
|
||||
|
||||
ConfigProperties properties = DefaultConfigProperties.create(Collections.emptyMap());
|
||||
String serviceName = properties.getString("otel.service.name");
|
||||
if (serviceName != null) {
|
||||
builder.put(SERVICE_NAME, serviceName).build();
|
||||
}
|
||||
|
||||
builder.put(SERVICE_INSTANCE_ID, RANDOM_SERVICE_INSTANCE_ID);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
io.opentelemetry.sdk.extension.incubator.fileconfig.ServiceResourceDetector
|
||||
|
|
@ -106,7 +106,7 @@ class DeclarativeConfigurationCreateTest {
|
|||
// exporter with OTLP exporter, following by invalid batch exporter which references invalid
|
||||
// exporter "foo".
|
||||
String yaml =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "logger_provider:\n"
|
||||
+ " processors:\n"
|
||||
+ " - batch:\n"
|
||||
|
|
@ -133,7 +133,7 @@ class DeclarativeConfigurationCreateTest {
|
|||
@Test
|
||||
void parseAndCreate_EmptyComponentProviderConfig() {
|
||||
String yaml =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "logger_provider:\n"
|
||||
+ " processors:\n"
|
||||
+ " - test:\n"
|
||||
|
|
@ -151,7 +151,7 @@ class DeclarativeConfigurationCreateTest {
|
|||
@Test
|
||||
void create_ModelCustomizer() {
|
||||
OpenTelemetryConfigurationModel model = new OpenTelemetryConfigurationModel();
|
||||
model.withFileFormat("0.4");
|
||||
model.withFileFormat("1.0-rc.1");
|
||||
model.withTracerProvider(
|
||||
new TracerProviderModel()
|
||||
.withProcessors(
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class DeclarativeConfigurationParseTest {
|
|||
void parse_KitchenSinkExampleFile() throws IOException {
|
||||
OpenTelemetryConfigurationModel expected = new OpenTelemetryConfigurationModel();
|
||||
|
||||
expected.withFileFormat("0.4");
|
||||
expected.withFileFormat("1.0-rc.1");
|
||||
expected.withDisabled(false);
|
||||
expected.withLogLevel("info");
|
||||
|
||||
|
|
@ -171,9 +171,9 @@ class DeclarativeConfigurationParseTest {
|
|||
new ExperimentalResourceDetectorModel()
|
||||
.withAdditionalProperty("host", null),
|
||||
new ExperimentalResourceDetectorModel()
|
||||
.withAdditionalProperty("os", null),
|
||||
.withAdditionalProperty("process", null),
|
||||
new ExperimentalResourceDetectorModel()
|
||||
.withAdditionalProperty("process", null))))
|
||||
.withAdditionalProperty("service", null))))
|
||||
.withSchemaUrl("https://opentelemetry.io/schemas/1.16.0");
|
||||
expected.withResource(resource);
|
||||
|
||||
|
|
@ -705,7 +705,7 @@ class DeclarativeConfigurationParseTest {
|
|||
OpenTelemetryConfigurationModel config = DeclarativeConfiguration.parse(configExampleFile);
|
||||
|
||||
// General config
|
||||
assertThat(config.getFileFormat()).isEqualTo("0.4");
|
||||
assertThat(config.getFileFormat()).isEqualTo("1.0-rc.1");
|
||||
assertThat(config.getResource()).isEqualTo(resource);
|
||||
assertThat(config.getAttributeLimits()).isEqualTo(attributeLimits);
|
||||
assertThat(config.getPropagator()).isEqualTo(propagator);
|
||||
|
|
@ -770,7 +770,7 @@ class DeclarativeConfigurationParseTest {
|
|||
@Test
|
||||
void parse_nullValuesParsedToEmptyObjects() {
|
||||
String objectPlaceholderString =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "tracer_provider:\n"
|
||||
+ " processors:\n"
|
||||
+ " - batch:\n"
|
||||
|
|
@ -788,7 +788,7 @@ class DeclarativeConfigurationParseTest {
|
|||
new ByteArrayInputStream(objectPlaceholderString.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
String noOjbectPlaceholderString =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "tracer_provider:\n"
|
||||
+ " processors:\n"
|
||||
+ " - batch:\n"
|
||||
|
|
@ -986,7 +986,7 @@ class DeclarativeConfigurationParseTest {
|
|||
@Test
|
||||
void read_WithEnvironmentVariables() {
|
||||
String yaml =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "tracer_provider:\n"
|
||||
+ " processors:\n"
|
||||
+ " - batch:\n"
|
||||
|
|
@ -1005,7 +1005,7 @@ class DeclarativeConfigurationParseTest {
|
|||
assertThat(model)
|
||||
.isEqualTo(
|
||||
new OpenTelemetryConfigurationModel()
|
||||
.withFileFormat("0.4")
|
||||
.withFileFormat("1.0-rc.1")
|
||||
.withTracerProvider(
|
||||
new TracerProviderModel()
|
||||
.withProcessors(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
|||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOn;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
|
||||
|
|
@ -63,8 +64,12 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class OpenTelemetryConfigurationFactoryTest {
|
||||
|
||||
|
|
@ -74,23 +79,41 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
new DeclarativeConfigContext(
|
||||
SpiHelper.create(OpenTelemetryConfigurationFactoryTest.class.getClassLoader()));
|
||||
|
||||
@Test
|
||||
void create_InvalidFileFormat() {
|
||||
List<OpenTelemetryConfigurationModel> testCases =
|
||||
Arrays.asList(
|
||||
new OpenTelemetryConfigurationModel(),
|
||||
new OpenTelemetryConfigurationModel().withFileFormat("1"));
|
||||
@ParameterizedTest
|
||||
@MethodSource("fileFormatArgs")
|
||||
void create_FileFormat(String fileFormat, boolean isValid) {
|
||||
OpenTelemetryConfigurationModel model =
|
||||
new OpenTelemetryConfigurationModel().withFileFormat(fileFormat);
|
||||
|
||||
List<Closeable> closeables = new ArrayList<>();
|
||||
for (OpenTelemetryConfigurationModel testCase : testCases) {
|
||||
if (isValid) {
|
||||
assertThatCode(() -> OpenTelemetryConfigurationFactory.getInstance().create(model, context))
|
||||
.doesNotThrowAnyException();
|
||||
} else {
|
||||
assertThatThrownBy(
|
||||
() -> OpenTelemetryConfigurationFactory.getInstance().create(testCase, context))
|
||||
() -> OpenTelemetryConfigurationFactory.getInstance().create(model, context))
|
||||
.isInstanceOf(DeclarativeConfigException.class)
|
||||
.hasMessage("Unsupported file format. Supported formats include: 0.4");
|
||||
cleanup.addCloseables(closeables);
|
||||
.hasMessage("Unsupported file format. Supported formats include 0.4, 1.0*");
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream<Arguments> fileFormatArgs() {
|
||||
return Stream.of(
|
||||
// Invalid file formats
|
||||
Arguments.of(null, false),
|
||||
Arguments.of("0.3", false),
|
||||
Arguments.of("a0.4", false),
|
||||
Arguments.of("0.4a", false),
|
||||
Arguments.of("foo", false),
|
||||
Arguments.of("1.0-rc.a", false),
|
||||
Arguments.of("1.0.0", false),
|
||||
Arguments.of("1.0.3", false),
|
||||
// Valid file formats
|
||||
Arguments.of("0.4", true),
|
||||
Arguments.of("1.0-rc.1", true),
|
||||
Arguments.of("1.0-rc.2", true),
|
||||
Arguments.of("1.0", true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void create_Defaults() {
|
||||
List<Closeable> closeables = new ArrayList<>();
|
||||
|
|
@ -99,7 +122,7 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
|
||||
OpenTelemetrySdk sdk =
|
||||
OpenTelemetryConfigurationFactory.getInstance()
|
||||
.create(new OpenTelemetryConfigurationModel().withFileFormat("0.4"), context);
|
||||
.create(new OpenTelemetryConfigurationModel().withFileFormat("1.0-rc.1"), context);
|
||||
cleanup.addCloseable(sdk);
|
||||
cleanup.addCloseables(closeables);
|
||||
|
||||
|
|
@ -116,7 +139,7 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
OpenTelemetryConfigurationFactory.getInstance()
|
||||
.create(
|
||||
new OpenTelemetryConfigurationModel()
|
||||
.withFileFormat("0.4")
|
||||
.withFileFormat("1.0-rc.1")
|
||||
.withDisabled(true)
|
||||
// Logger provider configuration should be ignored since SDK is disabled
|
||||
.withLoggerProvider(
|
||||
|
|
@ -210,7 +233,7 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
OpenTelemetryConfigurationFactory.getInstance()
|
||||
.create(
|
||||
new OpenTelemetryConfigurationModel()
|
||||
.withFileFormat("0.4")
|
||||
.withFileFormat("1.0-rc.1")
|
||||
.withPropagator(
|
||||
new PropagatorModel()
|
||||
.withCompositeList("tracecontext,baggage,ottrace,b3multi,b3,jaeger"))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junitpioneer.jupiter.ClearSystemProperty;
|
||||
|
||||
class ServiceResourceDetectorTest {
|
||||
|
||||
@Test
|
||||
void getTypeAndName() {
|
||||
ServiceResourceDetector detector = new ServiceResourceDetector();
|
||||
|
||||
assertThat(detector.getType()).isEqualTo(Resource.class);
|
||||
assertThat(detector.getName()).isEqualTo("service");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ClearSystemProperty(key = "otel.service.name")
|
||||
void create_SystemPropertySet() {
|
||||
System.setProperty("otel.service.name", "test");
|
||||
|
||||
assertThat(new ServiceResourceDetector().create(DeclarativeConfigProperties.empty()))
|
||||
.satisfies(
|
||||
resource -> {
|
||||
Attributes attributes = resource.getAttributes();
|
||||
assertThat(attributes.get(AttributeKey.stringKey("service.name"))).isEqualTo("test");
|
||||
assertThatCode(
|
||||
() ->
|
||||
UUID.fromString(
|
||||
Objects.requireNonNull(
|
||||
attributes.get(AttributeKey.stringKey("service.instance.id")))))
|
||||
.doesNotThrowAnyException();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void create_NoSystemProperty() {
|
||||
assertThat(new ServiceResourceDetector().create(DeclarativeConfigProperties.empty()))
|
||||
.satisfies(
|
||||
resource -> {
|
||||
Attributes attributes = resource.getAttributes();
|
||||
assertThat(attributes.get(AttributeKey.stringKey("service.name"))).isNull();
|
||||
assertThatCode(
|
||||
() ->
|
||||
UUID.fromString(
|
||||
Objects.requireNonNull(
|
||||
attributes.get(AttributeKey.stringKey("service.instance.id")))))
|
||||
.doesNotThrowAnyException();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test;
|
|||
class YamlDeclarativeConfigPropertiesTest {
|
||||
|
||||
private static final String extendedSchema =
|
||||
"file_format: \"0.4\"\n"
|
||||
"file_format: \"1.0-rc.1\"\n"
|
||||
+ "disabled: false\n"
|
||||
+ "\n"
|
||||
+ "resource:\n"
|
||||
|
|
@ -69,7 +69,7 @@ class YamlDeclarativeConfigPropertiesTest {
|
|||
@Test
|
||||
void configurationSchema() {
|
||||
// Validate can read declarative configuration schema properties
|
||||
assertThat(structuredConfigProps.getString("file_format")).isEqualTo("0.4");
|
||||
assertThat(structuredConfigProps.getString("file_format")).isEqualTo("1.0-rc.1");
|
||||
DeclarativeConfigProperties resourceProps = structuredConfigProps.getStructured("resource");
|
||||
assertThat(resourceProps).isNotNull();
|
||||
List<DeclarativeConfigProperties> resourceAttributesList =
|
||||
|
|
|
|||
|
|
@ -81,7 +81,21 @@ public final class PeriodicMetricReader implements MetricReader {
|
|||
|
||||
@Override
|
||||
public CompletableResultCode forceFlush() {
|
||||
return scheduled.doRun();
|
||||
CompletableResultCode result = new CompletableResultCode();
|
||||
CompletableResultCode doRunResult = scheduled.doRun();
|
||||
doRunResult.whenComplete(
|
||||
() -> {
|
||||
CompletableResultCode flushResult = exporter.flush();
|
||||
flushResult.whenComplete(
|
||||
() -> {
|
||||
if (doRunResult.isSuccess() && flushResult.isSuccess()) {
|
||||
result.succeed();
|
||||
} else {
|
||||
result.fail();
|
||||
}
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -154,6 +154,35 @@ class PeriodicMetricReaderTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void forceflush_callsFlush() {
|
||||
MetricExporter metricExporter = mock(MetricExporter.class);
|
||||
when(metricExporter.export(any()))
|
||||
.thenReturn(CompletableResultCode.ofSuccess())
|
||||
.thenReturn(CompletableResultCode.ofSuccess())
|
||||
.thenThrow(new RuntimeException("Export Failed!"));
|
||||
when(metricExporter.flush())
|
||||
.thenReturn(CompletableResultCode.ofSuccess())
|
||||
.thenReturn(CompletableResultCode.ofFailure())
|
||||
.thenReturn(CompletableResultCode.ofSuccess());
|
||||
when(metricExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess());
|
||||
|
||||
PeriodicMetricReader reader =
|
||||
PeriodicMetricReader.builder(metricExporter)
|
||||
.setInterval(Duration.ofNanos(Long.MAX_VALUE))
|
||||
.build();
|
||||
|
||||
try {
|
||||
reader.register(collectionRegistration);
|
||||
assertThat(reader.forceFlush().join(10, TimeUnit.SECONDS).isSuccess()).isTrue();
|
||||
assertThat(reader.forceFlush().join(10, TimeUnit.SECONDS).isSuccess()).isFalse();
|
||||
assertThat(reader.forceFlush().join(10, TimeUnit.SECONDS).isSuccess()).isFalse();
|
||||
} finally {
|
||||
reader.shutdown();
|
||||
}
|
||||
verify(metricExporter, times(3)).flush();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timeout(2)
|
||||
@SuppressLogger(PeriodicMetricReader.class)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
pluginManagement {
|
||||
plugins {
|
||||
id("com.gradleup.shadow") version "8.3.6"
|
||||
id("com.gradleup.shadow") version "8.3.7"
|
||||
id("com.gradle.develocity") version "4.0.2"
|
||||
id("de.undercouch.download") version "5.6.0"
|
||||
id("org.jsonschema2pojo") version "1.2.2"
|
||||
|
|
|
|||
Loading…
Reference in New Issue