Skip to content

Commit

Permalink
Merge branch 'fix/event-drop-session-update-inconsistencies' into fix…
Browse files Browse the repository at this point in the history
…/event-drop-session-update-inconsistencies-extra
  • Loading branch information
adinauer committed May 3, 2022
2 parents af302a1 + a85eca4 commit bba94ea
Show file tree
Hide file tree
Showing 22 changed files with 225 additions and 89 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/enforce-license-compliance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Enforce License Compliance

on:
push:
branches: [master, main, release/*]
pull_request:
branches: [master, main]

jobs:
enforce-license-compliance:
runs-on: ubuntu-latest
steps:
- name: 'Enforce License Compliance'
uses: getsentry/action-enforce-license-compliance@main
with:
fossa_api_key: ${{ secrets.FOSSA_API_KEY }}
19 changes: 17 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,24 @@

## Unreleased

### Fix

* Change order of event filtering mechanisms (#2001)
* Only send session update for dropped events if state changed (#2002)

## 6.0.0-beta.2

* Fix: Android profiling initializes on first profile start (#2009)

## 6.0.0-beta.1

* Fix: Profiling rate decreased from 300hz to 100hz (#1997)
* Fix: Allow disabling sending of client reports via Android Manifest and external options (#2007)
* Fix: Change order of event filtering mechanisms (#2001)
* Fix: Only send session update for dropped events if state changed (#2002)
* Ref: Upgrade Spring Boot dependency to 2.5.13 (#2011)

### Sentry Self-hosted Compatibility

- Starting with version `6.6.0` of `sentry`, [Sentry's version >= v21.9.0](https://github.com/getsentry/self-hosted/releases) is required or you have to manually disable sending client reports via the `sendClientReports` option. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed.

## 6.0.0-alpha.6

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Sentry SDK for Java and Android

# Blog posts

* [Sentry’s Android Gradle Plugin Updated with Room Support and More](https://blog.sentry.io/2022/04/20/sentrys-android-gradle-plugin-updated-with-room-support-and-more/)
* [Troubleshooting Spring Boot applications with Sentry](https://blog.sentry.io/2022/04/18/troubleshooting-spring-boot-applications-with-sentry)
* [Android Manifest Placeholders](https://blog.sentry.io/2022/03/30/android-manifest-placeholders/)
* [UI Breadcrumbs for Android Error Events](https://blog.sentry.io/2022/02/08/ui-breadcrumbs-for-android-error-events)
* [Bytecode transformations: The Android Gradle Plugin](https://blog.sentry.io/2021/12/14/bytecode-transformations-the-android-gradle-plugin)
Expand Down
4 changes: 1 addition & 3 deletions buildSrc/src/main/java/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ object Config {
val kotlinVersion = "1.5.31"
val kotlinStdLib = "stdlib-jdk8"

val springBootVersion = "2.4.4"
// Spring is currently not compatible with Kotlin 1.4
val springKotlinCompatibleLanguageVersion = "1.3"
val springBootVersion = "2.5.13"
val kotlinCompatibleLanguageVersion = "1.4"

object BuildPlugins {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ org.gradle.parallel=true
android.useAndroidX=true

# Release information
versionName=6.0.0-alpha.6
versionName=6.0.0-beta.2

# disable renderscript, it's enabled by default
android.defaults.buildfeatures.renderscript=false
Expand Down
2 changes: 0 additions & 2 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun enableAllAutoBreadcrumbs (Z)V
public fun getAnrTimeoutIntervalMillis ()J
public fun getDebugImagesLoader ()Lio/sentry/android/core/IDebugImagesLoader;
public fun getProfilingTracesDirPath ()Ljava/lang/String;
public fun getProfilingTracesIntervalMillis ()I
public fun isAnrEnabled ()Z
public fun isAnrReportInDebug ()Z
Expand All @@ -149,7 +148,6 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun setEnableAutoActivityLifecycleTracing (Z)V
public fun setEnableSystemEventBreadcrumbs (Z)V
public fun setEnableUserInteractionBreadcrumbs (Z)V
public fun setProfilingTracesDirPath (Ljava/lang/String;)V
public fun setProfilingTracesIntervalMillis (I)V
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import io.sentry.SentryLevel;
import io.sentry.android.fragment.FragmentLifecycleIntegration;
import io.sentry.android.timber.SentryTimberIntegration;
import io.sentry.util.FileUtils;
import io.sentry.util.Objects;
import java.io.BufferedInputStream;
import java.io.File;
Expand Down Expand Up @@ -297,31 +296,12 @@ private static void readDefaultOptionValues(
* @param context the Application context
* @param options the SentryAndroidOptions
*/
@SuppressWarnings("FutureReturnValueIgnored")
private static void initializeCacheDirs(
final @NotNull Context context, final @NotNull SentryAndroidOptions options) {
final File cacheDir = new File(context.getCacheDir(), "sentry");
final File profilingTracesDir = new File(cacheDir, "profiling_traces");
options.setCacheDirPath(cacheDir.getAbsolutePath());
options.setProfilingTracesDirPath(profilingTracesDir.getAbsolutePath());

if (options.isProfilingEnabled()) {
profilingTracesDir.mkdirs();
final File[] oldTracesDirContent = profilingTracesDir.listFiles();

options
.getExecutorService()
.submit(
() -> {
if (oldTracesDirContent == null) return;
// Method trace files are normally deleted at the end of traces, but if that fails
// for some
// reason we try to clear any old files here.
for (File f : oldTracesDirContent) {
FileUtils.deleteRecursively(f);
}
});
}
}

private static boolean isNdkAvailable(final @NotNull BuildInfoProvider buildInfoProvider) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ final class AndroidTransactionProfiler implements ITransactionProfiler {
private final @NotNull BuildInfoProvider buildInfoProvider;
private final @Nullable PackageInfo packageInfo;
private long transactionStartNanos = 0;
private boolean isInitialized = false;

public AndroidTransactionProfiler(
final @NotNull Context context,
Expand All @@ -59,6 +60,14 @@ public AndroidTransactionProfiler(
this.buildInfoProvider =
Objects.requireNonNull(buildInfoProvider, "The BuildInfoProvider is required.");
this.packageInfo = ContextUtils.getPackageInfo(context, options.getLogger());
}

private void init() {
// We initialize it only once
if (isInitialized) {
return;
}
isInitialized = true;
final String tracesFilesDirPath = options.getProfilingTracesDirPath();
if (!options.isProfilingEnabled()) {
options.getLogger().log(SentryLevel.INFO, "Profiling is disabled in options.");
Expand Down Expand Up @@ -93,7 +102,10 @@ public synchronized void onTransactionStart(@NotNull ITransaction transaction) {
// Debug.startMethodTracingSampling() is only available since Lollipop
if (buildInfoProvider.getSdkInfoVersion() < Build.VERSION_CODES.LOLLIPOP) return;

// traceFilesDir is null or intervalUs is 0 only if there was a problem in the constructor, but
// Let's initialize trace folder and profiling interval
init();

// traceFilesDir is null or intervalUs is 0 only if there was a problem in the init, but
// we already logged that
if (traceFilesDir == null || intervalUs == 0 || !traceFilesDir.exists()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import io.sentry.SpanStatus;
import io.sentry.protocol.SdkVersion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/** Sentry SDK options for Android */
public final class SentryAndroidOptions extends SentryOptions {
Expand Down Expand Up @@ -85,11 +84,8 @@ public final class SentryAndroidOptions extends SentryOptions {
*/
private boolean enableActivityLifecycleTracingAutoFinish = true;

/** The cache dir. path for caching profiling traces */
private @Nullable String profilingTracesDirPath;

/** Interval for profiling traces in milliseconds. Defaults to 300 times per second */
private int profilingTracesIntervalMillis = 1_000 / 300;
/** Interval for profiling traces in milliseconds. Defaults to 100 times per second */
private int profilingTracesIntervalMillis = 1_000 / 100;

/** Interface that loads the debug images list */
private @NotNull IDebugImagesLoader debugImagesLoader = NoOpDebugImagesLoader.getInstance();
Expand Down Expand Up @@ -226,24 +222,6 @@ public void enableAllAutoBreadcrumbs(boolean enable) {
enableUserInteractionBreadcrumbs = enable;
}

/**
* Returns the profiling traces dir. path if set
*
* @return the profiling traces dir. path or null if not set
*/
public @Nullable String getProfilingTracesDirPath() {
return profilingTracesDirPath;
}

/**
* Sets the profiling traces dir. path
*
* @param profilingTracesDirPath the profiling traces dir. path
*/
public void setProfilingTracesDirPath(@Nullable String profilingTracesDirPath) {
this.profilingTracesDirPath = profilingTracesDirPath;
}

/**
* Returns the interval for profiling traces in milliseconds.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,6 @@ class AndroidOptionsInitializerTest {
assertFalse(File(fixture.sentryOptions.profilingTracesDirPath!!).exists())
}

@Test
fun `profilingTracesDirPath should be created and cleared when profiling is enabled`() {
fixture.initSut(configureOptions = {
isProfilingEnabled = true
})

assertTrue(File(fixture.sentryOptions.profilingTracesDirPath!!).exists())
assertTrue(File(fixture.sentryOptions.profilingTracesDirPath!!).list()!!.isEmpty())
}

@Test
fun `outboxDir should be set at initialization`() {
fixture.initSut()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import android.os.Build
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.times
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import io.sentry.ILogger
import io.sentry.SentryLevel
import io.sentry.SentryTracer
import io.sentry.TransactionContext
import io.sentry.test.getCtor
Expand All @@ -25,14 +30,18 @@ class AndroidTransactionProfilerTest {
private val className = "io.sentry.android.core.AndroidTransactionProfiler"
private val ctorTypes = arrayOf(Context::class.java, SentryAndroidOptions::class.java, BuildInfoProvider::class.java)
private val fixture = Fixture()
private lateinit var file: File

private class Fixture {
private val mockDsn = "http://key@localhost/proj"
val buildInfo = mock<BuildInfoProvider> {
whenever(it.sdkInfoVersion).thenReturn(Build.VERSION_CODES.LOLLIPOP)
}
val mockLogger = mock<ILogger>()
val options = SentryAndroidOptions().apply {
dsn = mockDsn
isProfilingEnabled = true
isDebug = true
setLogger(mockLogger)
}
val transaction1 = SentryTracer(TransactionContext("", ""), mock())
val transaction2 = SentryTracer(TransactionContext("", ""), mock())
Expand All @@ -44,13 +53,15 @@ class AndroidTransactionProfilerTest {
@BeforeTest
fun `set up`() {
context = ApplicationProvider.getApplicationContext()
file = context.cacheDir
AndroidOptionsInitializer.init(fixture.options, createMockContext())
AndroidOptionsInitializer.init(fixture.options, context, fixture.mockLogger, false, false)
// Profiler doesn't start if the folder doesn't exists.
// Usually it's generated when calling Sentry.init, but for tests we can create it manually.
File(fixture.options.profilingTracesDirPath).mkdirs()
}

@AfterTest
fun clear() {
file.deleteRecursively()
context.cacheDir.deleteRecursively()
}

@Test
Expand Down Expand Up @@ -98,6 +109,68 @@ class AndroidTransactionProfilerTest {
assertNull(traceData)
}

@Test
fun `profiler evaluates isProfiling options only on first transaction profiling`() {
fixture.options.apply {
isProfilingEnabled = false
}

// We create the profiler, and nothing goes wrong
val profiler = fixture.getSut(context)
verify(fixture.mockLogger, never()).log(SentryLevel.INFO, "Profiling is disabled in options.")

// Regardless of how many times the profiler is started, the option is evaluated and logged only once
profiler.onTransactionStart(fixture.transaction1)
profiler.onTransactionStart(fixture.transaction1)
verify(fixture.mockLogger, times(1)).log(SentryLevel.INFO, "Profiling is disabled in options.")
}

@Test
fun `profiler evaluates profilingTracesDirPath options only on first transaction profiling`() {
fixture.options.apply {
profilingTracesDirPath = ""
}

// We create the profiler, and nothing goes wrong
val profiler = fixture.getSut(context)
verify(fixture.mockLogger, never()).log(
SentryLevel.WARNING,
"Disabling profiling because no profiling traces dir path is defined in options."
)

// Regardless of how many times the profiler is started, the option is evaluated and logged only once
profiler.onTransactionStart(fixture.transaction1)
profiler.onTransactionStart(fixture.transaction1)
verify(fixture.mockLogger, times(1)).log(
SentryLevel.WARNING,
"Disabling profiling because no profiling traces dir path is defined in options."
)
}

@Test
fun `profiler evaluates profilingTracesIntervalMillis options only on first transaction profiling`() {
fixture.options.apply {
profilingTracesIntervalMillis = 0
}

// We create the profiler, and nothing goes wrong
val profiler = fixture.getSut(context)
verify(fixture.mockLogger, never()).log(
SentryLevel.WARNING,
"Disabling profiling because trace interval is set to %d milliseconds",
0L
)

// Regardless of how many times the profiler is started, the option is evaluated and logged only once
profiler.onTransactionStart(fixture.transaction1)
profiler.onTransactionStart(fixture.transaction1)
verify(fixture.mockLogger, times(1)).log(
SentryLevel.WARNING,
"Disabling profiling because trace interval is set to %d milliseconds",
0L
)
}

@Test
fun `profiler on tracesDirPath null`() {
fixture.options.apply {
Expand Down Expand Up @@ -173,10 +246,4 @@ class AndroidTransactionProfilerTest {
traceData = profiler.onTransactionFinish(fixture.transaction1)
assertEquals(fixture.transaction1.eventId.toString(), traceData!!.transactionId)
}

private fun createMockContext(): Context {
val mockContext = ContextUtilsTest.createMockContext()
whenever(mockContext.cacheDir).thenReturn(file)
return mockContext
}
}
2 changes: 1 addition & 1 deletion sentry-apache-http-client-5/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ configure<JavaPluginExtension> {

tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
kotlinOptions.languageVersion = Config.springKotlinCompatibleLanguageVersion
kotlinOptions.languageVersion = Config.kotlinCompatibleLanguageVersion
}

dependencies {
Expand Down
Loading

0 comments on commit bba94ea

Please sign in to comment.