Skip to content

Commit e6dcd44

Browse files
authored
Merge branch 'main' into dependabot/github_actions/codecov/codecov-action-4.6.0
2 parents 4cc6df8 + 274c295 commit e6dcd44

File tree

70 files changed

+2466
-735
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2466
-735
lines changed

.github/file-filters.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This is used by the action https://github.com/dorny/paths-filter
2+
3+
high_risk_code: &high_risk_code
4+
# Transport classes
5+
- "sentry/src/main/java/io/sentry/transport/AsyncHttpTransport.java"
6+
- "sentry/src/main/java/io/sentry/transport/HttpConnection.java"
7+
- "sentry/src/main/java/io/sentry/transport/QueuedThreadPoolExecutor.java"
8+
- "sentry/src/main/java/io/sentry/transport/RateLimiter.java"
9+
- "sentry-apache-http-client-5/src/main/java/io/sentry/transport/apache/ApacheHttpClientTransport.java"
10+
11+
# Class used by hybrid SDKs
12+
- "sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Changes In High Risk Code
2+
on:
3+
pull_request:
4+
5+
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
8+
cancel-in-progress: true
9+
10+
jobs:
11+
files-changed:
12+
name: Detect changed files
13+
runs-on: ubuntu-latest
14+
# Map a step output to a job output
15+
outputs:
16+
high_risk_code: ${{ steps.changes.outputs.high_risk_code }}
17+
high_risk_code_files: ${{ steps.changes.outputs.high_risk_code_files }}
18+
steps:
19+
- uses: actions/checkout@v4
20+
- name: Get changed files
21+
id: changes
22+
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
23+
with:
24+
token: ${{ github.token }}
25+
filters: .github/file-filters.yml
26+
27+
# Enable listing of files matching each filter.
28+
# Paths to files will be available in `${FILTER_NAME}_files` output variable.
29+
list-files: csv
30+
31+
validate-high-risk-code:
32+
if: needs.files-changed.outputs.high_risk_code == 'true'
33+
needs: files-changed
34+
runs-on: ubuntu-latest
35+
steps:
36+
- name: Comment on PR to notify of changes in high risk files
37+
uses: actions/github-script@v7
38+
env:
39+
high_risk_code: ${{ needs.files-changed.outputs.high_risk_code_files }}
40+
with:
41+
script: |
42+
const highRiskFiles = process.env.high_risk_code;
43+
const fileList = highRiskFiles.split(',').map(file => `- [ ] ${file}`).join('\n');
44+
github.rest.issues.createComment({
45+
issue_number: context.issue.number,
46+
owner: context.repo.owner,
47+
repo: context.repo.repo,
48+
body: `### 🚨 Detected changes in high risk code 🚨 \n High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:\n ${fileList}`
49+
})

CHANGELOG.md

+27-7
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,47 @@
44

55
### Features
66

7+
- Add meta option to attach ANR thread dumps ([#3791](https://github.com/getsentry/sentry-java/pull/3791))
8+
9+
### Fixes
10+
11+
- fix invalid profiles when the transaction name is empty ([#3747](https://github.com/getsentry/sentry-java/pull/3747))
12+
- Deprecate `enableTracing` option ([#3777](https://github.com/getsentry/sentry-java/pull/3777))
13+
- Vendor `java.util.Random` and replace `java.security.SecureRandom` usages ([#3783](https://github.com/getsentry/sentry-java/pull/3783))
14+
- Fix potential ANRs due to NDK scope sync ([#3754](https://github.com/getsentry/sentry-java/pull/3754))
15+
- Fix potential ANRs due to NDK System.loadLibrary calls ([#3670](https://github.com/getsentry/sentry-java/pull/3670))
16+
17+
## 7.15.0
18+
19+
### Features
20+
721
- Add support for `feedback` envelope header item type ([#3687](https://github.com/getsentry/sentry-java/pull/3687))
822
- Add breadcrumb.origin field ([#3727](https://github.com/getsentry/sentry-java/pull/3727))
23+
- Session Replay: Add options to selectively mask/unmask views captured in replay. The following options are available: ([#3689](https://github.com/getsentry/sentry-java/pull/3689))
24+
- `android:tag="sentry-mask|sentry-unmask"` in XML or `view.setTag("sentry-mask|sentry-unmask")` in code tags
25+
- if you already have a tag set for a view, you can set a tag by id: `<tag android:id="@id/sentry_privacy" android:value="mask|unmask"/>` in XML or `view.setTag(io.sentry.android.replay.R.id.sentry_privacy, "mask|unmask")` in code
26+
- `view.sentryReplayMask()` or `view.sentryReplayUnmask()` extension functions
27+
- mask/unmask `View`s of a certain type by adding fully-qualified classname to one of the lists `options.experimental.sessionReplay.addMaskViewClass()` or `options.experimental.sessionReplay.addUnmaskViewClass()`. Note, that all of the view subclasses/subtypes will be masked/unmasked as well
28+
- For example, (this is already a default behavior) to mask all `TextView`s and their subclasses (`RadioButton`, `EditText`, etc.): `options.experimental.sessionReplay.addMaskViewClass("android.widget.TextView")`
29+
- If you're using code obfuscation, adjust your proguard-rules accordingly, so your custom view class name is not minified
30+
- Session Replay: Support Jetpack Compose masking ([#3739](https://github.com/getsentry/sentry-java/pull/3739))
31+
- To selectively mask/unmask @Composables, use `Modifier.sentryReplayMask()` and `Modifier.sentryReplayUnmask()` modifiers
32+
- Session Replay: Mask `WebView`, `VideoView` and `androidx.media3.ui.PlayerView` by default ([#3775](https://github.com/getsentry/sentry-java/pull/3775))
933

1034
### Fixes
1135

1236
- Avoid stopping appStartProfiler after application creation ([#3630](https://github.com/getsentry/sentry-java/pull/3630))
1337
- Session Replay: Correctly detect dominant color for `TextView`s with Spans ([#3682](https://github.com/getsentry/sentry-java/pull/3682))
14-
- Session Replay: Add options to selectively redact/ignore views from being captured. The following options are available: ([#3689](https://github.com/getsentry/sentry-java/pull/3689))
15-
- `android:tag="sentry-redact|sentry-ignore"` in XML or `view.setTag("sentry-redact|sentry-ignore")` in code tags
16-
- if you already have a tag set for a view, you can set a tag by id: `<tag android:id="@id/sentry_privacy" android:value="redact|ignore"/>` in XML or `view.setTag(io.sentry.android.replay.R.id.sentry_privacy, "redact|ignore")` in code
17-
- `view.sentryReplayRedact()` or `view.sentryReplayIgnore()` extension functions
18-
- redact/ignore `View`s of a certain type by adding fully-qualified classname to one of the lists `options.experimental.sessionReplay.addRedactViewClass()` or `options.experimental.sessionReplay.addIgnoreViewClass()`. Note, that all of the view subclasses/subtypes will be redacted/ignored as well
19-
- For example, (this is already a default behavior) to redact all `TextView`s and their subclasses (`RadioButton`, `EditText`, etc.): `options.experimental.sessionReplay.addRedactViewClass("android.widget.TextView")`
20-
- If you're using code obfuscation, adjust your proguard-rules accordingly, so your custom view class name is not minified
2138
- Fix ensure Application Context is used even when SDK is initialized via Activity Context ([#3669](https://github.com/getsentry/sentry-java/pull/3669))
2239
- Fix potential ANRs due to `Calendar.getInstance` usage in Breadcrumbs constructor ([#3736](https://github.com/getsentry/sentry-java/pull/3736))
40+
- Fix potential ANRs due to default integrations ([#3778](https://github.com/getsentry/sentry-java/pull/3778))
41+
- Lazily initialize heavy `SentryOptions` members to avoid ANRs on app start ([#3749](https://github.com/getsentry/sentry-java/pull/3749))
2342

2443
*Breaking changes*:
2544

2645
- `options.experimental.sessionReplay.errorSampleRate` was renamed to `options.experimental.sessionReplay.onErrorSampleRate` ([#3637](https://github.com/getsentry/sentry-java/pull/3637))
2746
- Manifest option `io.sentry.session-replay.error-sample-rate` was renamed to `io.sentry.session-replay.on-error-sample-rate` ([#3637](https://github.com/getsentry/sentry-java/pull/3637))
47+
- Change `redactAllText` and `redactAllImages` to `maskAllText` and `maskAllImages` ([#3741](https://github.com/getsentry/sentry-java/pull/3741))
2848

2949
## 7.14.0
3050

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ Sentry SDK for Java and Android
5656
| sentry-opentelemetry-core | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.sentry/sentry-opentelemetry-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.sentry/sentry-opentelemetry-core) |
5757
| sentry-okhttp | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.sentry/sentry-okhttp/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.sentry/sentry-okhttp) |
5858

59+
# Releases
5960

61+
This repo uses the following ways to release SDK updates:
62+
63+
- `Pre-release`: We create pre-releases (alpha, beta, RC,…) for larger and potentially more impactful changes, such as new features or major versions.
64+
- `Latest`: We continuously release major/minor/hotfix versions from the `main` branch. These releases go through all our internal quality gates and are very safe to use and intended to be the default for most teams.
65+
- `Stable`: We promote releases from `Latest` when they have been used in the field for some time and in scale, considering time since release, adoption, and other quality and stability metrics. These releases will be indicated on the releases page (https://github.com/getsentry/sentry-java/releases/) with the `Stable` suffix.
6066

6167
# Useful links and docs
6268

buildSrc/src/main/java/Config.kt

+3
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,11 @@ object Config {
147147
val composeActivity = "androidx.activity:activity-compose:1.4.0"
148148
val composeFoundation = "androidx.compose.foundation:foundation:$composeVersion"
149149
val composeUi = "androidx.compose.ui:ui:$composeVersion"
150+
151+
val composeUiReplay = "androidx.compose.ui:ui:1.5.0" // Note: don't change without testing forwards compatibility
150152
val composeFoundationLayout = "androidx.compose.foundation:foundation-layout:$composeVersion"
151153
val composeMaterial = "androidx.compose.material3:material3:1.0.0-alpha13"
154+
val composeCoil = "io.coil-kt:coil-compose:2.6.0"
152155

153156
val apolloKotlin = "com.apollographql.apollo3:apollo-runtime:3.8.2"
154157

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ android.useAndroidX=true
1010
android.defaults.buildfeatures.buildconfig=true
1111

1212
# Release information
13-
versionName=7.14.0
13+
versionName=7.15.0
1414

1515
# Override the SDK name on native crashes on Android
1616
sentryAndroidSdkName=sentry.native.android

sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ public synchronized void onActivityCreated(
382382

383383
firstActivityCreated = true;
384384

385-
if (fullyDisplayedReporter != null) {
385+
if (performanceEnabled && ttfdSpan != null && fullyDisplayedReporter != null) {
386386
fullyDisplayedReporter.registerFullyDrawnListener(() -> onFullFrameDrawn(ttfdSpan));
387387
}
388388
}

sentry-android-core/src/main/java/io/sentry/android/core/AnrV2EventProcessor.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
import io.sentry.protocol.SentryTransaction;
5555
import io.sentry.protocol.User;
5656
import io.sentry.util.HintUtils;
57+
import io.sentry.util.Random;
5758
import java.io.File;
58-
import java.security.SecureRandom;
5959
import java.util.ArrayList;
6060
import java.util.Arrays;
6161
import java.util.Collections;
@@ -83,7 +83,7 @@ public final class AnrV2EventProcessor implements BackfillingEventProcessor {
8383

8484
private final @NotNull SentryExceptionFactory sentryExceptionFactory;
8585

86-
private final @Nullable SecureRandom random;
86+
private final @Nullable Random random;
8787

8888
public AnrV2EventProcessor(
8989
final @NotNull Context context,
@@ -96,7 +96,7 @@ public AnrV2EventProcessor(
9696
final @NotNull Context context,
9797
final @NotNull SentryAndroidOptions options,
9898
final @NotNull BuildInfoProvider buildInfoProvider,
99-
final @Nullable SecureRandom random) {
99+
final @Nullable Random random) {
100100
this.context = ContextUtils.getApplicationContext(context);
101101
this.options = options;
102102
this.buildInfoProvider = buildInfoProvider;
@@ -180,7 +180,7 @@ private boolean sampleReplay(final @NotNull SentryEvent event) {
180180

181181
try {
182182
// we have to sample here with the old sample rate, because it may change between app launches
183-
final @NotNull SecureRandom random = this.random != null ? this.random : new SecureRandom();
183+
final @NotNull Random random = this.random != null ? this.random : new Random();
184184
final double replayErrorSampleRateDouble = Double.parseDouble(replayErrorSampleRate);
185185
if (replayErrorSampleRateDouble < random.nextDouble()) {
186186
options

sentry-android-core/src/main/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegration.java

+46-26
Original file line numberDiff line numberDiff line change
@@ -85,43 +85,25 @@ public void close() throws IOException {
8585
@SuppressWarnings("deprecation")
8686
@Override
8787
public void onConfigurationChanged(@NotNull Configuration newConfig) {
88-
if (hub != null) {
89-
final Device.DeviceOrientation deviceOrientation =
90-
DeviceOrientations.getOrientation(context.getResources().getConfiguration().orientation);
91-
92-
String orientation;
93-
if (deviceOrientation != null) {
94-
orientation = deviceOrientation.name().toLowerCase(Locale.ROOT);
95-
} else {
96-
orientation = "undefined";
97-
}
98-
99-
final Breadcrumb breadcrumb = new Breadcrumb();
100-
breadcrumb.setType("navigation");
101-
breadcrumb.setCategory("device.orientation");
102-
breadcrumb.setData("position", orientation);
103-
breadcrumb.setLevel(SentryLevel.INFO);
104-
105-
final Hint hint = new Hint();
106-
hint.set(ANDROID_CONFIGURATION, newConfig);
107-
108-
hub.addBreadcrumb(breadcrumb, hint);
109-
}
88+
final long now = System.currentTimeMillis();
89+
executeInBackground(() -> captureConfigurationChangedBreadcrumb(now, newConfig));
11090
}
11191

11292
@Override
11393
public void onLowMemory() {
114-
createLowMemoryBreadcrumb(null);
94+
final long now = System.currentTimeMillis();
95+
executeInBackground(() -> captureLowMemoryBreadcrumb(now, null));
11596
}
11697

11798
@Override
11899
public void onTrimMemory(final int level) {
119-
createLowMemoryBreadcrumb(level);
100+
final long now = System.currentTimeMillis();
101+
executeInBackground(() -> captureLowMemoryBreadcrumb(now, level));
120102
}
121103

122-
private void createLowMemoryBreadcrumb(final @Nullable Integer level) {
104+
private void captureLowMemoryBreadcrumb(final long timeMs, final @Nullable Integer level) {
123105
if (hub != null) {
124-
final Breadcrumb breadcrumb = new Breadcrumb();
106+
final Breadcrumb breadcrumb = new Breadcrumb(timeMs);
125107
if (level != null) {
126108
// only add breadcrumb if TRIM_MEMORY_BACKGROUND, TRIM_MEMORY_MODERATE or
127109
// TRIM_MEMORY_COMPLETE.
@@ -147,4 +129,42 @@ private void createLowMemoryBreadcrumb(final @Nullable Integer level) {
147129
hub.addBreadcrumb(breadcrumb);
148130
}
149131
}
132+
133+
private void captureConfigurationChangedBreadcrumb(
134+
final long timeMs, final @NotNull Configuration newConfig) {
135+
if (hub != null) {
136+
final Device.DeviceOrientation deviceOrientation =
137+
DeviceOrientations.getOrientation(context.getResources().getConfiguration().orientation);
138+
139+
String orientation;
140+
if (deviceOrientation != null) {
141+
orientation = deviceOrientation.name().toLowerCase(Locale.ROOT);
142+
} else {
143+
orientation = "undefined";
144+
}
145+
146+
final Breadcrumb breadcrumb = new Breadcrumb(timeMs);
147+
breadcrumb.setType("navigation");
148+
breadcrumb.setCategory("device.orientation");
149+
breadcrumb.setData("position", orientation);
150+
breadcrumb.setLevel(SentryLevel.INFO);
151+
152+
final Hint hint = new Hint();
153+
hint.set(ANDROID_CONFIGURATION, newConfig);
154+
155+
hub.addBreadcrumb(breadcrumb, hint);
156+
}
157+
}
158+
159+
private void executeInBackground(final @NotNull Runnable runnable) {
160+
if (options != null) {
161+
try {
162+
options.getExecutorService().submit(runnable);
163+
} catch (Throwable t) {
164+
options
165+
.getLogger()
166+
.log(SentryLevel.ERROR, t, "Failed to submit app components breadcrumb task");
167+
}
168+
}
169+
}
150170
}

sentry-android-core/src/main/java/io/sentry/android/core/LifecycleWatcher.java

-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import io.sentry.IHub;
77
import io.sentry.SentryLevel;
88
import io.sentry.Session;
9-
import io.sentry.android.core.internal.util.BreadcrumbFactory;
109
import io.sentry.transport.CurrentDateProvider;
1110
import io.sentry.transport.ICurrentDateProvider;
1211
import java.util.Timer;
@@ -90,7 +89,6 @@ private void startSession() {
9089
if (lastUpdatedSession == 0L
9190
|| (lastUpdatedSession + sessionIntervalMillis) <= currentTimeMillis) {
9291
if (enableSessionTracking) {
93-
addSessionBreadcrumb("start");
9492
hub.startSession();
9593
}
9694
hub.getOptions().getReplayController().start();
@@ -125,7 +123,6 @@ private void scheduleEndSession() {
125123
@Override
126124
public void run() {
127125
if (enableSessionTracking) {
128-
addSessionBreadcrumb("end");
129126
hub.endSession();
130127
}
131128
hub.getOptions().getReplayController().stop();
@@ -157,11 +154,6 @@ private void addAppBreadcrumb(final @NotNull String state) {
157154
}
158155
}
159156

160-
private void addSessionBreadcrumb(final @NotNull String state) {
161-
final Breadcrumb breadcrumb = BreadcrumbFactory.forSession(state);
162-
hub.addBreadcrumb(breadcrumb);
163-
}
164-
165157
@TestOnly
166158
@Nullable
167159
TimerTask getTimerTask() {

sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ final class ManifestMetadataReader {
2626
static final String SAMPLE_RATE = "io.sentry.sample-rate";
2727
static final String ANR_ENABLE = "io.sentry.anr.enable";
2828
static final String ANR_REPORT_DEBUG = "io.sentry.anr.report-debug";
29-
3029
static final String ANR_TIMEOUT_INTERVAL_MILLIS = "io.sentry.anr.timeout-interval-millis";
30+
static final String ANR_ATTACH_THREAD_DUMPS = "io.sentry.anr.attach-thread-dumps";
3131

3232
static final String AUTO_INIT = "io.sentry.auto-init";
3333
static final String NDK_ENABLE = "io.sentry.ndk.enable";
@@ -56,7 +56,7 @@ final class ManifestMetadataReader {
5656
static final String UNCAUGHT_EXCEPTION_HANDLER_ENABLE =
5757
"io.sentry.uncaught-exception-handler.enable";
5858

59-
static final String TRACING_ENABLE = "io.sentry.traces.enable";
59+
@Deprecated static final String TRACING_ENABLE = "io.sentry.traces.enable";
6060
static final String TRACES_SAMPLE_RATE = "io.sentry.traces.sample-rate";
6161
static final String TRACES_ACTIVITY_ENABLE = "io.sentry.traces.activity.enable";
6262
static final String TRACES_ACTIVITY_AUTO_FINISH_ENABLE =
@@ -108,9 +108,9 @@ final class ManifestMetadataReader {
108108

109109
static final String REPLAYS_ERROR_SAMPLE_RATE = "io.sentry.session-replay.on-error-sample-rate";
110110

111-
static final String REPLAYS_REDACT_ALL_TEXT = "io.sentry.session-replay.redact-all-text";
111+
static final String REPLAYS_MASK_ALL_TEXT = "io.sentry.session-replay.mask-all-text";
112112

113-
static final String REPLAYS_REDACT_ALL_IMAGES = "io.sentry.session-replay.redact-all-images";
113+
static final String REPLAYS_MASK_ALL_IMAGES = "io.sentry.session-replay.mask-all-images";
114114

115115
/** ManifestMetadataReader ctor */
116116
private ManifestMetadataReader() {}
@@ -176,6 +176,9 @@ static void applyMetadata(
176176
ANR_TIMEOUT_INTERVAL_MILLIS,
177177
options.getAnrTimeoutIntervalMillis()));
178178

179+
options.setAttachAnrThreadDump(
180+
readBool(metadata, logger, ANR_ATTACH_THREAD_DUMPS, options.isAttachAnrThreadDump()));
181+
179182
final String dsn = readString(metadata, logger, DSN, options.getDsn());
180183
final boolean enabled = readBool(metadata, logger, ENABLE_SENTRY, options.isEnabled());
181184

@@ -409,12 +412,12 @@ static void applyMetadata(
409412
options
410413
.getExperimental()
411414
.getSessionReplay()
412-
.setRedactAllText(readBool(metadata, logger, REPLAYS_REDACT_ALL_TEXT, true));
415+
.setMaskAllText(readBool(metadata, logger, REPLAYS_MASK_ALL_TEXT, true));
413416

414417
options
415418
.getExperimental()
416419
.getSessionReplay()
417-
.setRedactAllImages(readBool(metadata, logger, REPLAYS_REDACT_ALL_IMAGES, true));
420+
.setMaskAllImages(readBool(metadata, logger, REPLAYS_MASK_ALL_IMAGES, true));
418421
}
419422

420423
options

0 commit comments

Comments
 (0)