diff --git a/README.md b/README.md index 05869143..b7a2ae36 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,7 @@ You can optionally configure the `RecyclableStreamManager.ThrowExceptionOnToArra | -----|-------|-------------| | MemoryStreamCreated | Verbose | Logged every time a stream object is allocated. Fields: `guid`, `tag`, `requestedSize`, `actualSize`. | | MemoryStreamDisposed | Verbose | Logged every time a stream object is disposed. Fields: `guid`, `tag`, `allocationStack`, `disposeStack`. | -| MemoryStreamDoubleDispose | Critical | Logged if a stream is disposed more than once. This indicates a logic error by the user of the stream. Dispose should happen exactly once per stream to avoid resource usage bugs. Fields: `guid`, `tag`, `allocationStack`, `disposeStack1`, `disposeStack2`. | +| MemoryStreamDoubleDispose | Verbose | Logged if a stream is disposed more than once. This indicates a logic error by the user of the stream. Dispose should happen exactly once per stream to avoid resource usage bugs. Fields: `guid`, `tag`, `allocationStack`, `disposeStack1`, `disposeStack2`. | | MemoryStreamFinalized | Error | Logged if a stream has gone out of scope without being disposed. This indicates a resource leak. Fields: `guid`, `tag`, `allocationStack`.| | MemoryStreamToArray | Verbose | Logged whenever `ToArray` is called. This indicates a potential problem, as calling `ToArray` goes against the concepts of good memory practice which `RecyclableMemoryStream` is trying to solve. Fields: `guid`, `tag`, `stack`, `size`.| | MemoryStreamManagerInitialized| Informational | Logged when the `RecyclableMemoryStreamManager` is initialized. Fields: `blockSize`, `largeBufferMultiple`, `maximumBufferSize`.| diff --git a/src/Events.cs b/src/Events.cs index 076685bf..3a4d8799 100644 --- a/src/Events.cs +++ b/src/Events.cs @@ -110,7 +110,7 @@ public void MemoryStreamDisposed(Guid guid, string? tag, long lifetimeMs, string /// Call stack of the first dispose. /// Call stack of the second dispose. /// Note: Stacks will only be populated if RecyclableMemoryStreamManager.GenerateCallStacks is true. - [Event(3, Level = EventLevel.Critical)] + [Event(3, Level = EventLevel.Verbose)] public void MemoryStreamDoubleDispose(Guid guid, string? tag, string? allocationStack, string? disposeStack1, string? disposeStack2) { diff --git a/src/RecyclableMemoryStream.cs b/src/RecyclableMemoryStream.cs index 42f16431..27a2064f 100644 --- a/src/RecyclableMemoryStream.cs +++ b/src/RecyclableMemoryStream.cs @@ -280,7 +280,7 @@ protected override void Dispose(bool disposing) if (this.disposed) { string? doubleDisposeStack = null; - if (this.memoryManager.options.GenerateCallStacks) + if (this.memoryManager.GenerateDoubleDisposedStackTrace) { doubleDisposeStack = Environment.StackTrace; } diff --git a/src/RecyclableMemoryStreamManager.cs b/src/RecyclableMemoryStreamManager.cs index 985309b7..5f8f85f9 100644 --- a/src/RecyclableMemoryStreamManager.cs +++ b/src/RecyclableMemoryStreamManager.cs @@ -25,6 +25,7 @@ namespace Microsoft.IO using System; using System.Collections.Concurrent; using System.Collections.Generic; + using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; using System.Threading; @@ -82,6 +83,13 @@ public partial class RecyclableMemoryStreamManager internal readonly Options options; + internal bool GenerateDoubleDisposedStackTrace => + this.options.GenerateCallStacks && + ( + this.StreamDoubleDisposed != null || + Events.Writer.IsEnabled(EventLevel.Verbose, EventKeywords.None) + ); + /// /// Settings for controlling the behavior of RecyclableMemoryStream ///