Skip to content

Commit

Permalink
Feat: Attach Java vendor and version to events and transactions. (#1703)
Browse files Browse the repository at this point in the history
  • Loading branch information
maciejwalkowiak authored Sep 28, 2021
1 parent b52a0f0 commit b8854fe
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

* Feat: Attach Java vendor and version to events and transactions (#1703)

## 5.2.0

* Feat: Allow setting proguard via Options and/or external resources (#1728)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.sentry.protocol.SentryRuntime;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.boot.SpringBootVersion;
import org.springframework.stereotype.Component;

/**
Expand All @@ -13,23 +14,21 @@
*/
@Component
public class CustomEventProcessor implements EventProcessor {
private final String javaVersion;
private final String javaVendor;
private final String springBootVersion;

public CustomEventProcessor(String javaVersion, String javaVendor) {
this.javaVersion = javaVersion;
this.javaVendor = javaVendor;
public CustomEventProcessor(String springBootVersion) {
this.springBootVersion = springBootVersion;
}

public CustomEventProcessor() {
this(System.getProperty("java.version"), System.getProperty("java.vendor"));
this(SpringBootVersion.getVersion());
}

@Override
public @NotNull SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) {
final SentryRuntime runtime = new SentryRuntime();
runtime.setVersion(javaVersion);
runtime.setName(javaVendor);
runtime.setVersion(springBootVersion);
runtime.setName("Spring Boot");
event.getContexts().setRuntime(runtime);
return event;
}
Expand Down
6 changes: 6 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1987,6 +1987,12 @@ public final class io/sentry/util/Pair {
public fun getSecond ()Ljava/lang/Object;
}

public final class io/sentry/util/Platform {
public fun <init> ()V
public static fun isAndroid ()Z
public static fun isJvm ()Z
}

public final class io/sentry/util/StringUtils {
public static fun capitalize (Ljava/lang/String;)Ljava/lang/String;
public static fun getStringAfterDot (Ljava/lang/String;)Ljava/lang/String;
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.sentry.transport.ITransportGate;
import io.sentry.transport.NoOpEnvelopeCache;
import io.sentry.transport.NoOpTransportGate;
import io.sentry.util.Platform;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -1584,6 +1585,10 @@ private SentryOptions(final boolean empty) {
eventProcessors.add(new MainEventProcessor(this));
eventProcessors.add(new DuplicateEventDetectionEventProcessor(this));

if (Platform.isJvm()) {
eventProcessors.add(new SentryRuntimeEventProcessor());
}

setSentryClientName(BuildConfig.SENTRY_JAVA_SDK_NAME + "/" + BuildConfig.VERSION_NAME);
setSdkVersion(createSdkVersion());
}
Expand Down
46 changes: 46 additions & 0 deletions sentry/src/main/java/io/sentry/SentryRuntimeEventProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.sentry;

import io.sentry.protocol.SentryRuntime;
import io.sentry.protocol.SentryTransaction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/** Attaches Java vendor and version to events and transactions. */
final class SentryRuntimeEventProcessor implements EventProcessor {
private final @Nullable String javaVersion;
private final @Nullable String javaVendor;

public SentryRuntimeEventProcessor(
final @Nullable String javaVersion, final @Nullable String javaVendor) {
this.javaVersion = javaVersion;
this.javaVendor = javaVendor;
}

public SentryRuntimeEventProcessor() {
this(System.getProperty("java.version"), System.getProperty("java.vendor"));
}

@Override
public @NotNull SentryEvent process(
final @NotNull SentryEvent event, final @Nullable Object hint) {
return process(event);
}

@Override
public @NotNull SentryTransaction process(
final @NotNull SentryTransaction transaction, final @Nullable Object hint) {
return process(transaction);
}

private <T extends SentryBaseEvent> @NotNull T process(final @NotNull T event) {
if (event.getContexts().getRuntime() == null) {
event.getContexts().setRuntime(new SentryRuntime());
}
final SentryRuntime runtime = event.getContexts().getRuntime();
if (runtime != null && runtime.getName() == null && runtime.getVersion() == null) {
runtime.setName(javaVendor);
runtime.setVersion(javaVersion);
}
return event;
}
}
28 changes: 28 additions & 0 deletions sentry/src/main/java/io/sentry/util/Platform.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.sentry.util;

import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public final class Platform {
private static boolean isAndroid;

static {
// System#getProperty can throw an exception if there is a security manager is configured and
// does not allow accessing system properties
try {
// All system properties on Android:
// https://developer.android.com/reference/java/lang/System#getProperties()
isAndroid = "The Android Project".equals(System.getProperty("java.vendor"));
} catch (Exception e) {
isAndroid = false;
}
}

public static boolean isAndroid() {
return isAndroid;
}

public static boolean isJvm() {
return !isAndroid;
}
}
66 changes: 66 additions & 0 deletions sentry/src/test/java/io/sentry/SentryRuntimeEventProcessorTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.sentry

import io.sentry.protocol.SentryRuntime
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull

class SentryRuntimeEventProcessorTest {

private val eventProcessor = SentryRuntimeEventProcessor("16", "OpenJDK")

@Test
fun `when event does not have a runtime, sets runtime`() {
val event = eventProcessor.process(SentryEvent(), null)
assertNotNull(event) {
assertNotNull(it.contexts.runtime) { runtime ->
assertEquals("OpenJDK", runtime.name)
assertEquals("16", runtime.version)
}
}
}

@Test
fun `when event has runtime with null name and null version, sets runtime`() {
val event = SentryEvent()
event.contexts.setRuntime(SentryRuntime())
val result = eventProcessor.process(event, null)
assertNotNull(result) {
assertNotNull(it.contexts.runtime) { runtime ->
assertEquals("OpenJDK", runtime.name)
assertEquals("16", runtime.version)
}
}
}

@Test
fun `when event has runtime with null name and version set, does not change runtime`() {
val event = SentryEvent()
val runtime = SentryRuntime()
runtime.version = "1.1"
event.contexts.setRuntime(runtime)
val result = eventProcessor.process(event, null)
assertNotNull(result) {
assertNotNull(it.contexts.runtime) { runtime ->
assertNull(runtime.name)
assertEquals("1.1", runtime.version)
}
}
}

@Test
fun `when event has runtime with null version and name set, does not change runtime`() {
val event = SentryEvent()
val runtime = SentryRuntime()
runtime.name = "Java"
event.contexts.setRuntime(runtime)
val result = eventProcessor.process(event, null)
assertNotNull(result) {
assertNotNull(it.contexts.runtime) { runtime ->
assertNull(runtime.version)
assertEquals("Java", runtime.name)
}
}
}
}

0 comments on commit b8854fe

Please sign in to comment.