diff --git a/src/Serilog/Context/LogContext.cs b/src/Serilog/Context/LogContext.cs
index feeef11eb..e969f169e 100644
--- a/src/Serilog/Context/LogContext.cs
+++ b/src/Serilog/Context/LogContext.cs
@@ -150,6 +150,34 @@ public static ILogEventEnricher Clone()
return new SafeAggregateEnricher(stack);
}
+ ///
+ /// Remove all enrichers from , returning
+ /// that must later be used to restore enrichers that were on the stack before was called.
+ ///
+ /// A token that must be disposed, in order, to restore properties back to the stack.
+ public static IDisposable Suspend()
+ {
+ var stack = GetOrCreateEnricherStack();
+ var bookmark = new ContextStackBookmark(stack);
+
+ Enrichers = ImmutableStack.Empty;
+
+ return bookmark;
+ }
+
+ ///
+ /// Remove all enrichers from for current async scope.
+ ///
+ public static void Reset()
+ {
+ var enrichers = GetOrCreateEnricherStack();
+ if (!enrichers.IsEmpty)
+ {
+ enrichers = ImmutableStack.Empty;
+ Enrichers = enrichers;
+ }
+ }
+
static ImmutableStack GetOrCreateEnricherStack()
{
var enrichers = Enrichers;
diff --git a/test/Serilog.Tests/Context/LogContextTests.cs b/test/Serilog.Tests/Context/LogContextTests.cs
index 44d313473..7fc0b62df 100644
--- a/test/Serilog.Tests/Context/LogContextTests.cs
+++ b/test/Serilog.Tests/Context/LogContextTests.cs
@@ -199,6 +199,62 @@ public async Task ContextPropertiesCrossAsyncCalls()
}
}
+ [Fact]
+ public async Task ContextEnrichersInAsyncScopeCanBeCleared()
+ {
+ LogEvent lastEvent = null;
+
+ var log = new LoggerConfiguration()
+ .Enrich.FromLogContext()
+ .WriteTo.Sink(new DelegatingSink(e => lastEvent = e))
+ .CreateLogger();
+
+ using (LogContext.Push(new PropertyEnricher("A", 1)))
+ {
+ await Task.Run(() =>
+ {
+ LogContext.Reset();
+ log.Write(Some.InformationEvent());
+ });
+
+ Assert.Empty(lastEvent.Properties);
+
+ // Reset should only work for current async scope, outside of it previous Context
+ // instance should be available again.
+ log.Write(Some.InformationEvent());
+ Assert.Equal(1, lastEvent.Properties["A"].LiteralValue());
+ }
+ }
+
+ [Fact]
+ public async Task ContextEnrichersCanBeTemporarilyCleared()
+ {
+ LogEvent lastEvent = null;
+
+ var log = new LoggerConfiguration()
+ .Enrich.FromLogContext()
+ .WriteTo.Sink(new DelegatingSink(e => lastEvent = e))
+ .CreateLogger();
+
+ using (LogContext.Push(new PropertyEnricher("A", 1)))
+ {
+ using (LogContext.Suspend())
+ {
+ await Task.Run(() =>
+ {
+ log.Write(Some.InformationEvent());
+ });
+
+ Assert.Empty(lastEvent.Properties);
+ }
+
+ // Suspend should only work for scope of using. After calling Dispose all enrichers
+ // should be restored.
+ log.Write(Some.InformationEvent());
+ Assert.Equal(1, lastEvent.Properties["A"].LiteralValue());
+ }
+ }
+
#if APPDOMAIN
// Must not actually try to pass context across domains,
// since user property types may not be serializable.