Skip to content

Commit

Permalink
use a new Context for Spring, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lcian committed Feb 17, 2025
1 parent 48452c9 commit 0a95314
Show file tree
Hide file tree
Showing 19 changed files with 306 additions and 46 deletions.
1 change: 0 additions & 1 deletion sentry-spring-jakarta/api/sentry-spring-jakarta.api
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public final class io/sentry/spring/jakarta/SpringProfilesEventProcessor : io/se
public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
public fun process (Lio/sentry/SentryReplayEvent;Lio/sentry/Hint;)Lio/sentry/SentryReplayEvent;
public fun process (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction;
public fun processInternal (Lio/sentry/SentryBaseEvent;)V
}

public final class io/sentry/spring/jakarta/SpringSecuritySentryUserProvider : io/sentry/spring/jakarta/SentryUserProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import io.sentry.SentryBaseEvent;
import io.sentry.SentryEvent;
import io.sentry.SentryReplayEvent;
import io.sentry.SpanContext;
import io.sentry.protocol.SentryTransaction;
import io.sentry.protocol.Spring;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.core.env.Environment;
Expand All @@ -16,8 +16,6 @@
* to the {@link io.sentry.TraceContext} associated with the event.
*/
public final class SpringProfilesEventProcessor implements EventProcessor {
private static final @NotNull String ACTIVE_PROFILES_TRACE_CONTEXT_KEY = "spring.active_profiles";

private final @NotNull Environment environment;

@Override
Expand All @@ -40,15 +38,11 @@ public final class SpringProfilesEventProcessor implements EventProcessor {
return event;
}

public void processInternal(final @NotNull SentryBaseEvent event) {
@Nullable SpanContext trace = event.getContexts().getTrace();
if (trace != null) {
@Nullable String[] activeProfiles = environment.getActiveProfiles();
if (activeProfiles == null) {
activeProfiles = new String[0];
}
trace.setData(ACTIVE_PROFILES_TRACE_CONTEXT_KEY, activeProfiles);
}
private void processInternal(final @NotNull SentryBaseEvent event) {
@Nullable String[] activeProfiles = environment.getActiveProfiles();
@NotNull Spring springContext = new Spring();
springContext.setActiveProfiles(activeProfiles);
event.getContexts().setSpring(springContext);
}

public SpringProfilesEventProcessor(final @NotNull Environment environment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.sentry.spring.jakarta
import io.sentry.ITransportFactory
import io.sentry.Sentry
import io.sentry.checkEvent
import io.sentry.protocol.Spring
import io.sentry.transport.ITransport
import org.assertj.core.api.Assertions.assertThat
import org.mockito.kotlin.any
Expand All @@ -24,25 +25,24 @@ class SpringProfilesEventProcessorTest {
.withUserConfiguration(MockTransportConfiguration::class.java)

@Test
fun `when default Spring profile is active, sets traceContext spring active_profiles to empty list on sent event`() {
fun `when default Spring profile is active, sets active_profiles in Spring context to empty list on sent event`() {
contextRunner
.run {
Sentry.captureMessage("test")
val transport = it.getBean(ITransport::class.java)
verify(transport).send(
checkEvent { event ->
val traceContext = event.contexts.trace
assertThat(traceContext).isNotNull()
val traceData = traceContext!!.data
assertThat(traceData.get("spring.active_profiles")).isEqualTo(listOf<String>())
val expected = Spring()
expected.activeProfiles = listOf<String>().toTypedArray()
assertThat(event.contexts.spring).isEqualTo(expected)
},
anyOrNull()
)
}
}

@Test
fun `when non-default Spring profiles are active, sets traceContext spring active_profiles to array of profile names`() {
fun `when non-default Spring profiles are active, sets active profiles in Spring context to list of profile names`() {
contextRunner
.withPropertyValues(
"spring.profiles.active=test1,test2"
Expand All @@ -52,10 +52,9 @@ class SpringProfilesEventProcessorTest {
val transport = it.getBean(ITransport::class.java)
verify(transport).send(
checkEvent { event ->
val traceContext = event.contexts.trace
assertThat(traceContext).isNotNull()
val traceData = traceContext!!.data
assertThat(traceData.get("spring.active_profiles")).isEqualTo(listOf("test1", "test2"))
val expected = Spring()
expected.activeProfiles = listOf("test1", "test2").toTypedArray()
assertThat(event.contexts.spring).isEqualTo(expected)
},
anyOrNull()
)
Expand Down
1 change: 0 additions & 1 deletion sentry-spring/api/sentry-spring.api
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public final class io/sentry/spring/SpringProfilesEventProcessor : io/sentry/Eve
public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
public fun process (Lio/sentry/SentryReplayEvent;Lio/sentry/Hint;)Lio/sentry/SentryReplayEvent;
public fun process (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction;
public fun processInternal (Lio/sentry/SentryBaseEvent;)V
}

public final class io/sentry/spring/SpringSecuritySentryUserProvider : io/sentry/spring/SentryUserProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import io.sentry.SentryBaseEvent;
import io.sentry.SentryEvent;
import io.sentry.SentryReplayEvent;
import io.sentry.SpanContext;
import io.sentry.protocol.SentryTransaction;
import io.sentry.protocol.Spring;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.core.env.Environment;
Expand All @@ -16,8 +16,6 @@
* to the {@link io.sentry.TraceContext} associated with the event.
*/
public final class SpringProfilesEventProcessor implements EventProcessor {
private static final @NotNull String ACTIVE_PROFILES_TRACE_CONTEXT_KEY = "spring.active_profiles";

private final @NotNull Environment environment;

@Override
Expand All @@ -40,15 +38,11 @@ public final class SpringProfilesEventProcessor implements EventProcessor {
return event;
}

public void processInternal(final @NotNull SentryBaseEvent event) {
@Nullable SpanContext trace = event.getContexts().getTrace();
if (trace != null) {
@Nullable String[] activeProfiles = environment.getActiveProfiles();
if (activeProfiles == null) {
activeProfiles = new String[0];
}
trace.setData(ACTIVE_PROFILES_TRACE_CONTEXT_KEY, activeProfiles);
}
private void processInternal(final @NotNull SentryBaseEvent event) {
@Nullable String[] activeProfiles = environment.getActiveProfiles();
@NotNull Spring springContext = new Spring();
springContext.setActiveProfiles(activeProfiles);
event.getContexts().setSpring(springContext);
}

public SpringProfilesEventProcessor(final @NotNull Environment environment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.sentry.spring
import io.sentry.ITransportFactory
import io.sentry.Sentry
import io.sentry.checkEvent
import io.sentry.protocol.Spring
import io.sentry.transport.ITransport
import org.assertj.core.api.Assertions.assertThat
import org.mockito.kotlin.any
Expand All @@ -24,25 +25,24 @@ class SpringProfilesEventProcessorTest {
.withUserConfiguration(MockTransportConfiguration::class.java)

@Test
fun `when default Spring profile is active, sets traceContext spring active_profiles to empty list on sent event`() {
fun `when default Spring profile is active, sets active_profiles in Spring context to empty list on sent event`() {
contextRunner
.run {
Sentry.captureMessage("test")
val transport = it.getBean(ITransport::class.java)
verify(transport).send(
checkEvent { event ->
val traceContext = event.contexts.trace
assertThat(traceContext).isNotNull()
val traceData = traceContext!!.data
assertThat(traceData.get("spring.active_profiles")).isEqualTo(listOf<String>())
val expected = Spring()
expected.activeProfiles = listOf<String>().toTypedArray()
assertThat(event.contexts.spring).isEqualTo(expected)
},
anyOrNull()
)
}
}

@Test
fun `when non-default Spring profiles are active, sets traceContext spring active_profiles to array of profile names`() {
fun `when non-default Spring profiles are active, sets active profiles in Spring context to list of profile names`() {
contextRunner
.withPropertyValues(
"spring.profiles.active=test1,test2"
Expand All @@ -52,10 +52,9 @@ class SpringProfilesEventProcessorTest {
val transport = it.getBean(ITransport::class.java)
verify(transport).send(
checkEvent { event ->
val traceContext = event.contexts.trace
assertThat(traceContext).isNotNull()
val traceData = traceContext!!.data
assertThat(traceData.get("spring.active_profiles")).isEqualTo(listOf("test1", "test2"))
val expected = Spring()
expected.activeProfiles = listOf("test1", "test2").toTypedArray()
assertThat(event.contexts.spring).isEqualTo(expected)
},
anyOrNull()
)
Expand Down
28 changes: 28 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ public final class io/sentry/CombinedContextsView : io/sentry/protocol/Contexts
public fun getResponse ()Lio/sentry/protocol/Response;
public fun getRuntime ()Lio/sentry/protocol/SentryRuntime;
public fun getSize ()I
public fun getSpring ()Lio/sentry/protocol/Spring;
public fun getTrace ()Lio/sentry/SpanContext;
public fun isEmpty ()Z
public fun keys ()Ljava/util/Enumeration;
Expand All @@ -238,6 +239,7 @@ public final class io/sentry/CombinedContextsView : io/sentry/protocol/Contexts
public fun setOperatingSystem (Lio/sentry/protocol/OperatingSystem;)V
public fun setResponse (Lio/sentry/protocol/Response;)V
public fun setRuntime (Lio/sentry/protocol/SentryRuntime;)V
public fun setSpring (Lio/sentry/protocol/Spring;)V
public fun setTrace (Lio/sentry/SpanContext;)V
public fun size ()I
public fun withResponse (Lio/sentry/util/HintUtils$SentryConsumer;)V
Expand Down Expand Up @@ -4422,6 +4424,7 @@ public class io/sentry/protocol/Contexts : io/sentry/JsonSerializable {
public fun getResponse ()Lio/sentry/protocol/Response;
public fun getRuntime ()Lio/sentry/protocol/SentryRuntime;
public fun getSize ()I
public fun getSpring ()Lio/sentry/protocol/Spring;
public fun getTrace ()Lio/sentry/SpanContext;
public fun hashCode ()I
public fun isEmpty ()Z
Expand All @@ -4439,6 +4442,7 @@ public class io/sentry/protocol/Contexts : io/sentry/JsonSerializable {
public fun setOperatingSystem (Lio/sentry/protocol/OperatingSystem;)V
public fun setResponse (Lio/sentry/protocol/Response;)V
public fun setRuntime (Lio/sentry/protocol/SentryRuntime;)V
public fun setSpring (Lio/sentry/protocol/Spring;)V
public fun setTrace (Lio/sentry/SpanContext;)V
public fun size ()I
public fun withResponse (Lio/sentry/util/HintUtils$SentryConsumer;)V
Expand Down Expand Up @@ -5352,6 +5356,30 @@ public final class io/sentry/protocol/SentryTransaction$JsonKeys {
public fun <init> ()V
}

public final class io/sentry/protocol/Spring : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public static final field TYPE Ljava/lang/String;
public fun <init> ()V
public fun <init> (Lio/sentry/protocol/Spring;)V
public fun equals (Ljava/lang/Object;)Z
public fun getActiveProfiles ()[Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun hashCode ()I
public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;)V
public fun setActiveProfiles ([Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/protocol/Spring$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/ObjectReader;Lio/sentry/ILogger;)Lio/sentry/protocol/Spring;
public synthetic fun deserialize (Lio/sentry/ObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/protocol/Spring$JsonKeys {
public static final field ACTIVE_PROFILES Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/protocol/TransactionInfo : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Ljava/lang/String;)V
public fun getUnknown ()Ljava/util/Map;
Expand Down
19 changes: 19 additions & 0 deletions sentry/src/main/java/io/sentry/CombinedContextsView.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.sentry.protocol.OperatingSystem;
import io.sentry.protocol.Response;
import io.sentry.protocol.SentryRuntime;
import io.sentry.protocol.Spring;
import io.sentry.util.HintUtils;
import java.io.IOException;
import java.util.Enumeration;
Expand Down Expand Up @@ -206,6 +207,24 @@ public void setResponse(@NotNull Response response) {
getDefaultContexts().setResponse(response);
}

@Override
public @Nullable Spring getSpring() {
final @Nullable Spring current = currentContexts.getSpring();
if (current != null) {
return current;
}
final @Nullable Spring isolation = isolationContexts.getSpring();
if (isolation != null) {
return isolation;
}
return globalContexts.getSpring();
}

@Override
public void setSpring(@NotNull Spring spring) {
getDefaultContexts().setSpring(spring);
}

@Override
public int size() {
return mergeContexts().size();
Expand Down
13 changes: 13 additions & 0 deletions sentry/src/main/java/io/sentry/protocol/Contexts.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public Contexts(final @NotNull Contexts contexts) {
this.setTrace(new SpanContext((SpanContext) value));
} else if (Response.TYPE.equals(entry.getKey()) && value instanceof Response) {
this.setResponse(new Response((Response) value));
} else if (Spring.TYPE.equals(entry.getKey()) && value instanceof Spring) {
this.setSpring(new Spring((Spring) value));
} else {
this.put(entry.getKey(), value);
}
Expand Down Expand Up @@ -148,6 +150,14 @@ public void setResponse(final @NotNull Response response) {
}
}

public @Nullable Spring getSpring() {
return toContextType(Spring.TYPE, Spring.class);
}

public void setSpring(final @NotNull Spring spring) {
this.put(Spring.TYPE, spring);
}

public int size() {
// since this used to extend map
return internalStorage.size();
Expand Down Expand Up @@ -266,6 +276,9 @@ public static final class Deserializer implements JsonDeserializer<Contexts> {
case Response.TYPE:
contexts.setResponse(new Response.Deserializer().deserialize(reader, logger));
break;
case Spring.TYPE:
contexts.setSpring(new Spring.Deserializer().deserialize(reader, logger));
break;
default:
Object object = reader.nextObjectOrNull();
if (object != null) {
Expand Down
Loading

0 comments on commit 0a95314

Please sign in to comment.