question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SentryEvent memory leak with large exception object graphs

See original GitHub issue

Package

Sentry

.NET Flavor

.NET Core

.NET Version

7.0

OS

Linux

SDK Version

3.34.0

Self-Hosted Sentry Version

No response

Steps to Reproduce

I’m having an issue where a process in which I’ve enabled the Sentry Microsoft.Extensions.Logging integration is consistently leaking memory. The issue seems to be most obvious in cases where the SentryEvent exception instance references a large object graph - say, a Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException that references a DbContext with a large number of entities loaded.

Expected Result

I would expect the SentryEvent instances to be processed/sent/etc. and eventually freed.

Actual Result

Based on the process memory consumption (and memory dumps) it seems like the SentryEvent instances are never freed: image

I’m wondering if the Sentry SDK is trying to serialize and send the DbUpdateConcurrencyException along with everything in the associated DbContext, fails due to limitations on event size, and ends up retrying forever.

A typical gcroot from dotnet-dump analyze looks like this:

          -> 7fa86fe3bc78     System.Threading.Thread
          -> 7fa8421108a0     System.Threading.ExecutionContext
          -> 7fa842110870     System.Threading.AsyncLocalValueMap+TwoElementAsyncLocalValueMap
          -> 7fa8420ab168     System.Collections.Generic.KeyValuePair<Sentry.Scope, Sentry.ISentryClient>[]
          -> 7fa84209c4e0     Sentry.SentryClient
          -> 7fa84209c5f0     Sentry.Internal.BackgroundWorker
          -> 7fa8420a72f8     System.Collections.Concurrent.ConcurrentQueue<Sentry.Protocol.Envelopes.Envelope>
          -> 7fa8420a7338     System.Collections.Concurrent.ConcurrentQueueSegment<Sentry.Protocol.Envelopes.Envelope>
          -> 7fa8420a7420     System.Collections.Concurrent.ConcurrentQueueSegment<Sentry.Protocol.Envelopes.Envelope>+Slot[]
          -> 7fa8663d47d0     Sentry.Protocol.Envelopes.Envelope
          -> 7fa8663d4668     System.Collections.Generic.List<Sentry.Protocol.Envelopes.EnvelopeItem>
          -> 7fa8663d4798     Sentry.Protocol.Envelopes.EnvelopeItem[]
          -> 7fa8663d4778     Sentry.Protocol.Envelopes.EnvelopeItem
          -> 7fa8663d4760     Sentry.Protocol.Envelopes.JsonSerializable
          -> 7fa866bde340     Sentry.SentryEvent
          -> 7fa866bdc618     Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException
          -> 7fa866bdc8f0     System.Collections.Generic.List<Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry>
          -> 7fa866bdc930     Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry[]
          -> 7fa866bdc910     Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry
          -> 7fa87a64b3a8     Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry
          -> 7fa87967c120     Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager
          -> 7fa8796723d0     <MyApplicationDbContext>

Issue Analytics

  • State:open
  • Created 2 months ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
danportscommented, Jul 28, 2023

It looks like I may be able to work around this problem to some degree on my end. When the TestJob throws a DbUpdateConcurrencyException, EF Core logs it, then Quartz.NET catches it and throws a JobExecutionException, which also gets logged. I believe the fact that both exceptions are logged back-to-back may be what triggers the memory leak in the runtime. When I modify TestJob to catch the DbUpdateConcurrencyException, wrap it in a JobExecutionException, and throw that, the memory leak seems to go away. It’s possible that wrapping the exception changes the code path in a way that avoids triggering the ConcurrentQueue memory leak. I have to admit I’m not completely satisfied with that answer (how exactly is that code path different??), but it is nice to have a workaround for now.

1reaction
bitsandfoxescommented, Jul 28, 2023

Huge thanks for the repro! We’ll look into this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How can I create a memory leak in Java?
This leads to objects building up in memory and possibly causing an OutofMemoryError exception.
Read more >
Performance Monitoring: Sentry SDK API Evolution
The objective of this document is to contextualize the evolution of the Performance Monitoring features in Sentry SDKs. We start with a summary...
Read more >
sentry-dotnet
Effort: Large Effort: Medium Effort: Small EntityFramework. Flaky Test Impact: Large ... SentryEvent memory leak with large exception object graphs.
Read more >
Patch 13.15 Bug Megathread : r/leagueoflegends
Massive memory leak that just makes the client hug more and more memory. Upvote 14
Read more >
@sentry/hub | Yarn - Package Manager
Object captured as exception with keys: prop1, prop2 Event `MouseEvent` ... fix(node): Convert debugging code to callbacks to fix memory leak in ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found