diff --git a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java index c606bdf88b6..685402e27bd 100644 --- a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java +++ b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java @@ -28,6 +28,7 @@ import java.util.Date; import java.util.List; import java.util.Map; +import java.util.ResourceBundle; import java.util.logging.ErrorManager; import java.util.logging.Filter; import java.util.logging.Handler; @@ -150,10 +151,15 @@ protected void captureLog(@NotNull LogRecord loggingEvent) { final @Nullable Object[] arguments = loggingEvent.getParameters(); final @NotNull SentryAttributes attributes = SentryAttributes.of(); - @NotNull String message = loggingEvent.getMessage(); + final @Nullable String messageTemplate = loggingEvent.getMessage(); + if (messageTemplate == null) { + return; + } + + @NotNull String message = messageTemplate; if (loggingEvent.getResourceBundle() != null - && loggingEvent.getResourceBundle().containsKey(loggingEvent.getMessage())) { - message = loggingEvent.getResourceBundle().getString(loggingEvent.getMessage()); + && loggingEvent.getResourceBundle().containsKey(messageTemplate)) { + message = loggingEvent.getResourceBundle().getString(messageTemplate); } final @NotNull String formattedMessage = maybeFormatted(arguments, message); @@ -290,13 +296,16 @@ SentryEvent createEvent(final @NotNull LogRecord record) { final Message sentryMessage = new Message(); sentryMessage.setParams(toParams(record.getParameters())); - String message = record.getMessage(); - if (record.getResourceBundle() != null - && record.getResourceBundle().containsKey(record.getMessage())) { - message = record.getResourceBundle().getString(record.getMessage()); + final @Nullable String messageTemplate = record.getMessage(); + final @Nullable ResourceBundle resourceBundle = record.getResourceBundle(); + @Nullable String message = messageTemplate; + if (messageTemplate != null + && resourceBundle != null + && resourceBundle.containsKey(messageTemplate)) { + message = resourceBundle.getString(messageTemplate); } sentryMessage.setMessage(message); - if (record.getParameters() != null) { + if (message != null && record.getParameters() != null) { try { sentryMessage.setFormatted(formatMessage(message, record.getParameters())); } catch (RuntimeException e) { diff --git a/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt b/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt index 2cd10a81cd4..028c6759727 100644 --- a/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt +++ b/sentry-jul/src/test/kotlin/io/sentry/jul/SentryHandlerTest.kt @@ -16,7 +16,9 @@ import io.sentry.transport.ITransport import java.time.Instant import java.time.LocalDateTime import java.time.ZoneId +import java.util.ListResourceBundle import java.util.logging.Level +import java.util.logging.LogRecord import java.util.logging.Logger import kotlin.test.AfterTest import kotlin.test.BeforeTest @@ -485,6 +487,65 @@ class SentryHandlerTest { verify(fixture.transport, never()).send(checkLogs {}) } + @Test + fun `captures null message as event and breadcrumb when logs are enabled`() { + fixture = + Fixture( + minimumBreadcrumbLevel = Level.INFO, + minimumEventLevel = Level.SEVERE, + enableLogs = true, + ) + + fixture.logger.info(null as String?) + fixture.logger.severe(null as String?) + Sentry.flush(10) + + verify(fixture.transport) + .send( + checkEvent { event -> + assertNull(event.message?.message) + assertEquals(1, event.breadcrumbs?.size) + assertNull(event.breadcrumbs?.single()?.message) + }, + anyOrNull(), + ) + verify(fixture.transport, never()).send(checkLogs {}) + } + + @Test + fun `captures null message as event and breadcrumb when resource bundle is set`() { + fixture = + Fixture( + minimumBreadcrumbLevel = Level.INFO, + minimumEventLevel = Level.SEVERE, + enableLogs = true, + ) + val resourceBundle = + object : ListResourceBundle() { + override fun getContents(): Array> = + arrayOf(arrayOf("message", "localized message")) + } + + fixture.handler.publish( + LogRecord(Level.INFO, null).apply { this.resourceBundle = resourceBundle } + ) + fixture.handler.publish( + LogRecord(Level.SEVERE, null).apply { this.resourceBundle = resourceBundle } + ) + Sentry.flush(10) + + verify(fixture.transport) + .send( + checkEvent { event -> + assertNull(event.message?.message) + assertEquals(1, event.breadcrumbs?.size) + assertNull(event.breadcrumbs?.single()?.message) + }, + anyOrNull(), + ) + verify(fixture.transport, never()).send(checkLogs {}) + } + @Test fun `converts finest log level to Sentry log level`() { fixture = Fixture(minimumLevel = Level.FINEST)