Skip to content

Commit cffc94b

Browse files
authored
Merge pull request #6122 from getsentry/fix/data-collection-explicit-opt-in
fix(core): [Data Collection 27] Make opt-in explicit
2 parents 670c4a7 + 5a3ce33 commit cffc94b

8 files changed

Lines changed: 48 additions & 27 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,7 @@ static void applyMetadata(
834834
final @NotNull Object metadata,
835835
final @NotNull ILogger logger,
836836
final @NotNull DataCollection currentDataCollection) {
837-
final @NotNull DataCollection dataCollection = new DataCollection(false);
837+
final @NotNull DataCollection dataCollection = new DataCollection();
838838

839839
if (containsKey(metadata, DATA_COLLECTION_USER_INFO)) {
840840
dataCollection.setUserInfo(readBool(metadata, logger, DATA_COLLECTION_USER_INFO, false));

‎sentry/api/sentry.api‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ public final class io/sentry/DataCategory : java/lang/Enum {
387387

388388
public final class io/sentry/DataCollection {
389389
public fun <init> ()V
390-
public fun <init> (Z)V
390+
public fun forceDataCollection ()V
391391
public fun getCookies ()Lio/sentry/KeyValueCollectionBehavior;
392392
public fun getDatabaseQueryData ()Ljava/lang/Boolean;
393393
public fun getFilePaths ()Ljava/lang/Boolean;

‎sentry/src/main/java/io/sentry/DataCollection.java‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@ public final class DataCollection {
2121
private final @NotNull HttpHeaders httpHeaders = new HttpHeaders();
2222
private final @NotNull Graphql graphql = new Graphql();
2323

24-
public DataCollection() {
25-
this(true);
26-
}
24+
public DataCollection() {}
2725

28-
@ApiStatus.Internal
29-
public DataCollection(final boolean forceDataCollection) {
30-
this.forceDataCollection = forceDataCollection;
26+
/** Opts into the documented Data Collection defaults when no individual option is configured. */
27+
public void forceDataCollection() {
28+
forceDataCollection = true;
3129
}
3230

3331
public @Nullable Boolean getUserInfo() {

‎sentry/src/main/java/io/sentry/ExternalOptions.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ public final class ExternalOptions {
250250

251251
private static @Nullable DataCollection parseDataCollection(
252252
final @NotNull PropertiesProvider propertiesProvider) {
253-
final DataCollection dataCollection = new DataCollection(false);
253+
final DataCollection dataCollection = new DataCollection();
254254

255255
final Boolean userInfo = propertiesProvider.getBooleanProperty("data-collection.user-info");
256256
if (userInfo != null) {

‎sentry/src/main/java/io/sentry/SentryOptions.java‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ public class SentryOptions implements RateLimiterConfig {
352352
/** whether to send personal identifiable information along with events */
353353
private boolean sendDefaultPii = false;
354354

355-
private @NotNull DataCollection dataCollection = new DataCollection(false);
355+
private @NotNull DataCollection dataCollection = new DataCollection();
356356

357357
private final @NotNull DataCollectionResolver dataCollectionResolver =
358358
new DataCollectionResolver(this);
@@ -1776,7 +1776,9 @@ public void setSendDefaultPii(boolean sendDefaultPii) {
17761776
/**
17771777
* Replaces the configuration for data that the SDK collects automatically.
17781778
*
1779-
* <p>Passing an empty {@link DataCollection} opts into the documented data-collection defaults.
1779+
* <p>This discards any Data Collection options already configured on this instance. To opt into
1780+
* the documented defaults while preserving them, call {@link
1781+
* DataCollection#forceDataCollection()} on the object returned by {@link #getDataCollection()}.
17801782
*/
17811783
public void setDataCollection(final @NotNull DataCollection dataCollection) {
17821784
if (dataCollection != null) {

‎sentry/src/test/java/io/sentry/DataCollectionResolverTest.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ class DataCollectionResolverTest {
371371

372372
@Test
373373
fun `explicit empty data collection enables every HTTP body direction`() {
374-
val options = SentryOptions().apply { dataCollection = DataCollection() }
374+
val options = SentryOptions().apply { dataCollection.forceDataCollection() }
375375

376376
assertThat(options.dataCollectionResolver.isIncomingRequestBody).isTrue()
377377
assertThat(options.dataCollectionResolver.isOutgoingRequestBody).isTrue()

‎sentry/src/test/java/io/sentry/DataCollectionTest.kt‎

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import kotlin.test.assertFailsWith
66

77
class DataCollectionTest {
88
@Test
9-
fun `public constructor forces Data Collection for empty configuration`() {
9+
fun `public constructor does not force Data Collection for empty configuration`() {
1010
val dataCollection = DataCollection()
1111

1212
assertThat(dataCollection.userInfo).isNull()
@@ -19,19 +19,21 @@ class DataCollectionTest {
1919
assertThat(dataCollection.httpHeaders.response).isNull()
2020
assertThat(dataCollection.graphql.document).isNull()
2121
assertThat(dataCollection.graphql.variables).isNull()
22-
assertThat(dataCollection.isExplicitlyConfigured()).isTrue()
22+
assertThat(dataCollection.isExplicitlyConfigured()).isFalse()
2323
}
2424

2525
@Test
26-
fun `SDK-owned configuration does not force Data Collection`() {
27-
val dataCollection = DataCollection(false)
26+
fun `force Data Collection makes empty configuration explicit`() {
27+
val dataCollection = DataCollection()
2828

29-
assertThat(dataCollection.isExplicitlyConfigured()).isFalse()
29+
dataCollection.forceDataCollection()
30+
31+
assertThat(dataCollection.isExplicitlyConfigured()).isTrue()
3032
}
3133

3234
@Test
33-
fun `nested override makes SDK-owned configuration explicit`() {
34-
val dataCollection = DataCollection(false)
35+
fun `nested override makes configuration explicit`() {
36+
val dataCollection = DataCollection()
3537

3638
dataCollection.graphql.setVariables(false)
3739

@@ -40,7 +42,7 @@ class DataCollectionTest {
4042

4143
@Test
4244
fun `explicit false is distinct from unset`() {
43-
val dataCollection = DataCollection(false)
45+
val dataCollection = DataCollection()
4446

4547
dataCollection.setUserInfo(false)
4648

@@ -50,7 +52,7 @@ class DataCollectionTest {
5052

5153
@Test
5254
fun `nullable Boolean options are mutable Kotlin properties`() {
53-
val dataCollection = DataCollection(false)
55+
val dataCollection = DataCollection()
5456

5557
dataCollection.userInfo = false
5658
dataCollection.databaseQueryData = false
@@ -81,7 +83,7 @@ class DataCollectionTest {
8183

8284
@Test
8385
fun `empty HTTP body set is distinct from unset`() {
84-
val dataCollection = DataCollection(false)
86+
val dataCollection = DataCollection()
8587

8688
dataCollection.setHttpBodies(emptySet())
8789

@@ -105,7 +107,7 @@ class DataCollectionTest {
105107

106108
@Test
107109
fun `database query data false is distinct from unset`() {
108-
val dataCollection = DataCollection(false)
110+
val dataCollection = DataCollection()
109111

110112
dataCollection.setDatabaseQueryData(false)
111113

@@ -115,7 +117,7 @@ class DataCollectionTest {
115117

116118
@Test
117119
fun `file paths false is distinct from unset`() {
118-
val dataCollection = DataCollection(false)
120+
val dataCollection = DataCollection()
119121

120122
dataCollection.setFilePaths(false)
121123

@@ -125,7 +127,7 @@ class DataCollectionTest {
125127

126128
@Test
127129
fun `nested HTTP header override marks configuration explicit`() {
128-
val dataCollection = DataCollection(false)
130+
val dataCollection = DataCollection()
129131
val behavior = KeyValueCollectionBehavior.denyList("authorization")
130132

131133
dataCollection.httpHeaders.setRequest(behavior)
@@ -135,7 +137,7 @@ class DataCollectionTest {
135137

136138
@Test
137139
fun `nested GraphQL false marks configuration explicit`() {
138-
val dataCollection = DataCollection(false)
140+
val dataCollection = DataCollection()
139141

140142
dataCollection.graphql.setVariables(false)
141143

‎sentry/src/test/java/io/sentry/SentryOptionsTest.kt‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,33 @@ class SentryOptionsTest {
4848
}
4949

5050
@Test
51-
fun `setting an empty data collection marks it explicitly configured`() {
51+
fun `setting an empty data collection preserves legacy mode`() {
5252
val options = SentryOptions()
5353

5454
options.dataCollection = DataCollection()
5555

56+
assertThat(options.dataCollection.isExplicitlyConfigured()).isFalse()
57+
}
58+
59+
@Test
60+
fun `forcing empty data collection marks it explicitly configured`() {
61+
val options = SentryOptions()
62+
63+
options.dataCollection.forceDataCollection()
64+
5665
assertThat(options.dataCollection.isExplicitlyConfigured()).isTrue()
5766
}
5867

68+
@Test
69+
fun `forcing data collection preserves existing options`() {
70+
val options = SentryOptions()
71+
options.dataCollection.setUserInfo(false)
72+
73+
options.dataCollection.forceDataCollection()
74+
75+
assertThat(options.dataCollection.userInfo).isFalse()
76+
}
77+
5978
@Test
6079
fun `setting data collection replaces the default instance`() {
6180
val options = SentryOptions()

0 commit comments

Comments
 (0)