Skip to content

Commit 4bf0a82

Browse files
bitsandfoxesromtsnmarkushisentry-junior[bot]
authored
feat: add Get/Set Environment on Scope (#5772)
* added get/set environment to scope * updated changelog * updated changelog * sync scope clear * clear * apply to replay * scope helper * comment * made scope apply its environment on other events too * Update CHANGELOG.md Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com> * feat: apply the scope environment to Baggage/DSC and address review feedback * fix: read the DSC environment from the combined scope view instead of the isolation scope * feat: apply the scope environment to logs, metrics and profiles * test: stub the ScopeType overload of configureScope in scopes mocks * feat(android): sync the scope environment to the NDK scope * ci: fix Build Job ubuntu-latest [pr-shepherd] * test(apollo-5): stub the ScopeType overload of configureScope in scopes mock * chore: move changelog entry to Unreleased * fix(ndk): catch only RejectedExecutionException when syncing the scope environment --------- Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com> Co-authored-by: Markus Hintersteiner <markus.hintersteiner@sentry.io> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
1 parent 8eee5d1 commit 4bf0a82

63 files changed

Lines changed: 706 additions & 27 deletions

File tree

Some content is hidden

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

‎CHANGELOG.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Unreleased
44

5+
### Features
6+
7+
- Added `Environment` to the `Scope`, allowing you to overwrite the `Environment` set on the options ([#5772](https://github.com/getsentry/sentry-java/pull/5772))
8+
- The scope `Environment` is also applied to the trace envelope header (DSC), logs, metrics and profiles, so all telemetry of a trace reports the same environment
9+
510
### Fixes
611

712
- Keep UI profiling running when `startProfiler` is called before a requested stop takes effect at the end of the current chunk ([#6291](https://github.com/getsentry/sentry-java/pull/6291))

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ private void backfillScope(
198198
setRequest(event);
199199
setUser(event);
200200
setScopeTags(event);
201+
setScopeEnvironment(event);
201202
setBreadcrumbs(event);
202203
setExtras(event);
203204
setContexts(event);
@@ -492,6 +493,16 @@ private void setEnvironment(
492493
}
493494
}
494495

496+
private void setScopeEnvironment(final @NotNull SentryBaseEvent event) {
497+
if (event.getEnvironment() == null) {
498+
final @Nullable String scopeEnvironment =
499+
readFromDisk(options, PersistingScopeObserver.ENVIRONMENT_FILENAME, String.class);
500+
if (scopeEnvironment != null) {
501+
event.setEnvironment(scopeEnvironment);
502+
}
503+
}
504+
}
505+
495506
private void setDebugMeta(
496507
final @NotNull SentryBaseEvent event, final @NotNull OptionsSource optionsSource) {
497508
DebugMeta debugMeta = event.getDebugMeta();

‎sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,18 @@ class ApplicationExitInfoEventProcessorTest {
461461
assertEquals("release", processed.environment)
462462
}
463463

464+
@Test
465+
fun `if scope environment is persisted, it takes precedence over the options environment`() {
466+
val hint = HintUtils.createWithTypeCheckHint(BackfillableHint())
467+
468+
val processor = fixture.getSut(tmpDir, populateOptionsCache = true)
469+
fixture.persistScope(PersistingScopeObserver.ENVIRONMENT_FILENAME, "staging")
470+
471+
val processed = processor.process(SentryEvent(), hint)
472+
473+
assertEquals("staging", processed!!.environment)
474+
}
475+
464476
@Test
465477
fun `if release is not persisted and app was not updated, uses release from options`() {
466478
val hint = HintUtils.createWithTypeCheckHint(AbnormalExitHint(timestamp = 2_000))
@@ -542,6 +554,7 @@ class ApplicationExitInfoEventProcessorTest {
542554
fixture.options.release = "io.sentry.samples@1.2.0+232"
543555
fixture.options.environment = "production"
544556
fixture.options.dist = "custom-dist"
557+
fixture.persistScope(PersistingScopeObserver.ENVIRONMENT_FILENAME, "staging")
545558
setLastUpdateTime(1_000)
546559

547560
val processed = processor.process(SentryEvent(), hint)!!

‎sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerClickTest.kt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import io.sentry.IScopes
1515
import io.sentry.PropagationContext
1616
import io.sentry.Scope.IWithPropagationContext
1717
import io.sentry.ScopeCallback
18+
import io.sentry.ScopeType
1819
import io.sentry.SentryLevel.INFO
1920
import io.sentry.android.core.SentryAndroidOptions
2021
import io.sentry.util.LazyEvaluator
@@ -85,6 +86,9 @@ class SentryGestureListenerClickTest {
8586
doAnswer { (it.arguments[0] as ScopeCallback).run(scope) }
8687
.whenever(scopes)
8788
.configureScope(any())
89+
doAnswer { (it.arguments[1] as ScopeCallback).run(scope) }
90+
.whenever(scopes)
91+
.configureScope(anyOrNull<ScopeType>(), any())
8892
doAnswer {
8993
(it.arguments[0] as IWithPropagationContext).accept(propagationContext)
9094
propagationContext

‎sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerScrollTest.kt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import io.sentry.IScopes
1717
import io.sentry.PropagationContext
1818
import io.sentry.Scope
1919
import io.sentry.ScopeCallback
20+
import io.sentry.ScopeType
2021
import io.sentry.SentryLevel
2122
import io.sentry.SentryLevel.INFO
2223
import io.sentry.android.core.SentryAndroidOptions
@@ -82,6 +83,9 @@ class SentryGestureListenerScrollTest {
8283
doAnswer { (it.arguments[0] as ScopeCallback).run(scope) }
8384
.whenever(scopes)
8485
.configureScope(any())
86+
doAnswer { (it.arguments[1] as ScopeCallback).run(scope) }
87+
.whenever(scopes)
88+
.configureScope(anyOrNull<ScopeType>(), any())
8589
doAnswer {
8690
(it.arguments[0] as Scope.IWithPropagationContext).accept(propagationContext)
8791
propagationContext

‎sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerTracingTest.kt‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import io.sentry.IScope
1313
import io.sentry.IScopes
1414
import io.sentry.Scope
1515
import io.sentry.ScopeCallback
16+
import io.sentry.ScopeType
1617
import io.sentry.SentryTracer
1718
import io.sentry.SpanContext
1819
import io.sentry.SpanId
@@ -31,6 +32,7 @@ import kotlin.test.assertNotNull
3132
import kotlin.test.assertNull
3233
import org.mockito.ArgumentCaptor
3334
import org.mockito.kotlin.any
35+
import org.mockito.kotlin.anyOrNull
3436
import org.mockito.kotlin.check
3537
import org.mockito.kotlin.clearInvocations
3638
import org.mockito.kotlin.doAnswer
@@ -94,6 +96,9 @@ class SentryGestureListenerTracingTest {
9496
doAnswer { (it.arguments[0] as ScopeCallback).run(scope) }
9597
.whenever(scopes)
9698
.configureScope(any())
99+
doAnswer { (it.arguments[1] as ScopeCallback).run(scope) }
100+
.whenever(scopes)
101+
.configureScope(anyOrNull<ScopeType>(), any())
97102

98103
return SentryGestureListener(activity, scopes, options)
99104
}

‎sentry-android-ndk/api/sentry-android-ndk.api‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public final class io/sentry/android/ndk/NdkScopeObserver : io/sentry/ScopeObser
2020
public fun clearAttachments ()V
2121
public fun removeExtra (Ljava/lang/String;)V
2222
public fun removeTag (Ljava/lang/String;)V
23+
public fun setEnvironment (Ljava/lang/String;)V
2324
public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V
2425
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
2526
public fun setTrace (Lio/sentry/SpanContext;Lio/sentry/IScope;)V

‎sentry-android-ndk/src/main/java/io/sentry/android/ndk/NdkScopeObserver.java‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.sentry.util.Objects;
1515
import java.util.Locale;
1616
import java.util.Map;
17+
import java.util.concurrent.RejectedExecutionException;
1718
import org.jetbrains.annotations.ApiStatus;
1819
import org.jetbrains.annotations.NotNull;
1920
import org.jetbrains.annotations.Nullable;
@@ -53,6 +54,15 @@ public void setUser(final @Nullable User user) {
5354
}
5455
}
5556

57+
@Override
58+
public void setEnvironment(@Nullable String environment) {
59+
try {
60+
options.getExecutorService().submit(() -> nativeScope.setEnvironment(environment));
61+
} catch (RejectedExecutionException e) {
62+
options.getLogger().log(SentryLevel.ERROR, e, "Scope sync setEnvironment has an error.");
63+
}
64+
}
65+
5666
@Override
5767
public void addBreadcrumb(final @NotNull Breadcrumb crumb) {
5868
try {

‎sentry-android-ndk/src/test/java/io/sentry/android/ndk/NdkScopeObserverTest.kt‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,15 @@ class NdkScopeObserverTest {
184184

185185
verify(fixture.nativeScope).clearAttachments()
186186
}
187+
188+
@Test
189+
fun `set environments forwards call to native scope`() {
190+
val sut = fixture.getSut()
191+
192+
sut.setEnvironment(null)
193+
verify(fixture.nativeScope).setEnvironment(eq(null))
194+
195+
sut.setEnvironment("production")
196+
verify(fixture.nativeScope).setEnvironment(eq("production"))
197+
}
187198
}

‎sentry-android-replay/src/test/java/io/sentry/android/replay/ReplaySmokeTest.kt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
1616
import io.sentry.IScopes
1717
import io.sentry.Scope
1818
import io.sentry.ScopeCallback
19+
import io.sentry.ScopeType
1920
import io.sentry.SentryOptions
2021
import io.sentry.SentryReplayEvent.ReplayType
2122
import io.sentry.android.replay.util.ReplayShadowMediaCodec
@@ -72,6 +73,9 @@ class ReplaySmokeTest {
7273
doAnswer { (it.arguments[0] as ScopeCallback).run(scope) }
7374
.whenever(it)
7475
.configureScope(any())
76+
doAnswer { (it.arguments[1] as ScopeCallback).run(scope) }
77+
.whenever(it)
78+
.configureScope(anyOrNull<ScopeType>(), any())
7579

7680
on { rateLimiter }.doReturn(rateLimiter)
7781
}

0 commit comments

Comments
 (0)