@@ -7,9 +7,13 @@ import io.sentry.Breadcrumb
77import io.sentry.EventProcessor
88import io.sentry.FilterString
99import io.sentry.Hint
10+ import io.sentry.IContinuousProfiler
11+ import io.sentry.IProfileConverter
1012import io.sentry.IScopes
1113import io.sentry.ITransportFactory
1214import io.sentry.Integration
15+ import io.sentry.NoOpContinuousProfiler
16+ import io.sentry.NoOpProfileConverter
1317import io.sentry.NoOpTransportFactory
1418import io.sentry.SamplingContext
1519import io.sentry.Sentry
@@ -18,6 +22,8 @@ import io.sentry.SentryIntegrationPackageStorage
1822import io.sentry.SentryLevel
1923import io.sentry.SentryLogEvent
2024import io.sentry.SentryOptions
25+ import io.sentry.asyncprofiler.profiling.JavaContinuousProfiler
26+ import io.sentry.asyncprofiler.provider.AsyncProfilerProfileConverterProvider
2127import io.sentry.checkEvent
2228import io.sentry.opentelemetry.SentryAutoConfigurationCustomizerProvider
2329import io.sentry.opentelemetry.agent.AgentMarker
@@ -45,6 +51,7 @@ import kotlin.test.assertFalse
4551import kotlin.test.assertTrue
4652import org.aspectj.lang.ProceedingJoinPoint
4753import org.assertj.core.api.Assertions.assertThat
54+ import org.mockito.internal.util.MockUtil.isMock
4855import org.mockito.kotlin.any
4956import org.mockito.kotlin.anyOrNull
5057import org.mockito.kotlin.mock
@@ -87,6 +94,7 @@ class SentryAutoConfigurationTest {
8794 AutoConfigurations .of(
8895 SentryAutoConfiguration ::class .java,
8996 WebMvcAutoConfiguration ::class .java,
97+ SentryProfilerAutoConfiguration ::class .java,
9098 )
9199 )
92100
@@ -1037,6 +1045,110 @@ class SentryAutoConfigurationTest {
10371045 }
10381046 }
10391047
1048+ @Test
1049+ fun `when AgentMarker is on the classpath and ContinuousProfiling is enabled IContinuousProfiler and IProfileConverter beans are created and set on options` () {
1050+ SentryIntegrationPackageStorage .getInstance().clearStorage()
1051+ contextRunner
1052+ .withPropertyValues(
1053+ " sentry.dsn=http://key@localhost/proj" ,
1054+ " sentry.profile-session-sample-rate=1.0" ,
1055+ )
1056+ .run {
1057+ assertThat(it).hasSingleBean(IContinuousProfiler ::class .java)
1058+ assertThat(it).hasSingleBean(IProfileConverter ::class .java)
1059+ assertThat(it)
1060+ .getBean(IProfileConverter ::class .java)
1061+ .isInstanceOf(
1062+ AsyncProfilerProfileConverterProvider .AsyncProfilerProfileConverter ::class .java
1063+ )
1064+ assertThat(it)
1065+ .getBean(IContinuousProfiler ::class .java)
1066+ .isInstanceOf(JavaContinuousProfiler ::class .java)
1067+ assertThat(it)
1068+ .getBean(IProfileConverter ::class .java)
1069+ .isSameAs(Sentry .getGlobalScope().options.profilerConverter)
1070+ assertThat(it)
1071+ .getBean(IContinuousProfiler ::class .java)
1072+ .isSameAs(Sentry .getGlobalScope().options.continuousProfiler)
1073+ }
1074+ }
1075+
1076+ @Test
1077+ fun `when AgentMarker is on the classpath and ContinuousProfiling is enabled IContinuousProfiler and IProfileConverter exist beans are taken from options` () {
1078+ SentryIntegrationPackageStorage .getInstance().clearStorage()
1079+
1080+ contextRunner
1081+ .withPropertyValues(
1082+ " sentry.dsn=http://key@localhost/proj" ,
1083+ " sentry.profile-session-sample-rate=1.0" ,
1084+ " sentry.auto-init=false" ,
1085+ " debug=true" ,
1086+ )
1087+ .withUserConfiguration(CustomProfilerOptionsConfigurationConfiguration ::class .java)
1088+ .run {
1089+ val profiler = it.getBean(IContinuousProfiler ::class .java)
1090+ assertTrue(isMock(profiler))
1091+ assertThat(it).hasSingleBean(IContinuousProfiler ::class .java)
1092+ assertThat(it).hasSingleBean(IProfileConverter ::class .java)
1093+ assertThat(it)
1094+ .getBean(IProfileConverter ::class .java)
1095+ .isSameAs(Sentry .getGlobalScope().options.profilerConverter)
1096+ assertThat(it)
1097+ .getBean(IContinuousProfiler ::class .java)
1098+ .isSameAs(Sentry .getGlobalScope().options.continuousProfiler)
1099+ }
1100+ }
1101+
1102+ @Test
1103+ fun `when AgentMarker is on the classpath and ContinuousProfiling is disabled NoOp Beans are created` () {
1104+ SentryIntegrationPackageStorage .getInstance().clearStorage()
1105+
1106+ contextRunner
1107+ .withPropertyValues(" sentry.dsn=http://key@localhost/proj" , " sentry.auto-init=false" )
1108+ .run {
1109+ assertThat(it).hasSingleBean(IContinuousProfiler ::class .java)
1110+ assertThat(it).hasSingleBean(IProfileConverter ::class .java)
1111+ assertThat(it)
1112+ .getBean(IProfileConverter ::class .java)
1113+ .isInstanceOf(NoOpProfileConverter ::class .java)
1114+ assertThat(it)
1115+ .getBean(IContinuousProfiler ::class .java)
1116+ .isInstanceOf(NoOpContinuousProfiler ::class .java)
1117+ }
1118+ }
1119+
1120+ @Test
1121+ fun `when AgentMarker is not on the classpath and ContinuousProfiling is enabled IContinuousProfiler and IProfileConverter beans are not created` () {
1122+ SentryIntegrationPackageStorage .getInstance().clearStorage()
1123+ contextRunner
1124+ .withPropertyValues(
1125+ " sentry.dsn=http://key@localhost/proj" ,
1126+ " sentry.profile-session-sample-rate=1.0" ,
1127+ " debug=true" ,
1128+ )
1129+ .withClassLoader(FilteredClassLoader (AgentMarker ::class .java, OpenTelemetry ::class .java))
1130+ .run {
1131+ assertThat(it).doesNotHaveBean(IContinuousProfiler ::class .java)
1132+ assertThat(it).doesNotHaveBean(IProfileConverter ::class .java)
1133+ }
1134+ }
1135+
1136+ @Test
1137+ fun `when JavaContinuousProfiler is not on the classpath and ContinuousProfiling is enabled IProfileConverter beans are not created` () {
1138+ SentryIntegrationPackageStorage .getInstance().clearStorage()
1139+ contextRunner
1140+ .withPropertyValues(
1141+ " sentry.dsn=http://key@localhost/proj" ,
1142+ " sentry.profile-session-sample-rate=1.0" ,
1143+ " debug=true" ,
1144+ )
1145+ .withClassLoader(FilteredClassLoader (JavaContinuousProfiler ::class .java))
1146+ .run {
1147+ assertThat(it).doesNotHaveBean(IContinuousProfiler ::class .java)
1148+ assertThat(it).doesNotHaveBean(IProfileConverter ::class .java)
1149+ }
1150+ }
1151+
10401152 @Configuration(proxyBeanMethods = false )
10411153 open class CustomSchedulerFactoryBeanCustomizerConfiguration {
10421154 class MyJobListener : JobListener {
@@ -1082,6 +1194,17 @@ class SentryAutoConfigurationTest {
10821194 @Bean open fun sentryOptionsConfiguration () = Sentry .OptionsConfiguration <SentryOptions > {}
10831195 }
10841196
1197+ @Configuration(proxyBeanMethods = false )
1198+ open class CustomProfilerOptionsConfigurationConfiguration {
1199+ private val profiler = mock<IContinuousProfiler >()
1200+
1201+ @Bean
1202+ open fun customOptionsConfiguration () =
1203+ Sentry .OptionsConfiguration <SentryOptions > { it.setContinuousProfiler(profiler) }
1204+
1205+ @Bean open fun beforeSendCallback () = CustomBeforeSendCallback ()
1206+ }
1207+
10851208 @Configuration(proxyBeanMethods = false )
10861209 open class MockTransportConfiguration {
10871210
0 commit comments