Skip to content

Commit b3a5663

Browse files
authored
Merge branch 'main' into rz/fix/session-replay-improvements
2 parents b65c0b7 + c8461d4 commit b3a5663

File tree

76 files changed

+3633
-69
lines changed

Some content is hidden

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

76 files changed

+3633
-69
lines changed

.craft.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
minVersion: 0.29.3
22
changelogPolicy: auto
33
targets:
4-
- name: symbol-collector
5-
includeNames: /libsentry(-android)?\.so/
6-
batchType: android
7-
bundleIdPrefix: sentry-android-ndk-
84
- name: maven
95
includeNames: /^sentry.*$/
106
gradleCliPath: ./gradlew

CHANGELOG.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,26 @@
22

33
## Unreleased
44

5+
### Features
6+
7+
- The `ignoredErrors` option is now configurable via the manifest property `io.sentry.traces.ignored-errors` ([#4178](https://github.com/getsentry/sentry-java/pull/4178))
8+
- A list of active Spring profiles is attached to payloads sent to Sentry (errors, traces, etc.) and displayed in the UI when using our Spring or Spring Boot integrations ([#4147](https://github.com/getsentry/sentry-java/pull/4147))
9+
- This consists of an empty list when only the default profile is active
10+
- Added `enableTraceIdGeneration` to the AndroidOptions. This allows Hybrid SDKs to "freeze" and control the trace and connect errors on different layers of the application ([4188](https://github.com/getsentry/sentry-java/pull/4188))
11+
- Move to a single NetworkCallback listener to reduce number of IPC calls on Android ([#4164](https://github.com/getsentry/sentry-java/pull/4164))
12+
- Add GraphQL Apollo Kotlin 4 integration ([#4166](https://github.com/getsentry/sentry-java/pull/4166))
13+
514
### Fixes
615

716
- `SentryOptions.setTracePropagationTargets` is no longer marked internal ([#4170](https://github.com/getsentry/sentry-java/pull/4170))
817
- Session Replay: Fix crash when a navigation breadcrumb does not have "to" destination ([#4185](https://github.com/getsentry/sentry-java/pull/4185))
18+
- Session Replay: Cap video segment duration to maximum 5 minutes to prevent endless video encoding in background ([#4185](https://github.com/getsentry/sentry-java/pull/4185))
19+
- Check `tracePropagationTargets` in OpenTelemetry propagator ([#4191](https://github.com/getsentry/sentry-java/pull/4191))
20+
- If a URL can be retrieved from OpenTelemetry span attributes, we check it against `tracePropagationTargets` before attaching `sentry-trace` and `baggage` headers to outgoing requests
21+
- If no URL can be retrieved we always attach the headers
22+
- Fix `ignoredErrors`, `ignoredTransactions` and `ignoredCheckIns` being unset by external options like `sentry.properties` or ENV vars ([#4207](https://github.com/getsentry/sentry-java/pull/4207))
23+
- Whenever parsing of external options was enabled (`enableExternalConfiguration`), which is the default for many integrations, the values set on `SentryOptions` passed to `Sentry.init` would be lost
24+
- Even if the value was not set in any external configuration it would still be set to an empty list
925

1026
### Behavioural Changes
1127

@@ -115,7 +131,11 @@ Version 8 of the Sentry Android/Java SDK brings a variety of features and fixes.
115131
- New `Scope` types have been introduced, see "Behavioural Changes" for more details.
116132
- Lifecycle tokens have been introduced to manage `Scope` lifecycle, see "Behavioural Changes" for more details.
117133
- Bumping `minSdk` level to 21 (Android 5.0)
118-
- Our `sentry-opentelemetry-agent` has been improved and now works in combination with the rest of Sentry. You may now mix and match OpenTelemetry and Sentry API for instrumenting your application.
134+
- Our `sentry-opentelemetry-agent` has been improved and now works in combination with the rest of Sentry. You may now combine OpenTelemetry and Sentry for instrumenting your application.
135+
- You may now use both OpenTelemetry SDK and Sentry SDK to capture transactions and spans. They can also be mixed and end up on the same transaction.
136+
- OpenTelemetry extends the Sentry SDK by adding spans for numerous integrations, like Ktor, Vert.x and MongoDB. Please check [the OpenTelemetry GitHub repository](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation) for a full list.
137+
- OpenTelemetry allows propagating trace information from and to additional libraries, that Sentry did not support before, for example gRPC.
138+
- OpenTelemetry also has broader support for propagating the Sentry `Scopes` through reactive libraries like RxJava.
119139
- The SDK is now compatible with Spring Boot 3.4
120140
- We now support GraphQL v22 (`sentry-graphql-22`)
121141
- Metrics have been removed

CONTRIBUTING.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,36 @@ To run the build and tests:
2727
make compile
2828
```
2929

30+
# Format
31+
32+
To format the changed code and make CI happy you can run:
33+
34+
```shell
35+
make format
36+
```
37+
38+
or
39+
40+
```shell
41+
./gradlew spotlessApply
42+
```
43+
44+
# Binary compatibility validation
45+
46+
To prevent breaking ABI changes and exposing things we should not, we make use of https://github.com/Kotlin/binary-compatibility-validator. If your change intended to introduce a new public method/property or modify the existing one you can overwrite the API declarations to make CI happy as follows (overwrites them from scratch):
47+
48+
```shell
49+
make api
50+
```
51+
52+
or
53+
54+
```shell
55+
./gradlew apiDump
56+
```
57+
58+
However, if your change did not intend to modify the public API, consider changing the method/property visibility or removing the change altogether.
59+
3060
# CI
3161

3262
Build and tests are automatically run against branches and pull requests

buildSrc/src/main/java/Config.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ object Config {
157157
val composeCoil = "io.coil-kt:coil-compose:2.6.0"
158158

159159
val apolloKotlin = "com.apollographql.apollo3:apollo-runtime:3.8.2"
160+
val apolloKotlin4 = "com.apollographql.apollo:apollo-runtime:4.1.1"
160161

161162
val sentryNativeNdk = "io.sentry:sentry-native-ndk:0.7.20"
162163

@@ -250,6 +251,7 @@ object Config {
250251
val SENTRY_SPRING_BOOT_JAKARTA_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring-boot.jakarta"
251252
val SENTRY_OPENTELEMETRY_AGENT_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.agent"
252253
val SENTRY_APOLLO3_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.apollo3"
254+
val SENTRY_APOLLO4_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.apollo4"
253255
val SENTRY_APOLLO_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.apollo"
254256
val SENTRY_GRAPHQL_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.graphql"
255257
val SENTRY_GRAPHQL22_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.graphql22"

sentry-android-core/api/sentry-android-core.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
292292
public fun isEnableAppComponentBreadcrumbs ()Z
293293
public fun isEnableAppLifecycleBreadcrumbs ()Z
294294
public fun isEnableAutoActivityLifecycleTracing ()Z
295+
public fun isEnableAutoTraceIdGeneration ()Z
295296
public fun isEnableFramesTracking ()Z
296297
public fun isEnableNdk ()Z
297298
public fun isEnableNetworkEventBreadcrumbs ()Z
@@ -315,6 +316,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
315316
public fun setEnableAppComponentBreadcrumbs (Z)V
316317
public fun setEnableAppLifecycleBreadcrumbs (Z)V
317318
public fun setEnableAutoActivityLifecycleTracing (Z)V
319+
public fun setEnableAutoTraceIdGeneration (Z)V
318320
public fun setEnableFramesTracking (Z)V
319321
public fun setEnableNdk (Z)V
320322
public fun setEnableNetworkEventBreadcrumbs (Z)V

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ private void startTracing(final @NotNull Activity activity) {
161161
if (scopes != null && !isRunningTransactionOrTrace(activity)) {
162162
if (!performanceEnabled) {
163163
activitiesWithOngoingTransactions.put(activity, NoOpTransaction.getInstance());
164-
TracingUtils.startNewTrace(scopes);
164+
if (options.isEnableAutoTraceIdGeneration()) {
165+
TracingUtils.startNewTrace(scopes);
166+
}
165167
} else {
166168
// as we allow a single transaction running on the bound Scope, we finish the previous ones
167169
stopPreviousTransactions();

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ final class ManifestMetadataReader {
105105

106106
static final String MAX_BREADCRUMBS = "io.sentry.max-breadcrumbs";
107107

108+
static final String IGNORED_ERRORS = "io.sentry.ignored-errors";
109+
110+
static final String ENABLE_AUTO_TRACE_ID_GENERATION =
111+
"io.sentry.traces.enable-auto-id-generation";
112+
108113
/** ManifestMetadataReader ctor */
109114
private ManifestMetadataReader() {}
110115

@@ -378,6 +383,13 @@ static void applyMetadata(
378383
readBool(
379384
metadata, logger, ENABLE_SCOPE_PERSISTENCE, options.isEnableScopePersistence()));
380385

386+
options.setEnableAutoTraceIdGeneration(
387+
readBool(
388+
metadata,
389+
logger,
390+
ENABLE_AUTO_TRACE_ID_GENERATION,
391+
options.isEnableAutoTraceIdGeneration()));
392+
381393
if (options.getSessionReplay().getSessionSampleRate() == null) {
382394
final Double sessionSampleRate =
383395
readDouble(metadata, logger, REPLAYS_SESSION_SAMPLE_RATE);
@@ -400,6 +412,8 @@ static void applyMetadata(
400412
options
401413
.getSessionReplay()
402414
.setMaskAllImages(readBool(metadata, logger, REPLAYS_MASK_ALL_IMAGES, true));
415+
416+
options.setIgnoredErrors(readList(metadata, logger, IGNORED_ERRORS));
403417
}
404418

405419
options

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ public final class SentryAndroidOptions extends SentryOptions {
166166
*/
167167
private boolean enableScopeSync = true;
168168

169+
/**
170+
* Whether to enable automatic trace ID generation. This is mainly used by the Hybrid SDKs to
171+
* control the trace ID generation from the outside.
172+
*/
173+
private boolean enableAutoTraceIdGeneration = true;
174+
169175
public interface BeforeCaptureCallback {
170176

171177
/**
@@ -594,4 +600,12 @@ public void setFrameMetricsCollector(
594600
final @Nullable SentryFrameMetricsCollector frameMetricsCollector) {
595601
this.frameMetricsCollector = frameMetricsCollector;
596602
}
603+
604+
public boolean isEnableAutoTraceIdGeneration() {
605+
return enableAutoTraceIdGeneration;
606+
}
607+
608+
public void setEnableAutoTraceIdGeneration(final boolean enableAutoTraceIdGeneration) {
609+
this.enableAutoTraceIdGeneration = enableAutoTraceIdGeneration;
610+
}
597611
}

sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,9 @@ private void startTracing(final @NotNull UiElement target, final @NotNull Gestur
202202

203203
if (!(options.isTracingEnabled() && options.isEnableUserInteractionTracing())) {
204204
if (isNewInteraction) {
205-
TracingUtils.startNewTrace(scopes);
205+
if (options.isEnableAutoTraceIdGeneration()) {
206+
TracingUtils.startNewTrace(scopes);
207+
}
206208
activeUiElement = target;
207209
activeEventType = eventType;
208210
}

sentry-android-core/src/main/java/io/sentry/android/core/internal/util/AndroidConnectionStatusProvider.java

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44
import android.annotation.SuppressLint;
55
import android.content.Context;
66
import android.net.ConnectivityManager;
7+
import android.net.ConnectivityManager.NetworkCallback;
78
import android.net.Network;
89
import android.net.NetworkCapabilities;
910
import android.os.Build;
10-
import androidx.annotation.NonNull;
1111
import io.sentry.IConnectionStatusProvider;
1212
import io.sentry.ILogger;
13+
import io.sentry.ISentryLifecycleToken;
1314
import io.sentry.SentryLevel;
1415
import io.sentry.android.core.BuildInfoProvider;
1516
import io.sentry.android.core.ContextUtils;
16-
import java.util.HashMap;
17-
import java.util.Map;
17+
import io.sentry.util.AutoClosableReentrantLock;
18+
import java.util.ArrayList;
19+
import java.util.List;
1820
import org.jetbrains.annotations.ApiStatus;
1921
import org.jetbrains.annotations.NotNull;
2022
import org.jetbrains.annotations.Nullable;
@@ -31,8 +33,9 @@ public final class AndroidConnectionStatusProvider implements IConnectionStatusP
3133
private final @NotNull Context context;
3234
private final @NotNull ILogger logger;
3335
private final @NotNull BuildInfoProvider buildInfoProvider;
34-
private final @NotNull Map<IConnectionStatusObserver, ConnectivityManager.NetworkCallback>
35-
registeredCallbacks;
36+
private final @NotNull List<IConnectionStatusObserver> connectionStatusObservers;
37+
private final @NotNull AutoClosableReentrantLock lock = new AutoClosableReentrantLock();
38+
private volatile @Nullable NetworkCallback networkCallback;
3639

3740
public AndroidConnectionStatusProvider(
3841
@NotNull Context context,
@@ -41,7 +44,7 @@ public AndroidConnectionStatusProvider(
4144
this.context = ContextUtils.getApplicationContext(context);
4245
this.logger = logger;
4346
this.buildInfoProvider = buildInfoProvider;
44-
this.registeredCallbacks = new HashMap<>();
47+
this.connectionStatusObservers = new ArrayList<>();
4548
}
4649

4750
@Override
@@ -65,40 +68,64 @@ public AndroidConnectionStatusProvider(
6568

6669
@Override
6770
public boolean addConnectionStatusObserver(final @NotNull IConnectionStatusObserver observer) {
71+
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
72+
connectionStatusObservers.add(observer);
73+
}
6874

69-
final ConnectivityManager.NetworkCallback callback =
70-
new ConnectivityManager.NetworkCallback() {
71-
@Override
72-
public void onAvailable(@NonNull Network network) {
73-
observer.onConnectionStatusChanged(getConnectionStatus());
74-
}
75-
76-
@Override
77-
public void onLosing(@NonNull Network network, int maxMsToLive) {
78-
observer.onConnectionStatusChanged(getConnectionStatus());
79-
}
80-
81-
@Override
82-
public void onLost(@NonNull Network network) {
83-
observer.onConnectionStatusChanged(getConnectionStatus());
84-
}
85-
86-
@Override
87-
public void onUnavailable() {
88-
observer.onConnectionStatusChanged(getConnectionStatus());
75+
if (networkCallback == null) {
76+
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
77+
if (networkCallback == null) {
78+
final @NotNull NetworkCallback newNetworkCallback =
79+
new NetworkCallback() {
80+
@Override
81+
public void onAvailable(final @NotNull Network network) {
82+
updateObservers();
83+
}
84+
85+
@Override
86+
public void onUnavailable() {
87+
updateObservers();
88+
}
89+
90+
@Override
91+
public void onLost(final @NotNull Network network) {
92+
updateObservers();
93+
}
94+
95+
public void updateObservers() {
96+
final @NotNull ConnectionStatus status = getConnectionStatus();
97+
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
98+
for (final @NotNull IConnectionStatusObserver observer :
99+
connectionStatusObservers) {
100+
observer.onConnectionStatusChanged(status);
101+
}
102+
}
103+
}
104+
};
105+
106+
if (registerNetworkCallback(context, logger, buildInfoProvider, newNetworkCallback)) {
107+
networkCallback = newNetworkCallback;
108+
return true;
109+
} else {
110+
return false;
89111
}
90-
};
91-
92-
registeredCallbacks.put(observer, callback);
93-
return registerNetworkCallback(context, logger, buildInfoProvider, callback);
112+
}
113+
}
114+
}
115+
// networkCallback is already registered, so we can safely return true
116+
return true;
94117
}
95118

96119
@Override
97120
public void removeConnectionStatusObserver(final @NotNull IConnectionStatusObserver observer) {
98-
final @Nullable ConnectivityManager.NetworkCallback callback =
99-
registeredCallbacks.remove(observer);
100-
if (callback != null) {
101-
unregisterNetworkCallback(context, logger, callback);
121+
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
122+
connectionStatusObservers.remove(observer);
123+
if (connectionStatusObservers.isEmpty()) {
124+
if (networkCallback != null) {
125+
unregisterNetworkCallback(context, logger, networkCallback);
126+
networkCallback = null;
127+
}
128+
}
102129
}
103130
}
104131

@@ -281,7 +308,7 @@ public static boolean registerNetworkCallback(
281308
final @NotNull Context context,
282309
final @NotNull ILogger logger,
283310
final @NotNull BuildInfoProvider buildInfoProvider,
284-
final @NotNull ConnectivityManager.NetworkCallback networkCallback) {
311+
final @NotNull NetworkCallback networkCallback) {
285312
if (buildInfoProvider.getSdkInfoVersion() < Build.VERSION_CODES.N) {
286313
logger.log(SentryLevel.DEBUG, "NetworkCallbacks need Android N+.");
287314
return false;
@@ -307,7 +334,7 @@ public static boolean registerNetworkCallback(
307334
public static void unregisterNetworkCallback(
308335
final @NotNull Context context,
309336
final @NotNull ILogger logger,
310-
final @NotNull ConnectivityManager.NetworkCallback networkCallback) {
337+
final @NotNull NetworkCallback networkCallback) {
311338

312339
final ConnectivityManager connectivityManager = getConnectivityManager(context, logger);
313340
if (connectivityManager == null) {
@@ -322,8 +349,13 @@ public static void unregisterNetworkCallback(
322349

323350
@TestOnly
324351
@NotNull
325-
public Map<IConnectionStatusObserver, ConnectivityManager.NetworkCallback>
326-
getRegisteredCallbacks() {
327-
return registeredCallbacks;
352+
public List<IConnectionStatusObserver> getStatusObservers() {
353+
return connectionStatusObservers;
354+
}
355+
356+
@TestOnly
357+
@Nullable
358+
public NetworkCallback getNetworkCallback() {
359+
return networkCallback;
328360
}
329361
}

0 commit comments

Comments
 (0)