Skip to content

perf(core): [Logs and Metrics Enable Flags 11] Avoid unused Logs worker thread - #5952

Open
adinauer wants to merge 5 commits into
feat/warn-legacy-logs-springfrom
perf/logs-batch-thread-first-use
Open

adinauer wants to merge 5 commits into
feat/warn-legacy-logs-springfrom
perf/logs-batch-thread-first-use

Conversation

@adinauer

@adinauer adinauer commented Aug 13, 2026 •

Copy link
Copy Markdown
Member

PR Stack (Logs and Metrics Enable Flags)


📜 Description

Tracks whether LoggerBatchProcessor has accepted its first Log item. Before that point, empty flushes and restart closes do not schedule processor work. Normal close still closes the executor directly.

After the first accepted item, batching, flushing, and restart-close behavior remain unchanged. Items rejected because of shutdown or queue capacity do not mark the processor as used.

💡 Motivation and Context

The aggregate Logs enable flag has been removed, so every SDK client now owns a logger batch processor. Without this guard, lifecycle flushes—particularly Android background callbacks—can start a worker thread even when the application never captures a Log.

💚 How did you test it?

  • ./gradlew :sentry:test :sentry-android-core:testReleaseUnitTest
  • ./gradlew spotlessApply apiDump
  • Added core tests for construction, empty flush, close, restart close, rejected items, and behavior after first use
  • Added an Android background callback test before first use

📝 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

Remove the aggregate Metrics enable flag.

#skip-changelog

⚠️ Merge this PR using a merge commit (not squash). Only the collection branch is squash-merged into main.

Track whether the logger batch processor has accepted an item and skip empty flush and restart-close scheduling until then. This prevents SDK initialization and Android background callbacks from starting a worker thread when Logs are unused.

Co-Authored-By: Claude <noreply@anthropic.com>
@sentry

sentry Bot commented Aug 13, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-android Build Distribution Settings

@github-actions

github-actions Bot commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 314.02 ms 352.98 ms 38.96 ms
Size 0 B 0 B 0 B

Baseline results on branch: feat/warn-legacy-logs-spring

Startup times

Revision Plain With Sentry Diff
c2e4325 310.06 ms 363.22 ms 53.16 ms

App size

Revision Plain With Sentry Diff
c2e4325 0 B 0 B 0 B

Previous results on branch: perf/logs-batch-thread-first-use

Startup times

Revision Plain With Sentry Diff
31a945a 307.74 ms 351.86 ms 44.11 ms

App size

Revision Plain With Sentry Diff
31a945a 0 B 0 B 0 B

Comment thread sentry/src/main/java/io/sentry/logger/LoggerBatchProcessor.java

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This seems like a bugfix unrelated to the stack. Can we make this an independent PR?

@adinauer

Copy link
Copy Markdown
Member Author

This seems like a bugfix unrelated to the stack. Can we make this an independent PR?

Before this PR stack we used noop instances to avoid the thread creation. Since we can't rely on enableLogs / enableMetrics anymore this PR is needed. It's not a separate bugfix but rather an optimization that should be part of the PR stack.

@@ -114,6 +116,9 @@ private void maybeSchedule(boolean immediately) {

@Override
public void flush(long timeoutMillis) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: A race condition between add() and flush() can cause flush() to return early without waiting for a queued item, breaking its synchronous contract.
Severity: MEDIUM

Suggested Fix

To fix the race condition, set the hasAcceptedItem flag to true before adding the event to the queue with queue.offer(logEvent). Alternatively, use a lock or another synchronization primitive to protect the critical section between adding to the queue and setting the flag.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: sentry/src/main/java/io/sentry/logger/LoggerBatchProcessor.java#L118

Potential issue: A race condition exists between the `add()` and `flush()` methods in
`LoggerBatchProcessor`. A thread can add an item to the `queue` via
`queue.offer(logEvent)`, but before it sets the `hasAcceptedItem` flag to `true`,
another thread can call `flush()`. The `flush()` method checks `if (!hasAcceptedItem)`
and returns immediately, failing to wait for the newly queued item. This violates the
implicit contract of `flush()`, which is expected to block until all pending items are
processed, especially during client shutdown when `SentryClient.close()` relies on it to
ensure all logs are sent.

Also affects:

  • sentry/src/main/java/io/sentry/logger/LoggerBatchProcessor.java:88~89

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants