Skip to content

Run specific code outside of Sentry domain/hub/scope #7031

Closed
@nwalters512

Description

@nwalters512

Problem Statement

My web server maintains a pool of long-lived resources. These resources are created on application startup and used in some of the requests. However, if we detect that a resource is unhealthy during a request, we'll remove it and create a new one.

These resources each maintain a long-lived socket. As best as I can tell, Sentry's hub/scope mechanisms maintain a reference to the incoming HTTP request and associate it with this socket. If the request object is very large (e.g. it contains a lot of data on res.locals), this data will be retained effectively forever, even once the request finishes. This manifests as a memory leak.

I'm not entirely sure of how Sentry's internals work, but this appears to be related to Sentry's usage of Node domains to track request context across async operations. If I take a heap snapshot at runtime, I can see that the response is ultimately retained in a domain's members, and if I disable Sentry completely, the response is no longer retained in any domain.

I've created a small repo to illustrate this issue: https://github.com/nwalters512/sentry-domain-memory-leak. Follow these steps to see the issue:

  • Clone the repo and run yarn install
  • Run docker pull ubuntu
  • Run node --inspect index.js
  • Attach a debugger and look at the memory consumption; it should be ~10MB
  • Make a request to http://localhost:80/ in your browser.
  • Look at the memory consumption in the debugger; it should be about 300MB and should stay that way even after manually triggering a garbage collection
  • Stop the server, remove all Sentry-related code from index.js, and repeat the above steps. Note that memory consumption should fall back to ~10MB either immediately or after triggering a garbage collection.

I'm writing this as a feature request because I have a relatively clear idea of what I want from Sentry: the ability to run a piece of code completely outside of Sentry's domains/hubs/scopes. AFAICT from the docs, there's not currently a way to do this.

Solution Brainstorm

From an API standpoint, something like this would be nice:

await Sentry.disableScope(async () => {
  await makeLongLivedResource();
});

Not knowing much about Sentry's internals, I can't really guess as to exactly how this could be implemented.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions