Skip to content

Commit ae1f43a

Browse files
adinauerclaude
andcommitted
feat(logback): Add Logs opt-in
Require an explicit Logback appender opt-in before forwarding records as Sentry Logs. Keep event and breadcrumb capture independent while the aggregate core Logs flag remains in place. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent aeb796b commit ae1f43a

4 files changed

Lines changed: 70 additions & 3 deletions

File tree

sentry-logback/api/sentry-logback.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class io/sentry/logback/SentryAppender : ch/qos/logback/core/Unsynchroniz
1414
public fun getMinimumBreadcrumbLevel ()Lch/qos/logback/classic/Level;
1515
public fun getMinimumEventLevel ()Lch/qos/logback/classic/Level;
1616
public fun getMinimumLevel ()Lch/qos/logback/classic/Level;
17+
public fun isEnableLogs ()Z
18+
public fun setEnableLogs (Z)V
1719
public fun setEncoder (Lch/qos/logback/core/encoder/Encoder;)V
1820
public fun setMinimumBreadcrumbLevel (Lch/qos/logback/classic/Level;)V
1921
public fun setMinimumEventLevel (Lch/qos/logback/classic/Level;)V

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public class SentryAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
5252
private @NotNull Level minimumBreadcrumbLevel = Level.INFO;
5353
private @NotNull Level minimumEventLevel = Level.ERROR;
5454
private @NotNull Level minimumLevel = Level.INFO;
55+
private boolean enableLogs = false;
5556
private @Nullable Encoder<ILoggingEvent> encoder;
5657

5758
static {
@@ -87,7 +88,8 @@ public void start() {
8788

8889
@Override
8990
protected void append(@NotNull ILoggingEvent eventObject) {
90-
if (ScopesAdapter.getInstance().getOptions().getLogs().isEnabled()
91+
if (enableLogs
92+
&& ScopesAdapter.getInstance().getOptions().getLogs().isEnabled()
9193
&& eventObject.getLevel().isGreaterOrEqual(minimumLevel)) {
9294
captureLog(eventObject);
9395
}
@@ -323,6 +325,14 @@ public void setMinimumLevel(final @Nullable Level minimumLevel) {
323325
return minimumLevel;
324326
}
325327

328+
public void setEnableLogs(final boolean enableLogs) {
329+
this.enableLogs = enableLogs;
330+
}
331+
332+
public boolean isEnableLogs() {
333+
return enableLogs;
334+
}
335+
326336
@ApiStatus.Internal
327337
void setTransportFactory(final @Nullable ITransportFactory transportFactory) {
328338
this.transportFactory = transportFactory;

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

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import kotlin.test.assertTrue
3838
import org.mockito.kotlin.any
3939
import org.mockito.kotlin.anyOrNull
4040
import org.mockito.kotlin.mock
41+
import org.mockito.kotlin.never
4142
import org.mockito.kotlin.verify
4243
import org.mockito.kotlin.whenever
4344
import org.slf4j.Logger
@@ -55,6 +56,7 @@ class SentryAppenderTest {
5556
encoder: Encoder<ILoggingEvent>? = null,
5657
sendDefaultPii: Boolean = false,
5758
enableLogs: Boolean = false,
59+
enableGlobalLogs: Boolean = enableLogs,
5860
options: SentryOptions = SentryOptions(),
5961
startLater: Boolean = false,
6062
) {
@@ -71,7 +73,7 @@ class SentryAppenderTest {
7173
this.encoder = encoder
7274
options.dsn = dsn
7375
options.isSendDefaultPii = sendDefaultPii
74-
options.logs.isEnabled = enableLogs
76+
options.logs.isEnabled = enableGlobalLogs
7577
options.logs.loggerBatchProcessorFactory = ILoggerBatchProcessorFactory { options, client ->
7678
LoggerBatchProcessor(options, client, ImmediateExecutorService())
7779
}
@@ -81,6 +83,7 @@ class SentryAppenderTest {
8183
appender.setMinimumBreadcrumbLevel(minimumBreadcrumbLevel)
8284
appender.setMinimumEventLevel(minimumEventLevel)
8385
appender.setMinimumLevel(minimumLevel)
86+
appender.setEnableLogs(enableLogs)
8487
appender.context = loggerContext
8588
appender.setTransportFactory(transportFactory)
8689
encoder?.context = loggerContext
@@ -322,6 +325,57 @@ class SentryAppenderTest {
322325
)
323326
}
324327

328+
@Test
329+
fun `does not capture logs by default when aggregate logs are enabled`() {
330+
fixture = Fixture(enableGlobalLogs = true)
331+
332+
assertFalse(fixture.appender.isEnableLogs)
333+
fixture.logger.info("this should not be captured as a log")
334+
Sentry.flush(10)
335+
336+
verify(fixture.transport, never()).send(checkLogs {})
337+
}
338+
339+
@Test
340+
fun `captures logs when local and aggregate logs are enabled`() {
341+
fixture = Fixture(enableLogs = true)
342+
343+
assertTrue(fixture.appender.isEnableLogs)
344+
fixture.logger.info("this should be captured as a log")
345+
Sentry.flush(10)
346+
347+
verify(fixture.transport)
348+
.send(
349+
checkLogs { logs ->
350+
assertEquals("this should be captured as a log", logs.items.first().body)
351+
}
352+
)
353+
}
354+
355+
@Test
356+
fun `captures events and breadcrumbs when local logs are disabled`() {
357+
fixture =
358+
Fixture(
359+
minimumBreadcrumbLevel = Level.INFO,
360+
minimumEventLevel = Level.ERROR,
361+
enableGlobalLogs = true,
362+
)
363+
364+
fixture.logger.info("this should be a breadcrumb")
365+
fixture.logger.error("this should be an event")
366+
Sentry.flush(10)
367+
368+
verify(fixture.transport)
369+
.send(
370+
checkEvent { event ->
371+
assertEquals("this should be an event", event.message?.formatted)
372+
assertEquals("this should be a breadcrumb", event.breadcrumbs?.single()?.message)
373+
},
374+
anyOrNull(),
375+
)
376+
verify(fixture.transport, never()).send(checkLogs {})
377+
}
378+
325379
@Test
326380
fun `converts trace log level to Sentry log level`() {
327381
fixture = Fixture(minimumLevel = Level.TRACE, enableLogs = true)

sentry-samples/sentry-samples-logback/src/main/resources/logback.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
<enabled>true</enabled>
1818
</logs>
1919
</options>
20+
<enableLogs>true</enableLogs>
2021
<!-- Demonstrates how to modify the minimum values -->
2122
<!-- Default for Events is ERROR -->
2223
<minimumEventLevel>WARN</minimumEventLevel>
2324
<!-- Default for Breadcrumbs is INFO -->
2425
<minimumBreadcrumbLevel>DEBUG</minimumBreadcrumbLevel>
25-
<!-- Default for Breadcrumbs is INFO -->
26+
<!-- Default for Logs is INFO -->
2627
<minimumLevel>INFO</minimumLevel>
2728
</appender>
2829

0 commit comments

Comments
 (0)