Skip to content

Commit bd0cf78

Browse files
authored
Ensure GlobalLoggerProvider is set once (#4804)
* Ensure GlobalLoggerProvider is set once * Add GlobalLoggerProviderTest * PR feedback
1 parent b0802ad commit bd0cf78

File tree

6 files changed

+86
-4
lines changed

6 files changed

+86
-4
lines changed

api/logs/src/main/java/io/opentelemetry/api/logs/GlobalLoggerProvider.java

+28-4
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,29 @@
66
package io.opentelemetry.api.logs;
77

88
import io.opentelemetry.api.GlobalOpenTelemetry;
9+
import java.util.concurrent.atomic.AtomicReference;
10+
import javax.annotation.Nullable;
911

1012
/**
1113
* This class provides a temporary global accessor for {@link LoggerProvider} until the log API is
1214
* marked stable. It will eventually be merged into {@link GlobalOpenTelemetry}.
1315
*/
16+
// We intentionally assign to be used for error reporting.
17+
@SuppressWarnings("StaticAssignmentOfThrowable")
1418
public final class GlobalLoggerProvider {
1519

16-
private static volatile LoggerProvider globalLoggerProvider = DefaultLoggerProvider.getInstance();
20+
private static final AtomicReference<LoggerProvider> instance =
21+
new AtomicReference<>(LoggerProvider.noop());
22+
23+
@Nullable private static volatile Throwable setInstanceCaller;
1724

1825
private GlobalLoggerProvider() {}
1926

2027
/** Returns the globally registered {@link LoggerProvider}. */
28+
// instance cannot be set to null
29+
@SuppressWarnings("NullAway")
2130
public static LoggerProvider get() {
22-
return globalLoggerProvider;
31+
return instance.get();
2332
}
2433

2534
/**
@@ -28,7 +37,22 @@ public static LoggerProvider get() {
2837
* application initialization logic.
2938
*/
3039
public static void set(LoggerProvider loggerProvider) {
31-
globalLoggerProvider =
32-
loggerProvider == null ? DefaultLoggerProvider.getInstance() : loggerProvider;
40+
boolean changed = instance.compareAndSet(LoggerProvider.noop(), loggerProvider);
41+
if (!changed && (loggerProvider != LoggerProvider.noop())) {
42+
throw new IllegalStateException(
43+
"GlobalLoggerProvider.set has already been called. GlobalLoggerProvider.set "
44+
+ "must be called only once before any calls to GlobalLoggerProvider.get. "
45+
+ "Previous invocation set to cause of this exception.",
46+
setInstanceCaller);
47+
}
48+
setInstanceCaller = new Throwable();
49+
}
50+
51+
/**
52+
* Unsets the global {@link LoggerProvider}. This is only meant to be used from tests which need
53+
* to reconfigure {@link LoggerProvider}.
54+
*/
55+
public static void resetForTest() {
56+
instance.set(LoggerProvider.noop());
3357
}
3458
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.api.logs;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
10+
11+
import org.junit.jupiter.api.AfterEach;
12+
import org.junit.jupiter.api.BeforeAll;
13+
import org.junit.jupiter.api.Test;
14+
15+
class GlobalLoggerProviderTest {
16+
17+
@BeforeAll
18+
static void beforeClass() {
19+
GlobalLoggerProvider.resetForTest();
20+
}
21+
22+
@AfterEach
23+
void after() {
24+
GlobalLoggerProvider.resetForTest();
25+
}
26+
27+
@Test
28+
void setAndGet() {
29+
assertThat(GlobalLoggerProvider.get()).isEqualTo(LoggerProvider.noop());
30+
LoggerProvider loggerProvider =
31+
instrumentationScopeName -> LoggerProvider.noop().loggerBuilder(instrumentationScopeName);
32+
GlobalLoggerProvider.set(loggerProvider);
33+
assertThat(GlobalLoggerProvider.get()).isEqualTo(loggerProvider);
34+
}
35+
36+
@Test
37+
void setThenSet() {
38+
GlobalLoggerProvider.set(
39+
instrumentationScopeName -> LoggerProvider.noop().loggerBuilder(instrumentationScopeName));
40+
assertThatThrownBy(
41+
() ->
42+
GlobalLoggerProvider.set(
43+
instrumentationScopeName ->
44+
LoggerProvider.noop().loggerBuilder(instrumentationScopeName)))
45+
.isInstanceOf(IllegalStateException.class)
46+
.hasMessageContaining("GlobalLoggerProvider.set has already been called")
47+
.hasStackTraceContaining("setThenSet");
48+
}
49+
}

sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public SdkLoggerProviderBuilder apply(
126126
@BeforeEach
127127
void resetGlobal() {
128128
GlobalOpenTelemetry.resetForTest();
129+
GlobalLoggerProvider.resetForTest();
129130
builder =
130131
AutoConfiguredOpenTelemetrySdk.builder()
131132
.setResultAsGlobal(false)

sdk-extensions/autoconfigure/src/testInitializeRegistersGlobal/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static org.assertj.core.api.Assertions.assertThat;
99

1010
import io.opentelemetry.api.GlobalOpenTelemetry;
11+
import io.opentelemetry.api.logs.GlobalLoggerProvider;
1112
import io.opentelemetry.sdk.OpenTelemetrySdk;
1213
import org.junit.jupiter.api.BeforeEach;
1314
import org.junit.jupiter.api.Test;
@@ -17,6 +18,7 @@ class AutoConfiguredOpenTelemetrySdkTest {
1718
@BeforeEach
1819
void setUp() {
1920
GlobalOpenTelemetry.resetForTest();
21+
GlobalLoggerProvider.resetForTest();
2022
}
2123

2224
@Test

sdk-extensions/autoconfigure/src/testOtlp/java/io/opentelemetry/sdk/autoconfigure/OtlpGrpcConfigTest.java

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.google.common.collect.Lists;
1717
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
1818
import io.opentelemetry.api.GlobalOpenTelemetry;
19+
import io.opentelemetry.api.logs.GlobalLoggerProvider;
1920
import io.opentelemetry.api.metrics.MeterProvider;
2021
import io.opentelemetry.sdk.OpenTelemetrySdk;
2122
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
@@ -58,13 +59,15 @@ class OtlpGrpcConfigTest {
5859
@BeforeEach
5960
void setUp() {
6061
GlobalOpenTelemetry.resetForTest();
62+
GlobalLoggerProvider.resetForTest();
6163
}
6264

6365
@AfterEach
6466
public void tearDown() {
6567
server.reset();
6668
shutdownGlobalSdk();
6769
GlobalOpenTelemetry.resetForTest();
70+
GlobalLoggerProvider.resetForTest();
6871
}
6972

7073
@Test

sdk-extensions/autoconfigure/src/testOtlp/java/io/opentelemetry/sdk/autoconfigure/OtlpHttpConfigTest.java

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import com.google.common.collect.Lists;
1818
import io.opentelemetry.api.GlobalOpenTelemetry;
19+
import io.opentelemetry.api.logs.GlobalLoggerProvider;
1920
import io.opentelemetry.api.metrics.MeterProvider;
2021
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
2122
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
@@ -44,12 +45,14 @@ class OtlpHttpConfigTest {
4445
void setUp() {
4546
server.reset();
4647
GlobalOpenTelemetry.resetForTest();
48+
GlobalLoggerProvider.resetForTest();
4749
}
4850

4951
@AfterEach
5052
public void tearDown() {
5153
shutdownGlobalSdk();
5254
GlobalOpenTelemetry.resetForTest();
55+
GlobalLoggerProvider.resetForTest();
5356
}
5457

5558
@Test

0 commit comments

Comments
 (0)