Skip to content

Commit 43b13a8

Browse files
authored
Merge e575f0d into 85d7417
2 parents 85d7417 + e575f0d commit 43b13a8

File tree

6 files changed

+186
-9
lines changed

6 files changed

+186
-9
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Fixes
6+
7+
- Only set log template for logging integrations if formatted message differs from template ([#4682](https://github.com/getsentry/sentry-java/pull/4682))
8+
59
### Features
610

711
- Add support for Spring Boot 4 and Spring 7 ([#4601](https://github.com/getsentry/sentry-java/pull/4601))

sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,19 @@ protected void captureLog(@NotNull LogRecord loggingEvent) {
154154
message = loggingEvent.getResourceBundle().getString(loggingEvent.getMessage());
155155
}
156156

157-
attributes.add(SentryAttribute.stringAttribute("sentry.message.template", message));
157+
String formattedMessage = null;
158+
boolean formattingFailed = false;
159+
try {
160+
formattedMessage = maybeFormatted(arguments, message);
161+
} catch (RuntimeException e) {
162+
formattedMessage = message;
163+
formattingFailed = true;
164+
}
165+
166+
if (formattingFailed || !formattedMessage.equals(message)) {
167+
attributes.add(SentryAttribute.stringAttribute("sentry.message.template", message));
168+
}
158169

159-
final @NotNull String formattedMessage = maybeFormatted(arguments, message);
160170
final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes);
161171
params.setOrigin("auto.log.jul");
162172

@@ -170,6 +180,7 @@ protected void captureLog(@NotNull LogRecord loggingEvent) {
170180
return formatMessage(message, arguments);
171181
} catch (RuntimeException e) {
172182
// local formatting failed, sending raw message instead of formatted message
183+
throw e;
173184
}
174185
}
175186

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

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class SentryHandlerTest {
3535
val configureWithLogManager: Boolean = false,
3636
val transport: ITransport = mock(),
3737
contextTags: List<String>? = null,
38+
printfStyle: Boolean? = null,
3839
) {
3940
var logger: Logger
4041
var handler: SentryHandler
@@ -49,6 +50,9 @@ class SentryHandlerTest {
4950
handler.setMinimumBreadcrumbLevel(minimumBreadcrumbLevel)
5051
handler.setMinimumEventLevel(minimumEventLevel)
5152
handler.setMinimumLevel(minimumLevel)
53+
if (printfStyle == true) {
54+
handler.setPrintfStyle(printfStyle)
55+
}
5256
handler.level = Level.ALL
5357
logger.handlers.forEach { logger.removeHandler(it) }
5458
logger.addHandler(handler)
@@ -476,4 +480,97 @@ class SentryHandlerTest {
476480
verify(fixture.transport)
477481
.send(checkLogs { event -> assertEquals(SentryLogLevel.ERROR, event.items.first().level) })
478482
}
483+
484+
@Test
485+
fun `does not set template on log when logging message without parameters`() {
486+
fixture = Fixture(minimumLevel = Level.SEVERE)
487+
fixture.logger.severe("testing message without parameters")
488+
489+
Sentry.flush(1000)
490+
491+
verify(fixture.transport)
492+
.send(
493+
checkLogs { logs ->
494+
val log = logs.items.first()
495+
assertEquals("testing message without parameters", log.body)
496+
assertNull(log.attributes?.get("sentry.message.template"))
497+
}
498+
)
499+
}
500+
501+
@Test
502+
fun `sets template on log when logging message with parameters`() {
503+
fixture = Fixture(minimumLevel = Level.SEVERE)
504+
fixture.logger.log(Level.SEVERE, "testing message {0}", arrayOf("param"))
505+
506+
Sentry.flush(1000)
507+
508+
verify(fixture.transport)
509+
.send(
510+
checkLogs { logs ->
511+
val log = logs.items.first()
512+
assertEquals("testing message param", log.body)
513+
assertEquals("testing message {0}", log.attributes?.get("sentry.message.template")?.value)
514+
assertEquals("param", log.attributes?.get("sentry.message.parameter.0")?.value)
515+
}
516+
)
517+
}
518+
519+
@Test
520+
fun `sets template on log when logging message with parameters and using printfStyle`() {
521+
fixture = Fixture(minimumLevel = Level.SEVERE, printfStyle = true)
522+
fixture.logger.log(Level.SEVERE, "testing message %s", arrayOf("param"))
523+
524+
Sentry.flush(1000)
525+
526+
verify(fixture.transport)
527+
.send(
528+
checkLogs { logs ->
529+
val log = logs.items.first()
530+
assertEquals("testing message param", log.body)
531+
assertEquals("testing message %s", log.attributes?.get("sentry.message.template")?.value)
532+
assertEquals("param", log.attributes?.get("sentry.message.parameter.0")?.value)
533+
}
534+
)
535+
}
536+
537+
@Test
538+
fun `sets template on log when logging message with parameters and formatting fails`() {
539+
fixture = Fixture(minimumLevel = Level.SEVERE, printfStyle = true)
540+
fixture.logger.log(Level.SEVERE, "testing message %d %d", arrayOf(1))
541+
542+
Sentry.flush(1000)
543+
544+
verify(fixture.transport)
545+
.send(
546+
checkLogs { logs ->
547+
val log = logs.items.first()
548+
assertEquals("testing message %d %d", log.body)
549+
assertEquals(
550+
"testing message %d %d",
551+
log.attributes?.get("sentry.message.template")?.value,
552+
)
553+
assertEquals(1, log.attributes?.get("sentry.message.parameter.0")?.value)
554+
assertNull(log.attributes?.get("sentry.message.parameter.1"))
555+
}
556+
)
557+
}
558+
559+
@Test
560+
fun `sets template on log when logging message with parameters and formatting fails due to 0 args`() {
561+
fixture = Fixture(minimumLevel = Level.SEVERE, printfStyle = true)
562+
fixture.logger.log(Level.SEVERE, "testing message %d", emptyArray())
563+
564+
Sentry.flush(1000)
565+
566+
verify(fixture.transport)
567+
.send(
568+
checkLogs { logs ->
569+
val log = logs.items.first()
570+
assertEquals("testing message %d", log.body)
571+
assertEquals("testing message %d", log.attributes?.get("sentry.message.template")?.value)
572+
assertNull(log.attributes?.get("sentry.message.parameter.0"))
573+
}
574+
)
575+
}
479576
}

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,14 @@ protected void captureLog(@NotNull LogEvent loggingEvent) {
222222
final @Nullable Object[] arguments = loggingEvent.getMessage().getParameters();
223223
final @NotNull SentryAttributes attributes = SentryAttributes.of();
224224

225-
attributes.add(
226-
SentryAttribute.stringAttribute(
227-
"sentry.message.template", loggingEvent.getMessage().getFormat()));
228-
225+
final @Nullable String nonFormattedMessage = loggingEvent.getMessage().getFormat();
229226
final @NotNull String formattedMessage = loggingEvent.getMessage().getFormattedMessage();
227+
228+
if (nonFormattedMessage != null && !formattedMessage.equals(nonFormattedMessage)) {
229+
attributes.add(
230+
SentryAttribute.stringAttribute("sentry.message.template", nonFormattedMessage));
231+
}
232+
230233
final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes);
231234
params.setOrigin("auto.log.log4j2");
232235

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

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class SentryAppenderTest {
6060
}
6161
loggerContext.start()
6262
val config: Configuration = loggerContext.configuration
63+
6364
val appender =
6465
SentryAppender(
6566
"sentry",
@@ -533,4 +534,62 @@ class SentryAppenderTest {
533534
fixture.getSut(debug = true)
534535
assertTrue(ScopesAdapter.getInstance().options.isDebug)
535536
}
537+
538+
@Test
539+
fun `does not set template on log when logging message without parameters`() {
540+
val logger = fixture.getSut(minimumLevel = Level.ERROR)
541+
logger.error("testing message without parameters")
542+
543+
Sentry.flush(1000)
544+
545+
verify(fixture.transport)
546+
.send(
547+
checkLogs { logs ->
548+
val log = logs.items.first()
549+
assertEquals("testing message without parameters", log.body)
550+
assertNull(log.attributes?.get("sentry.message.template"))
551+
}
552+
)
553+
}
554+
555+
@Test
556+
fun `sets template on log when logging message with parameters`() {
557+
val logger = fixture.getSut(minimumLevel = Level.ERROR)
558+
logger.error("testing message {}", "param")
559+
560+
Sentry.flush(1000)
561+
562+
verify(fixture.transport)
563+
.send(
564+
checkLogs { logs ->
565+
val log = logs.items.first()
566+
assertEquals("testing message param", log.body)
567+
assertEquals("testing message {}", log.attributes?.get("sentry.message.template")?.value)
568+
assertEquals("param", log.attributes?.get("sentry.message.parameter.0")?.value)
569+
}
570+
)
571+
}
572+
573+
@Test
574+
fun `sets template on log when logging message with parameters and number of parameters is wrong`() {
575+
val logger = fixture.getSut(minimumLevel = Level.ERROR)
576+
logger.error("testing message {} {} {}", "param1", "param2")
577+
578+
Sentry.flush(1000)
579+
580+
verify(fixture.transport)
581+
.send(
582+
checkLogs { logs ->
583+
val log = logs.items.first()
584+
assertEquals("testing message param1 param2 {}", log.body)
585+
assertEquals(
586+
"testing message {} {} {}",
587+
log.attributes?.get("sentry.message.template")?.value,
588+
)
589+
assertEquals("param1", log.attributes?.get("sentry.message.parameter.0")?.value)
590+
assertEquals("param2", log.attributes?.get("sentry.message.parameter.1")?.value)
591+
assertNull(log.attributes?.get("sentry.message.parameter.2"))
592+
}
593+
)
594+
}
536595
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,18 @@ protected void captureLog(@NotNull ILoggingEvent loggingEvent) {
183183

184184
@Nullable Object[] arguments = null;
185185
final @NotNull SentryAttributes attributes = SentryAttributes.of();
186+
final @NotNull String formattedMessage = formatted(loggingEvent);
186187

187188
// if encoder is set we treat message+params as PII as encoders may be used to mask/strip PII
188189
if (encoder == null || ScopesAdapter.getInstance().getOptions().isSendDefaultPii()) {
189-
attributes.add(
190-
SentryAttribute.stringAttribute("sentry.message.template", loggingEvent.getMessage()));
190+
final @Nullable String nonFormattedMessage = loggingEvent.getMessage();
191+
if (nonFormattedMessage != null && !formattedMessage.equals(nonFormattedMessage)) {
192+
attributes.add(
193+
SentryAttribute.stringAttribute("sentry.message.template", nonFormattedMessage));
194+
}
191195
arguments = loggingEvent.getArgumentArray();
192196
}
193197

194-
final @NotNull String formattedMessage = formatted(loggingEvent);
195198
final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes);
196199
params.setOrigin("auto.log.logback");
197200

0 commit comments

Comments
 (0)