diff --git a/src/Sentry/Scope.cs b/src/Sentry/Scope.cs
index d062290133..e4b51bf74f 100644
--- a/src/Sentry/Scope.cs
+++ b/src/Sentry/Scope.cs
@@ -144,31 +144,33 @@ public SentryUser User
///
public string? Distribution { get; set; }
- ///
- public string? Environment
+ private string? _environment;
+
+ ///
+ public string Environment
{
- get;
- set
+ get => _environment ?? Options.SettingLocator.GetEnvironment();
+ set => SetEnvironment(value);
+ }
+
+ string? IEventLike.Environment
+ {
+ get => Environment;
+ set => SetEnvironment(value);
+ }
+
+ private void SetEnvironment(string? environment)
+ {
+ if (_environment == environment)
{
- if (field == value)
- {
- return;
- }
+ return;
+ }
- if (value is null)
- {
- Options.LogDebug("Environment cannot be null. Reverting to default value from the options.");
- field = Options.Environment;
- }
- else
- {
- field = value;
- }
+ _environment = environment;
- if (Options is { EnableScopeSync: true, ScopeObserver: { } observer })
- {
- observer.SetEnvironment(field);
- }
+ if (Options is { EnableScopeSync: true, ScopeObserver: { } observer })
+ {
+ observer.SetEnvironment(Environment);
}
}
@@ -431,7 +433,7 @@ public void Clear()
User = new();
Release = default;
Distribution = default;
- Environment = default;
+ SetEnvironment(null);
TransactionName = default;
Transaction = default;
Fingerprint = Array.Empty();
@@ -515,7 +517,17 @@ public void Apply(IEventLike other)
other.Release ??= Release;
other.Distribution ??= Distribution;
- other.Environment ??= Environment;
+ if (other is Scope otherScope)
+ {
+ if (otherScope._environment is null)
+ {
+ otherScope.SetEnvironment(_environment);
+ }
+ }
+ else
+ {
+ other.Environment ??= Environment;
+ }
other.TransactionName ??= TransactionName;
other.Level ??= Level;
diff --git a/test/Sentry.AspNetCore.Tests/ScopeExtensionsTests.Populate_RouteData_SetToScope.verified.txt b/test/Sentry.AspNetCore.Tests/ScopeExtensionsTests.Populate_RouteData_SetToScope.verified.txt
index 8ba783b0dd..efda02a581 100644
--- a/test/Sentry.AspNetCore.Tests/ScopeExtensionsTests.Populate_RouteData_SetToScope.verified.txt
+++ b/test/Sentry.AspNetCore.Tests/ScopeExtensionsTests.Populate_RouteData_SetToScope.verified.txt
@@ -4,6 +4,7 @@
QueryString:
},
User: {},
+ Environment: production,
TransactionName: GET Ctrl.Actn,
Tags: {
route.action: Actn,
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt
index 803c8f81b3..efdfc57015 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt
@@ -404,7 +404,7 @@ namespace Sentry
public System.Collections.Generic.IReadOnlyCollection Breadcrumbs { get; }
public Sentry.SentryContexts Contexts { get; set; }
public string? Distribution { get; set; }
- public string? Environment { get; set; }
+ public string Environment { get; set; }
public System.Collections.Generic.IReadOnlyDictionary Extra { get; }
public System.Collections.Generic.IReadOnlyList Fingerprint { get; set; }
public Sentry.SentryLevel? Level { get; set; }
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt
index 803c8f81b3..efdfc57015 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet11_0.verified.txt
@@ -404,7 +404,7 @@ namespace Sentry
public System.Collections.Generic.IReadOnlyCollection Breadcrumbs { get; }
public Sentry.SentryContexts Contexts { get; set; }
public string? Distribution { get; set; }
- public string? Environment { get; set; }
+ public string Environment { get; set; }
public System.Collections.Generic.IReadOnlyDictionary Extra { get; }
public System.Collections.Generic.IReadOnlyList Fingerprint { get; set; }
public Sentry.SentryLevel? Level { get; set; }
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt
index 803c8f81b3..efdfc57015 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt
@@ -404,7 +404,7 @@ namespace Sentry
public System.Collections.Generic.IReadOnlyCollection Breadcrumbs { get; }
public Sentry.SentryContexts Contexts { get; set; }
public string? Distribution { get; set; }
- public string? Environment { get; set; }
+ public string Environment { get; set; }
public System.Collections.Generic.IReadOnlyDictionary Extra { get; }
public System.Collections.Generic.IReadOnlyList Fingerprint { get; set; }
public Sentry.SentryLevel? Level { get; set; }
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt
index 803c8f81b3..efdfc57015 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt
@@ -404,7 +404,7 @@ namespace Sentry
public System.Collections.Generic.IReadOnlyCollection Breadcrumbs { get; }
public Sentry.SentryContexts Contexts { get; set; }
public string? Distribution { get; set; }
- public string? Environment { get; set; }
+ public string Environment { get; set; }
public System.Collections.Generic.IReadOnlyDictionary Extra { get; }
public System.Collections.Generic.IReadOnlyList Fingerprint { get; set; }
public Sentry.SentryLevel? Level { get; set; }
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
index 89bf5488a8..e9c923778b 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
@@ -392,7 +392,7 @@ namespace Sentry
public System.Collections.Generic.IReadOnlyCollection Breadcrumbs { get; }
public Sentry.SentryContexts Contexts { get; set; }
public string? Distribution { get; set; }
- public string? Environment { get; set; }
+ public string Environment { get; set; }
public System.Collections.Generic.IReadOnlyDictionary Extra { get; }
public System.Collections.Generic.IReadOnlyList Fingerprint { get; set; }
public Sentry.SentryLevel? Level { get; set; }
diff --git a/test/Sentry.Tests/Protocol/ScopeTests.cs b/test/Sentry.Tests/Protocol/ScopeTests.cs
index 4ac9bfae4d..d6b7f26130 100644
--- a/test/Sentry.Tests/Protocol/ScopeTests.cs
+++ b/test/Sentry.Tests/Protocol/ScopeTests.cs
@@ -958,7 +958,7 @@ public void Apply_Sdk_SourceNone_TargetSingle_DoesNotModifyTarget()
}
[Fact]
- public void Apply_Environment_Null()
+ public void Apply_Environment_Null_TargetUsesOptionsEnvironment()
{
var sut = _fixture.GetSut();
sut.Environment = null;
@@ -966,7 +966,7 @@ public void Apply_Environment_Null()
var target = _fixture.GetSut();
sut.Apply(target);
- Assert.Null(target.Environment);
+ Assert.Equal(target.Options.SettingLocator.GetEnvironment(), target.Environment);
}
[Fact]
diff --git a/test/Sentry.Tests/ScopeTests.cs b/test/Sentry.Tests/ScopeTests.cs
index 0e04ec4b34..1ef6924990 100644
--- a/test/Sentry.Tests/ScopeTests.cs
+++ b/test/Sentry.Tests/ScopeTests.cs
@@ -770,6 +770,45 @@ public void SetEnvironment_Null_ObserverReceivesOptionEnvironment()
observer.Received(1).SetEnvironment(Arg.Is(optionsEnvironment));
}
+ [Fact]
+ public void Environment_NotSet_ReturnsOptionsEnvironment()
+ {
+ var scope = new Scope(new SentryOptions { Environment = "staging" });
+
+ scope.Environment.Should().Be("staging");
+ }
+
+ [Fact]
+ public void Environment_NotSetInOptions_ReturnsDefaultEnvironment()
+ {
+ var scope = new Scope(new SentryOptions());
+
+ scope.Environment.Should().NotBeNullOrWhiteSpace();
+ }
+
+ [Fact]
+ public void Apply_EnvironmentNotSetOnScope_EventGetsOptionsEnvironment()
+ {
+ var scope = new Scope(new SentryOptions { Environment = "staging" });
+ var evt = new SentryEvent();
+
+ scope.Apply(evt);
+
+ evt.Environment.Should().Be("staging");
+ }
+
+ [Fact]
+ public void Apply_EnvironmentSetOnTarget_TargetEnvironmentPreserved()
+ {
+ var options = new SentryOptions { Environment = "production" };
+ var source = new Scope(options) { Environment = "staging" };
+ var target = new Scope(options) { Environment = "development" };
+
+ source.Apply(target);
+
+ target.Environment.Should().Be("development");
+ }
+
[Fact]
public void SetEnvironment_SameValue_ObserverNotifiedOnce()
{