Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion sentry-log4j2/api/sentry-log4j2.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ public final class io/sentry/log4j2/BuildConfig {
public class io/sentry/log4j2/SentryAppender : org/apache/logging/log4j/core/appender/AbstractAppender {
public static final field MECHANISM_TYPE Ljava/lang/String;
public fun <init> (Ljava/lang/String;Lorg/apache/logging/log4j/core/Filter;Ljava/lang/String;Lorg/apache/logging/log4j/Level;Lorg/apache/logging/log4j/Level;Ljava/lang/Boolean;Lio/sentry/ITransportFactory;Lio/sentry/IScopes;[Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Lorg/apache/logging/log4j/core/Filter;Ljava/lang/String;Lorg/apache/logging/log4j/Level;Lorg/apache/logging/log4j/Level;Lorg/apache/logging/log4j/Level;Ljava/lang/Boolean;Lio/sentry/ITransportFactory;Lio/sentry/IScopes;[Ljava/lang/String;)V
public fun append (Lorg/apache/logging/log4j/core/LogEvent;)V
public static fun createAppender (Ljava/lang/String;Lorg/apache/logging/log4j/Level;Lorg/apache/logging/log4j/Level;Ljava/lang/String;Ljava/lang/Boolean;Lorg/apache/logging/log4j/core/Filter;Ljava/lang/String;)Lio/sentry/log4j2/SentryAppender;
protected fun captureLog (Lorg/apache/logging/log4j/core/LogEvent;)V
public static fun createAppender (Ljava/lang/String;Lorg/apache/logging/log4j/Level;Lorg/apache/logging/log4j/Level;Lorg/apache/logging/log4j/Level;Ljava/lang/String;Ljava/lang/Boolean;Lorg/apache/logging/log4j/core/Filter;Ljava/lang/String;)Lio/sentry/log4j2/SentryAppender;
protected fun createBreadcrumb (Lorg/apache/logging/log4j/core/LogEvent;)Lio/sentry/Breadcrumb;
protected fun createEvent (Lorg/apache/logging/log4j/core/LogEvent;)Lio/sentry/SentryEvent;
public fun start ()V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@
import io.sentry.InitPriority;
import io.sentry.ScopesAdapter;
import io.sentry.Sentry;
import io.sentry.SentryAttribute;
import io.sentry.SentryAttributes;
import io.sentry.SentryEvent;
import io.sentry.SentryIntegrationPackageStorage;
import io.sentry.SentryLevel;
import io.sentry.SentryLogLevel;
import io.sentry.SentryOptions;
import io.sentry.exception.ExceptionMechanismException;
import io.sentry.logger.SentryLogParameters;
import io.sentry.protocol.Mechanism;
import io.sentry.protocol.Message;
import io.sentry.protocol.SdkVersion;
Expand Down Expand Up @@ -50,6 +54,7 @@ public class SentryAppender extends AbstractAppender {
private final @Nullable ITransportFactory transportFactory;
private @NotNull Level minimumBreadcrumbLevel = Level.INFO;
private @NotNull Level minimumEventLevel = Level.ERROR;
private @NotNull Level minimumLevel = Level.INFO;
private final @Nullable Boolean debug;
private final @NotNull IScopes scopes;
private final @Nullable List<String> contextTags;
Expand All @@ -59,12 +64,41 @@ public class SentryAppender extends AbstractAppender {
.addPackage("maven:io.sentry:sentry-log4j2", BuildConfig.VERSION_NAME);
}

/**
* @deprecated please use the non deprecated constructor instead.
*/
@Deprecated
Comment thread
adinauer marked this conversation as resolved.
@SuppressWarnings("InlineMeSuggester")
public SentryAppender(
final @NotNull String name,
final @Nullable Filter filter,
final @Nullable String dsn,
final @Nullable Level minimumBreadcrumbLevel,
final @Nullable Level minimumEventLevel,
Comment thread
adinauer marked this conversation as resolved.
final @Nullable Boolean debug,
final @Nullable ITransportFactory transportFactory,
final @NotNull IScopes scopes,
final @Nullable String[] contextTags) {
this(
name,
filter,
dsn,
minimumBreadcrumbLevel,
minimumEventLevel,
null,
debug,
transportFactory,
scopes,
contextTags);
}

public SentryAppender(
final @NotNull String name,
final @Nullable Filter filter,
final @Nullable String dsn,
final @Nullable Level minimumBreadcrumbLevel,
final @Nullable Level minimumEventLevel,
final @Nullable Level minimumLevel,
final @Nullable Boolean debug,
final @Nullable ITransportFactory transportFactory,
final @NotNull IScopes scopes,
Expand All @@ -77,6 +111,9 @@ public SentryAppender(
if (minimumEventLevel != null) {
this.minimumEventLevel = minimumEventLevel;
}
if (minimumLevel != null) {
this.minimumLevel = minimumLevel;
}
this.debug = debug;
this.transportFactory = transportFactory;
this.scopes = scopes;
Expand All @@ -89,6 +126,7 @@ public SentryAppender(
* @param name The name of the Appender.
* @param minimumBreadcrumbLevel The min. level of the breadcrumb.
* @param minimumEventLevel The min. level of the event.
* @param minimumLevel The min. level of the log event.
* @param dsn the Sentry DSN.
* @param debug if Sentry debug mode should be on
* @param filter The filter, if any, to use.
Expand All @@ -99,6 +137,7 @@ public SentryAppender(
@Nullable @PluginAttribute("name") final String name,
@Nullable @PluginAttribute("minimumBreadcrumbLevel") final Level minimumBreadcrumbLevel,
@Nullable @PluginAttribute("minimumEventLevel") final Level minimumEventLevel,
@Nullable @PluginAttribute("minimumLevel") final Level minimumLevel,
@Nullable @PluginAttribute("dsn") final String dsn,
@Nullable @PluginAttribute("debug") final Boolean debug,
@Nullable @PluginElement("filter") final Filter filter,
Expand All @@ -114,6 +153,7 @@ public SentryAppender(
dsn,
minimumBreadcrumbLevel,
minimumEventLevel,
minimumLevel,
debug,
null,
ScopesAdapter.getInstance(),
Expand Down Expand Up @@ -150,6 +190,9 @@ public void start() {

@Override
public void append(final @NotNull LogEvent eventObject) {
if (eventObject.getLevel().isMoreSpecificThan(minimumLevel)) {
captureLog(eventObject);
}
if (eventObject.getLevel().isMoreSpecificThan(minimumEventLevel)) {
final Hint hint = new Hint();
hint.set(SENTRY_SYNTHETIC_EXCEPTION, eventObject);
Expand All @@ -164,6 +207,29 @@ public void append(final @NotNull LogEvent eventObject) {
}
}

/**
* Captures a Sentry log from Log4j2's {@link LogEvent}.
*
* @param loggingEvent the log4j2 event
*/
// for the Android compatibility we must use old Java Date class
@SuppressWarnings("JdkObsolete")
protected void captureLog(@NotNull LogEvent loggingEvent) {
final @NotNull SentryLogLevel sentryLevel = toSentryLogLevel(loggingEvent.getLevel());

final @Nullable Object[] arguments = loggingEvent.getMessage().getParameters();
final @NotNull SentryAttributes attributes = SentryAttributes.of();

attributes.add(
SentryAttribute.stringAttribute(
"sentry.message.template", loggingEvent.getMessage().getFormat()));

final @NotNull String formattedMessage = loggingEvent.getMessage().getFormattedMessage();
final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes);

Sentry.logger().log(sentryLevel, params, formattedMessage, arguments);
}

/**
* Creates {@link SentryEvent} from Log4j2 {@link LogEvent}.
*
Expand Down Expand Up @@ -271,6 +337,28 @@ public void append(final @NotNull LogEvent eventObject) {
}
}

/**
* Transforms a {@link Level} into an {@link SentryLogLevel}.
*
* @param level original level as defined in log4j.
* @return log level used within sentry.
*/
private static @NotNull SentryLogLevel toSentryLogLevel(final @NotNull Level level) {
if (level.isMoreSpecificThan(Level.FATAL)) {
return SentryLogLevel.FATAL;
} else if (level.isMoreSpecificThan(Level.ERROR)) {
return SentryLogLevel.ERROR;
} else if (level.isMoreSpecificThan(Level.WARN)) {
return SentryLogLevel.WARN;
} else if (level.isMoreSpecificThan(Level.INFO)) {
return SentryLogLevel.INFO;
} else if (level.isMoreSpecificThan(Level.DEBUG)) {
return SentryLogLevel.DEBUG;
} else {
return SentryLogLevel.TRACE;
}
}

private @NotNull SdkVersion createSdkVersion(final @NotNull SentryOptions sentryOptions) {
SdkVersion sdkVersion = sentryOptions.getSdkVersion();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import io.sentry.InitPriority
import io.sentry.ScopesAdapter
import io.sentry.Sentry
import io.sentry.SentryLevel
import io.sentry.SentryLogLevel
import io.sentry.checkEvent
import io.sentry.checkLogs
import io.sentry.test.initForTest
import io.sentry.transport.ITransport
import java.time.Instant
Expand Down Expand Up @@ -49,6 +51,7 @@ class SentryAppenderTest {
transportFactory: ITransportFactory? = null,
minimumBreadcrumbLevel: Level? = null,
minimumEventLevel: Level? = null,
minimumLevel: Level? = null,
debug: Boolean? = null,
contextTags: List<String>? = null,
): ExtendedLogger {
Expand All @@ -64,6 +67,7 @@ class SentryAppenderTest {
"http://key@localhost/proj",
minimumBreadcrumbLevel,
minimumEventLevel,
minimumLevel,
debug,
this.transportFactory,
ScopesAdapter.getInstance(),
Expand Down Expand Up @@ -239,6 +243,72 @@ class SentryAppenderTest {
.send(checkEvent { event -> assertEquals(SentryLevel.FATAL, event.level) }, anyOrNull())
}

@Test
fun `converts trace log level to Sentry log level`() {
val logger = fixture.getSut(minimumLevel = Level.TRACE)
logger.trace("testing trace level")

Sentry.flush(1000)

verify(fixture.transport)
.send(checkLogs { event -> assertEquals(SentryLogLevel.TRACE, event.items.first().level) })
}

@Test
fun `converts debug log level to Sentry log level`() {
val logger = fixture.getSut(minimumLevel = Level.DEBUG)
logger.debug("testing debug level")

Sentry.flush(1000)

verify(fixture.transport)
.send(checkLogs { event -> assertEquals(SentryLogLevel.DEBUG, event.items.first().level) })
}

@Test
fun `converts info log level to Sentry log level`() {
val logger = fixture.getSut(minimumLevel = Level.INFO)
logger.info("testing info level")

Sentry.flush(1000)

verify(fixture.transport)
.send(checkLogs { event -> assertEquals(SentryLogLevel.INFO, event.items.first().level) })
}

@Test
fun `converts warn log level to Sentry log level`() {
val logger = fixture.getSut(minimumLevel = Level.WARN)
logger.warn("testing warn level")

Sentry.flush(1000)

verify(fixture.transport)
.send(checkLogs { event -> assertEquals(SentryLogLevel.WARN, event.items.first().level) })
}

@Test
fun `converts error log level to Sentry log level`() {
val logger = fixture.getSut(minimumLevel = Level.ERROR)
logger.error("testing error level")

Sentry.flush(1000)

verify(fixture.transport)
.send(checkLogs { event -> assertEquals(SentryLogLevel.ERROR, event.items.first().level) })
}

@Test
fun `converts fatal log level to Sentry log level`() {
val logger = fixture.getSut(minimumLevel = Level.FATAL)
logger.fatal("testing fatal level")

Sentry.flush(1000)

verify(fixture.transport)
.send(checkLogs { event -> assertEquals(SentryLogLevel.FATAL, event.items.first().level) })
}

@Test
fun `attaches thread information`() {
val logger = fixture.getSut(minimumEventLevel = Level.WARN)
Expand Down
1 change: 1 addition & 0 deletions sentry-log4j2/src/test/resources/sentry.properties
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
release=release from sentry.properties
logs.enabled=true
1 change: 1 addition & 0 deletions sentry-samples/sentry-samples-log4j2/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ configure<JavaPluginExtension> {
dependencies {
implementation(projects.sentryLog4j2)
implementation(libs.log4j.api)
implementation(libs.log4j.core)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
dsn="https://502f25099c204a2fbf4cb16edc5975d1@o447951.ingest.sentry.io/5428563"
minimumBreadcrumbLevel="DEBUG"
minimumEventLevel="WARN"
minimumLevel="DEBUG"
debug="true"
contextTags="userId,requestId"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
in-app-includes="io.sentry.samples"
logs.enabled=true
Loading