Skip to content

Commit

Permalink
feat(sentry-logback): add encoder for message formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
norwood committed Oct 11, 2022
1 parent 4ca1d7b commit 44d2d92
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
1 change: 1 addition & 0 deletions sentry-logback/api/sentry-logback.api
Expand Up @@ -11,6 +11,7 @@ public class io/sentry/logback/SentryAppender : ch/qos/logback/core/Unsynchroniz
protected fun createEvent (Lch/qos/logback/classic/spi/ILoggingEvent;)Lio/sentry/SentryEvent;
public fun getMinimumBreadcrumbLevel ()Lch/qos/logback/classic/Level;
public fun getMinimumEventLevel ()Lch/qos/logback/classic/Level;
public fun setEncoder (Lch/qos/logback/core/encoder/Encoder;)V
public fun setMinimumBreadcrumbLevel (Lch/qos/logback/classic/Level;)V
public fun setMinimumEventLevel (Lch/qos/logback/classic/Level;)V
public fun setOptions (Lio/sentry/SentryOptions;)V
Expand Down
24 changes: 22 additions & 2 deletions sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java
Expand Up @@ -6,6 +6,7 @@
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import com.jakewharton.nopen.annotation.Open;
import io.sentry.Breadcrumb;
Expand All @@ -20,6 +21,7 @@
import io.sentry.protocol.Message;
import io.sentry.protocol.SdkVersion;
import io.sentry.util.CollectionUtils;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand All @@ -39,6 +41,7 @@ public class SentryAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
private @Nullable ITransportFactory transportFactory;
private @NotNull Level minimumBreadcrumbLevel = Level.INFO;
private @NotNull Level minimumEventLevel = Level.ERROR;
private @Nullable Encoder<ILoggingEvent> encoder;

@Override
public void start() {
Expand Down Expand Up @@ -91,7 +94,7 @@ protected void append(@NotNull ILoggingEvent eventObject) {
final SentryEvent event = new SentryEvent(DateUtils.getDateTime(loggingEvent.getTimeStamp()));
final Message message = new Message();
message.setMessage(loggingEvent.getMessage());
message.setFormatted(loggingEvent.getFormattedMessage());
message.setFormatted(formatted(loggingEvent));
message.setParams(toParams(loggingEvent.getArgumentArray()));
event.setMessage(message);
event.setLogger(loggingEvent.getLoggerName());
Expand Down Expand Up @@ -137,6 +140,19 @@ protected void append(@NotNull ILoggingEvent eventObject) {
return event;
}

private String formatted(@NotNull ILoggingEvent loggingEvent) {
if (encoder != null) {
try {
return new String(encoder.encode(loggingEvent), StandardCharsets.UTF_8);
} catch (final Throwable t) {
// catch exceptions from possibly incorrectly configured encoder
// and fallback to default formatted message
addWarn("Failed to encode logging event", t);
}
}
return loggingEvent.getFormattedMessage();
}

private @NotNull List<String> toParams(@Nullable Object[] arguments) {
if (arguments != null) {
return Arrays.stream(arguments)
Expand All @@ -158,7 +174,7 @@ protected void append(@NotNull ILoggingEvent eventObject) {
final Breadcrumb breadcrumb = new Breadcrumb();
breadcrumb.setLevel(formatLevel(loggingEvent.getLevel()));
breadcrumb.setCategory(loggingEvent.getLoggerName());
breadcrumb.setMessage(loggingEvent.getFormattedMessage());
breadcrumb.setMessage(formatted(loggingEvent));
return breadcrumb;
}

Expand Down Expand Up @@ -222,4 +238,8 @@ public void setMinimumEventLevel(final @Nullable Level minimumEventLevel) {
void setTransportFactory(final @Nullable ITransportFactory transportFactory) {
this.transportFactory = transportFactory;
}

public void setEncoder(Encoder<ILoggingEvent> encoder) {
this.encoder = encoder;
}
}
Expand Up @@ -2,6 +2,10 @@ package io.sentry.logback

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.encoder.Encoder
import ch.qos.logback.core.encoder.EncoderBase
import ch.qos.logback.core.status.Status
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.anyOrNull
Expand Down Expand Up @@ -31,7 +35,7 @@ import kotlin.test.assertNull
import kotlin.test.assertTrue

class SentryAppenderTest {
private class Fixture(dsn: String? = "http://key@localhost/proj", minimumBreadcrumbLevel: Level? = null, minimumEventLevel: Level? = null, contextTags: List<String>? = null) {
private class Fixture(dsn: String? = "http://key@localhost/proj", minimumBreadcrumbLevel: Level? = null, minimumEventLevel: Level? = null, contextTags: List<String>? = null, encoder: Encoder<ILoggingEvent>? = null) {
val logger: Logger = LoggerFactory.getLogger(SentryAppenderTest::class.java)
val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
val transportFactory = mock<ITransportFactory>()
Expand All @@ -49,10 +53,13 @@ class SentryAppenderTest {
appender.setMinimumEventLevel(minimumEventLevel)
appender.context = loggerContext
appender.setTransportFactory(transportFactory)
encoder?.context = loggerContext
appender.setEncoder(encoder)
val rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME)
rootLogger.level = Level.TRACE
rootLogger.addAppender(appender)
appender.start()
encoder?.start()
loggerContext.start()
}
}
Expand Down Expand Up @@ -88,6 +95,7 @@ class SentryAppenderTest {
)
}


@Test
fun `converts message`() {
fixture = Fixture(minimumEventLevel = Level.DEBUG)
Expand All @@ -106,6 +114,59 @@ class SentryAppenderTest {
)
}

@Test
fun `encodes message`() {
var encoder = PatternLayoutEncoder()
encoder.pattern = "encoderadded %msg"
fixture = Fixture(minimumEventLevel = Level.DEBUG, encoder = encoder)
fixture.logger.info("testing encoding");

verify(fixture.transport).send(
checkEvent { event ->
assertNotNull(event.message) { message ->
assertEquals("encoderadded testing encoding", message.formatted)
assertEquals("testing encoding", message.message)
}
assertEquals("io.sentry.logback.SentryAppenderTest", event.logger)
},
anyOrNull()
)
}

class ThrowingEncoder: EncoderBase<ILoggingEvent> {
constructor(): super()
override fun headerBytes(): ByteArray {
TODO("Not yet implemented")
}

override fun footerBytes(): ByteArray {
TODO("Not yet implemented")
}

override fun encode(event: ILoggingEvent?): ByteArray {
TODO("Not yet implemented")
}
}

@Test
fun `fallsback when encoder throws`() {
var encoder = ThrowingEncoder()
fixture = Fixture(minimumEventLevel = Level.DEBUG, encoder = encoder)
fixture.logger.info("testing when encoder throws");

verify(fixture.transport).send(
checkEvent { event ->
assertNotNull(event.message) { message ->
assertEquals("testing when encoder throws", message.formatted)
assertEquals("testing when encoder throws", message.message)
}
assertEquals("io.sentry.logback.SentryAppenderTest", event.logger)
},
anyOrNull()
)
}


@Test
fun `event date is in UTC`() {
fixture = Fixture(minimumEventLevel = Level.DEBUG)
Expand Down

0 comments on commit 44d2d92

Please sign in to comment.