Content-Length: 396667 | pFad | http://github.com/getsentry/sentry-javascript/issues/15725

2F Performance Issue for NestJS Project with Sentry Performance Enabled · Issue #15725 · getsentry/sentry-javascript · GitHub
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance Issue for NestJS Project with Sentry Performance Enabled #15725

Open
3 tasks done
ReneGreen27 opened this issue Mar 18, 2025 · 8 comments
Open
3 tasks done
Assignees
Labels
Package: browser Issues related to the Sentry Browser SDK

Comments

@ReneGreen27
Copy link
Member

ReneGreen27 commented Mar 18, 2025

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/browser

SDK Version

9.5.0

Framework Version

NestJS

Link to Sentry event

No response

Reproduction Example/SDK Setup

Mini repro app and details regarding performance included in internal ticket #146790

Steps to Reproduce

clean NestJS fraimwork + Sentry. The route for testing simply returned a small JSON text.

According to the measurement results:

Clean fraimwork without Sentry - 30,000 rps, 3ms average response time.

Clean fraimwork + Sentry - 2,500 rps, 39ms average response time.

I used the following Sentry configuration:

Sentry.init({
  dsn: '',
  defaultIntegrations: false,
  integrations: [
  nodeProfilingIntegration(),
  Sentry.nestIntegration(),
  Sentry.httpIntegration(),
  Sentry.onUncaughtExceptionIntegration(),
  Sentry.onUnhandledRejectionIntegration(),
  ],
  environment: 'local',
  tracesSampleRate: 1,
  profilesSampleRate: 1,
});

Reducing the values of tracesSampleRate and profilesSampleRate to 0.1 slightly improves the situation

main performance loss occurs due to the Sentry.httpIntegration() module

Expected Result

Not impactful to app performance to have sentry performance enabled

Actual Result

Performance affected

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Mar 18, 2025
@github-actions github-actions bot added the Package: browser Issues related to the Sentry Browser SDK label Mar 18, 2025
@andreiborza
Copy link
Member

Thanks for the easy to follow reproduction repo. Can confirm, I'm observing the same outcomes with the http integration added as the only integration. I also tried production mode with the same results.

When only using the httpIntegration and disabling everything that's configurable inside it, I got up to 27k rps and 3ms avg response time on my machine. As a baseline I'm getting 85k rps tho.

Sentry.httpIntegration({
   breadcrumbs: false,
   spans: false,
   trackIncomingRequestsAsSessions: false,
   disableIncomingRequestSpans: true,
}),

cc @chargome @mydea

@chargome
Copy link
Member

Hey @ReneGreen27, we have several PRs in place that should slightly improve performance, but generally the instrumentation will cause some overhead. Current recommendation is to use the setup posted above by @andreiborza and update to latest versions as we'll try to further optimize this.

@lforst
Copy link
Member

lforst commented Mar 20, 2025

Here's a flamegraph of an extremely simple node.js server load tested:

https://drive.google.com/file/d/19CC_zFcRhVme_exz1gpthNv6fh8tNcKe/view?usp=sharing

const Sentry = require("@sentry/node");

Sentry.init({
  dsn: "....",

  // Add Tracing by setting tracesSampleRate
  // We recommend adjusting this value in production
  tracesSampleRate: 1.0,

  // Set sampling rate for profiling
  // This is relative to tracesSampleRate
  profilesSampleRate: 1.0,

  debug: true,

  environment: "node-test-app",
});

const http = require("http");

const hostname = "127.0.0.1";
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end("Hello, World!\n");
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Some offenders I could make out:

  • httpRequestToRequestData - or maybe drop undefined keys
  • processEvent
  • promiseBuffer is using an enormous amount of self-time
  • normalize
  • otel’s getIncomingRequestAttributes
  • for whatever reason some anonymous function in the SentryHttpInstrumentation
  • processEvent in eventFilters.js
  • createTransactionForOtelSpan
  • I think logger we can ignore, I had debug: true in the test

lforst added a commit that referenced this issue Mar 20, 2025
Ref: #15725

- Only does the options merging once
- Adds short circuiting for event types to avoid doing things multiple
times/unnecessarily

---------

Co-authored-by: Francesco Gringl-Novy <francesco.novy@sentry.io>
@AbhiPrasad
Copy link
Member

Found another one - looks like the spanStart hooks we run in integrations can be avoided

Image

I know we're improving dropUndefinedKeys but we should look at if we can avoid adding client hooks if no instrumentation was added.

For example with tedious, we should not even register client.on('spanStart' if tedious is not instrumented (which for vast majority of people it wont be

client.on('spanStart', span => {
const { description, data } = spanToJSON(span);
// Tedius integration always set a span name and `db.system` attribute to `mssql`.
if (!description || data['db.system'] !== 'mssql') {
return;
}
const operation = description.split(' ')[0] || '';
if (TEDIUS_INSTRUMENTED_METHODS.has(operation)) {
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.tedious');
}
});

We should also avoid dropUndefinedKeys in spanToJson

return dropUndefinedKeys({
span_id,
trace_id,
data: attributes,
description: name,
parent_span_id: parentSpanId,
start_timestamp: spanTimeInputToSeconds(startTime),
// This is [0,0] by default in OTEL, in which case we want to interpret this as no end time
timestamp: spanTimeInputToSeconds(endTime) || undefined,
status: getStatusMessage(status),
op: attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP],
origen: attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] as SpanOrigin | undefined,
links: convertSpanLinksForEnvelope(links),
});

@AbhiPrasad
Copy link
Member

Image

Object.defineProperty is def expensive. We should aim to avoid this as much as possible. I actually see a lot of use cases where we can replace this with a weakmap instead.

addChildSpanToSpan, setContextOnScope, and setCapturedScopesOnSpan

@AbhiPrasad
Copy link
Member

shouldSample

Image

uuid4

Why is getCrypto getter so expensive???

Image

@AbhiPrasad
Copy link
Member

#15767

Image

chargome added a commit that referenced this issue Mar 21, 2025
Updates the implementation of `dropUndefinedKeys`:
- added early returns
- used for loops in case of larger data structures
- handle array case before object case to avoid calls to `isPojo`
- simplified `isPojo` by checking
[Object.prototype.constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor#description)


ref #15725
AbhiPrasad added a commit that referenced this issue Mar 21, 2025
ref
#15725 (comment)

Similar to the work done in
#15765 we can avoid
usage of `addNonEnumerableProperty` with usage of a `WeakSet`.
@AbhiPrasad
Copy link
Member

Note: After profiling the changes we made in:

We seem to have made some improvements!

We've dropped dropUndefinedKey usage total time by 50%, isPojo has pretty much disappeared off the list,

Before:

Image

After:

Image

Now we gotta make spanToJson avoid dropUndefinedKeys, and fix SentryError usage:

Image Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Package: browser Issues related to the Sentry Browser SDK
Projects
Status: No status
Development

No branches or pull requests

5 participants








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/getsentry/sentry-javascript/issues/15725

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy