Skip to content

fix(clientreport): Stop deserializing discarded logs (JAVA-662) - #5835

Open
runningcode wants to merge 3 commits into
mainfrom
no/java-662-cpu-busy-loop
Open

fix(clientreport): Stop deserializing discarded logs (JAVA-662)#5835
runningcode wants to merge 3 commits into
mainfrom
no/java-662-cpu-busy-loop

Conversation

@runningcode

@runningcode runningcode commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

📜 Description

TL;DR we can skip deserializing the envelope payload just to read getItems().size() by adding a new SentryEnvelopeItemHeader.getItemCount() and using it. The serialization was reported by a customer(JAVA-662) to cause a busy CPU loop.

Full version:
ClientReportRecorder.recordLostEnvelopeItem counted discarded log and metric items by fully deserializing the envelope payload just to read getItems().size(). The item count is already carried in the envelope item header, so this change reads it from the header instead of deserializing. Byte counts still come from the raw getData() bytes.

  • Added SentryEnvelopeItemHeader.getItemCount().
  • Log/metric branches of recordLostEnvelopeItem now use the header count; when it is absent (legacy/foreign envelopes) they fall back to 1 and never deserialize.
  • Transactions are untouched — span counts are not stored in the header and that path isn't implicated.

💡 Motivation and Context

This was reported by a customer to cause a busy CPU loop and this is a quick and safe optimization.

Fixes GH-5830
Fixes JAVA-662

💚 How did you test it?

Unit tests in ClientReportTest

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

None.

@linear-code

linear-code Bot commented Jul 24, 2026

Copy link
Copy Markdown

JAVA-662

@sentry

sentry Bot commented Jul 24, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.50.0 (1) release

⚙️ sentry-android Build Distribution Settings

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 322.30 ms 345.35 ms 23.05 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
6b019b7 319.84 ms 333.15 ms 13.31 ms
c3ee041 310.64 ms 361.90 ms 51.26 ms
d501a7e 348.06 ms 431.42 ms 83.36 ms
3998a95 415.94 ms 478.54 ms 62.60 ms
ed33deb 343.30 ms 362.41 ms 19.10 ms
5b1a06b 310.56 ms 362.79 ms 52.22 ms
91bb874 310.68 ms 359.24 ms 48.56 ms
0ee65e9 317.37 ms 366.50 ms 49.13 ms
6edfca2 305.52 ms 432.78 ms 127.26 ms
5e269de 292.83 ms 379.12 ms 86.29 ms

App size

Revision Plain With Sentry Diff
6b019b7 0 B 0 B 0 B
c3ee041 0 B 0 B 0 B
d501a7e 0 B 0 B 0 B
3998a95 1.58 MiB 2.10 MiB 532.96 KiB
ed33deb 1.58 MiB 2.13 MiB 559.52 KiB
5b1a06b 0 B 0 B 0 B
91bb874 1.58 MiB 2.13 MiB 559.07 KiB
0ee65e9 0 B 0 B 0 B
6edfca2 1.58 MiB 2.13 MiB 559.07 KiB
5e269de 0 B 0 B 0 B

Previous results on branch: no/java-662-cpu-busy-loop

Startup times

Revision Plain With Sentry Diff
33f1054 298.98 ms 374.02 ms 75.04 ms

App size

Revision Plain With Sentry Diff
33f1054 0 B 0 B 0 B

@runningcode
runningcode force-pushed the no/java-662-cpu-busy-loop branch from d69d8d4 to bd9a1d8 Compare July 29, 2026 14:47
runningcode and others added 3 commits July 29, 2026 16:55
ClientReportRecorder counted discarded log and metric items by fully
deserializing the envelope payload just to read its size. On the discard
path this runs continuously under sustained rate limiting, and the JSON
reader's error-tolerant recovery throws an exception per token, pinning
CPU cores in a busy-loop (fillInStackTrace dominated the profile).

The item count is already stored in the envelope item header, so read it
from there instead of deserializing. Byte counts still come from the raw
data. This makes the discard path O(1) and allocation/exception-free.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The two tests asserting that restoring counts from an attached client
report does not re-fire onDiscard were named for their setup rather than
for what actually differed between them, which made the pair read as an
accidental duplicate.

Name each for its entry point and share the setup and verifications, so
it is clear the property is being pinned for both recordLostEnvelope and
recordLostEnvelopeItem.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@runningcode
runningcode force-pushed the no/java-662-cpu-busy-loop branch from bd9a1d8 to 8554314 Compare July 29, 2026 14:57
@runningcode
runningcode marked this pull request as ready for review July 29, 2026 14:59
@runningcode runningcode added the sanity-check PR needs a lightweight review for obvious issues label Jul 29, 2026

@0xadam-brown 0xadam-brown left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sanity-check PR needs a lightweight review for obvious issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CPU busy-loop in ClientReportRecorder.recordLostEnvelope → SentryEnvelopeItem.getLogs() when envelopes are discarded under rate limiting (8.49.0)

2 participants