Skip to content

Commit b8bd8c4

Browse files
romtsnclaude
andauthored
fix(logging): Use ImmediateExecutorService in logging tests and fix Log4j2 scopes usage (#5158)
* fix(logging): Use ImmediateExecutorService in logging tests and fix Log4j2 scopes usage Allow injecting ISentryExecutorService into LoggerBatchProcessor for deterministic test execution. Fix Log4j2 SentryAppender to use scopes instance instead of static Sentry calls for logging. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(log4j2): Move super.start() into start(OptionsConfiguration) overload Ensures the appender is marked as started regardless of which entry point is used, preventing loggerContext.start() from re-triggering the no-arg start() and reinitializing Sentry without the test executor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a415905 commit b8bd8c4

File tree

6 files changed

+68
-23
lines changed

6 files changed

+68
-23
lines changed

sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import io.sentry.SentryLogLevel
77
import io.sentry.SentryOptions
88
import io.sentry.checkEvent
99
import io.sentry.checkLogs
10+
import io.sentry.logger.ILoggerBatchProcessorFactory
11+
import io.sentry.logger.LoggerBatchProcessor
12+
import io.sentry.test.ImmediateExecutorService
1013
import io.sentry.test.applyTestOptions
1114
import io.sentry.test.initForTest
1215
import io.sentry.transport.ITransport
@@ -45,6 +48,9 @@ class SentryHandlerTest {
4548
val options = SentryOptions()
4649
options.dsn = "http://key@localhost/proj"
4750
options.setTransportFactory { _, _ -> transport }
51+
options.logs.loggerBatchProcessorFactory = ILoggerBatchProcessorFactory { options, client ->
52+
LoggerBatchProcessor(options, client, ImmediateExecutorService())
53+
}
4854
applyTestOptions(options)
4955
contextTags?.forEach { options.addContextTag(it) }
5056
logger = Logger.getLogger("jul.SentryHandlerTest")

sentry-log4j2/src/main/java/io/sentry/log4j2/SentryAppender.java

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -164,25 +164,37 @@ public SentryAppender(
164164

165165
@Override
166166
public void start() {
167+
start(getOptionsConfiguration(null));
168+
}
169+
170+
@NotNull
171+
Sentry.OptionsConfiguration<SentryOptions> getOptionsConfiguration(
172+
final @Nullable Sentry.OptionsConfiguration<SentryOptions> additionalOptionsConfiguration) {
173+
return options -> {
174+
options.setEnableExternalConfiguration(true);
175+
options.setInitPriority(InitPriority.LOWEST);
176+
options.setDsn(dsn);
177+
if (debug != null) {
178+
options.setDebug(debug);
179+
}
180+
options.setSentryClientName(
181+
BuildConfig.SENTRY_LOG4J2_SDK_NAME + "/" + BuildConfig.VERSION_NAME);
182+
options.setSdkVersion(createSdkVersion(options));
183+
if (contextTags != null) {
184+
for (final String contextTag : contextTags) {
185+
options.addContextTag(contextTag);
186+
}
187+
}
188+
Optional.ofNullable(transportFactory).ifPresent(options::setTransportFactory);
189+
if (additionalOptionsConfiguration != null) {
190+
additionalOptionsConfiguration.configure(options);
191+
}
192+
};
193+
}
194+
195+
void start(final @NotNull Sentry.OptionsConfiguration<SentryOptions> optionsConfiguration) {
167196
try {
168-
Sentry.init(
169-
options -> {
170-
options.setEnableExternalConfiguration(true);
171-
options.setInitPriority(InitPriority.LOWEST);
172-
options.setDsn(dsn);
173-
if (debug != null) {
174-
options.setDebug(debug);
175-
}
176-
options.setSentryClientName(
177-
BuildConfig.SENTRY_LOG4J2_SDK_NAME + "/" + BuildConfig.VERSION_NAME);
178-
options.setSdkVersion(createSdkVersion(options));
179-
if (contextTags != null) {
180-
for (final String contextTag : contextTags) {
181-
options.addContextTag(contextTag);
182-
}
183-
}
184-
Optional.ofNullable(transportFactory).ifPresent(options::setTransportFactory);
185-
});
197+
Sentry.init(optionsConfiguration);
186198
} catch (IllegalArgumentException e) {
187199
final @Nullable String errorMessage = e.getMessage();
188200
if (errorMessage == null || !errorMessage.startsWith("DSN is required.")) {
@@ -235,14 +247,13 @@ protected void captureLog(@NotNull LogEvent loggingEvent) {
235247
}
236248

237249
final @NotNull Map<String, String> contextData = loggingEvent.getContextData().toMap();
238-
final @NotNull List<String> contextTags =
239-
ScopesAdapter.getInstance().getOptions().getContextTags();
250+
final @NotNull List<String> contextTags = scopes.getOptions().getContextTags();
240251
LoggerPropertiesUtil.applyPropertiesToAttributes(attributes, contextTags, contextData);
241252

242253
final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes);
243254
params.setOrigin("auto.log.log4j2");
244255

245-
Sentry.logger().log(sentryLevel, params, formattedMessage, arguments);
256+
scopes.logger().log(sentryLevel, params, formattedMessage, arguments);
246257
}
247258

248259
/**

sentry-log4j2/src/test/kotlin/io/sentry/log4j2/SentryAppenderTest.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import io.sentry.SentryLevel
88
import io.sentry.SentryLogLevel
99
import io.sentry.checkEvent
1010
import io.sentry.checkLogs
11+
import io.sentry.logger.ILoggerBatchProcessorFactory
12+
import io.sentry.logger.LoggerBatchProcessor
13+
import io.sentry.test.ImmediateExecutorService
1114
import io.sentry.test.initForTest
1215
import io.sentry.transport.ITransport
1316
import java.time.Instant
@@ -93,7 +96,14 @@ class SentryAppenderTest {
9396

9497
loggerContext.updateLoggers(config)
9598

96-
appender.start()
99+
appender.start(
100+
appender.getOptionsConfiguration { options ->
101+
options.logs.loggerBatchProcessorFactory =
102+
ILoggerBatchProcessorFactory { options, client ->
103+
LoggerBatchProcessor(options, client, ImmediateExecutorService())
104+
}
105+
}
106+
)
97107
loggerContext.start()
98108

99109
return LogManager.getContext().getLogger(SentryAppenderTest::class.java.name)

sentry-logback/src/test/kotlin/io/sentry/logback/SentryAppenderTest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import io.sentry.SentryLogLevel
1818
import io.sentry.SentryOptions
1919
import io.sentry.checkEvent
2020
import io.sentry.checkLogs
21+
import io.sentry.logger.ILoggerBatchProcessorFactory
22+
import io.sentry.logger.LoggerBatchProcessor
23+
import io.sentry.test.ImmediateExecutorService
2124
import io.sentry.test.applyTestOptions
2225
import io.sentry.test.initForTest
2326
import io.sentry.transport.ITransport
@@ -69,6 +72,9 @@ class SentryAppenderTest {
6972
options.dsn = dsn
7073
options.isSendDefaultPii = sendDefaultPii
7174
options.logs.isEnabled = enableLogs
75+
options.logs.loggerBatchProcessorFactory = ILoggerBatchProcessorFactory { options, client ->
76+
LoggerBatchProcessor(options, client, ImmediateExecutorService())
77+
}
7278
applyTestOptions(options)
7379
contextTags?.forEach { options.addContextTag(it) }
7480
appender.setOptions(options)

sentry/api/sentry.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5259,6 +5259,7 @@ public class io/sentry/logger/LoggerBatchProcessor : io/sentry/logger/ILoggerBat
52595259
public static final field MAX_QUEUE_SIZE I
52605260
protected final field options Lio/sentry/SentryOptions;
52615261
public fun <init> (Lio/sentry/SentryOptions;Lio/sentry/ISentryClient;)V
5262+
public fun <init> (Lio/sentry/SentryOptions;Lio/sentry/ISentryClient;Lio/sentry/ISentryExecutorService;)V
52625263
public fun add (Lio/sentry/SentryLogEvent;)V
52635264
public fun close (Z)V
52645265
public fun flush (J)V

sentry/src/main/java/io/sentry/logger/LoggerBatchProcessor.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import java.util.concurrent.Future;
2222
import java.util.concurrent.RejectedExecutionException;
2323
import java.util.concurrent.TimeUnit;
24+
import org.jetbrains.annotations.ApiStatus;
2425
import org.jetbrains.annotations.NotNull;
2526
import org.jetbrains.annotations.Nullable;
27+
import org.jetbrains.annotations.TestOnly;
2628

2729
@Open
2830
public class LoggerBatchProcessor implements ILoggerBatchProcessor {
@@ -44,10 +46,19 @@ public class LoggerBatchProcessor implements ILoggerBatchProcessor {
4446

4547
public LoggerBatchProcessor(
4648
final @NotNull SentryOptions options, final @NotNull ISentryClient client) {
49+
this(options, client, new SentryExecutorService(options));
50+
}
51+
52+
@ApiStatus.Internal
53+
@TestOnly
54+
public LoggerBatchProcessor(
55+
final @NotNull SentryOptions options,
56+
final @NotNull ISentryClient client,
57+
final @NotNull ISentryExecutorService executorService) {
4758
this.options = options;
4859
this.client = client;
4960
this.queue = new ConcurrentLinkedQueue<>();
50-
this.executorService = new SentryExecutorService(options);
61+
this.executorService = executorService;
5162
}
5263

5364
@Override

0 commit comments

Comments
 (0)