Skip to content

[feat] add maxLogcatEntries new config param#247

Merged
Manabu-GT merged 3 commits into
mainfrom
feat/issue-245
May 16, 2026
Merged

[feat] add maxLogcatEntries new config param#247
Manabu-GT merged 3 commits into
mainfrom
feat/issue-245

Conversation

@Manabu-GT
Copy link
Copy Markdown
Owner

@Manabu-GT Manabu-GT commented May 15, 2026

Summary by CodeRabbit

  • New Features

    • Introduced maxLogcatEntries configuration setting to control the Logcat buffer size; defaults to 300 entries.
    • Logcat buffer capacity can now be updated at runtime.
  • Tests

    • Added test coverage for configuration validation and buffer capacity adjustments.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

Warning

Rate limit exceeded

@Manabu-GT has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 56 minutes and 11 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 43d00639-75ac-4d8b-960e-926e4f5cea51

📥 Commits

Reviewing files that changed from the base of the PR and between e75cfa5 and 80aff34.

📒 Files selected for processing (1)
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt
📝 Walkthrough

Walkthrough

This PR adds configurable logcat buffer retention through a new maxLogcatEntries property. The setting propagates from DebugOverlay.Config through DebugOverlayDataRepository to LogcatDataSource, which manages buffer size using a refactored EvictingQueue that now supports dynamic capacity changes with element eviction.

Changes

Configurable logcat buffer capacity

Layer / File(s) Summary
Configuration property and defaults
debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/DebugOverlay.kt, debugoverlay-core/src/test/kotlin/com/ms/square/debugoverlay/DebugOverlayTest.kt
ConfigBuilder and Config gain maxLogcatEntries: Int property with @IntRange(from = 1) validation and a DEFAULT_MAX_LOGCAT_ENTRIES = 300 constant. Tests verify config initialization, runtime updates, and rejection of invalid (zero/negative) values. Test teardown resets the config to default.
EvictingQueue capacity mutability
debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/EvictingQueue.kt, debugoverlay-core/src/test/kotlin/com/ms/square/debugoverlay/internal/data/EvictingQueueTest.kt
Constructor changes from fixed capacity: Int to initialCapacity: Int parameter. capacity becomes a public synchronized property with a setter that evicts oldest elements when capacity shrinks. Test coverage shifts from constructor-time validation to dynamic grow/shrink behavior including eviction verification.
LogcatDataSource capacity initialization and mutation
debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt
Constructor accepts initialMaxEntries to initialize the underlying EvictingQueue. Fixed maxEntries constant becomes a mutable property whose getter/setter synchronizes with entries.capacity. Both streaming (logcat -T) and snapshot (logcat -t) commands use entries.capacity for the line count argument.
Repository and DebugOverlay configuration propagation
debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/DebugOverlayDataRepository.kt, debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/DebugOverlay.kt
DebugOverlayDataRepository constructor accepts initialLogcatMaxEntries and seeds LogcatDataSource with it. New setLogcatMaxEntries() method updates runtime capacity. DebugOverlay.install() passes config value to the repository on initialization; DebugOverlay.config setter propagates changes via setLogcatMaxEntries().

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Manabu-GT/DebugOverlay-Android#108: Concurrent changes to EvictingQueue capacity semantics (mutable setter with eviction) and corresponding test coverage.
  • Manabu-GT/DebugOverlay-Android#170: Overlapping modifications to LogcatDataSource constructor and maxEntries handling alongside logcat parsing refactoring.
  • Manabu-GT/DebugOverlay-Android#126: Downstream logcat pipeline updates in DebugOverlayDataRepository and LogcatDataSource to support new snapshot query behavior dependent on configurable max-entry capture.

Suggested labels

enhancement

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding a new maxLogcatEntries configuration parameter to DebugOverlay.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-245

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link
Copy Markdown

claude Bot commented May 15, 2026

Claude finished @Manabu-GT's task in 2m 12s —— View job


Claude PR Review

  • Read changed files (DebugOverlay, EvictingQueue, LogcatDataSource, DebugOverlayDataRepository, tests)
  • Analyze for bugs, code quality, performance, security
  • Post detailed review feedback (inline comments)

Summary

Nice feature — exposing maxLogcatEntries as a public knob is a clean addition, and routing it through a single source of truth (entries.capacity in LogcatDataSource) is the right design. The propagation path (ConfigsetLogcatMaxEntriesEvictingQueue.capacity) is straightforward and well-documented, including the subtle "running subprocess keeps its original -T N until panel reopen" semantics.

That said, there is one regression worth fixing before merge, plus a few smaller suggestions. Detailed comments inline.

Findings

🔴 Blocker — capacity validation lost (inline)
The previous EvictingQueue had require(capacity > 0) enforcing the contract still claimed in its KDoc. After this change both the constructor and the new setter silently accept 0 (and -N), and the next add(item) call crashes with NoSuchElementException because queue.size >= 0 is always true, triggering removeFirst() on an empty deque. The two tests that guarded this contract were also removed. @IntRange(from = 1) on Config.maxLogcatEntries is a lint hint only and does not enforce at runtime — so a misconfigured value crashes on the first emitted log line, far from the misconfiguration point. Fix: restore require(...) in the init block and in the capacity setter, restore the tests, and consider adding the same validation on the Config builder.

🟡 Minor — @IntRange doesn't enforce (inline)
Failing fast at configuration time is much friendlier than crashing deep in the producer flow. A require in the builder setter (or Config init) would surface bad values at the call site.

🟡 Minor — LogcatDataSource test value (inline)
The two new tests effectively check that a var property delegates to another var property. Per the project's testing guide, this leans toward "testing the framework" rather than your code. The more interesting behavior (which logcat -T N value is actually used on next subscription after a maxEntries change) is not covered. Consider injecting a process executor so the exec command can be asserted, or otherwise testing the subscription-restart semantics.

🟢 Nit — annotation consistency (inline)
Consider adding @IntRange(from = 1) to LogcatDataSource.maxEntries to mirror the public Config.maxLogcatEntries contract.

What's working well

  • KDoc on LogcatDataSource.maxEntries correctly explains the "subprocess keeps its original -T N until WhileSubscribed restarts" behavior — that subtlety would otherwise be confusing.
  • Single source of truth via entries.capacity avoids a separate maxEntries field drifting out of sync with the queue's actual capacity.
  • The added EvictingQueueTest cases for grow/shrink/grow-then-shrink are good and cover the new mutable-capacity semantics.
  • Synchronization is correct: EvictingQueue setter is @Synchronized, eviction during shrink happens under the same monitor as add/size/toList, so no torn reads.
  • DebugOverlayDataRepository.setLogcatMaxEntries is a thin pass-through — appropriate scope.

Security & performance

  • Security: No new untrusted input paths. The value flows from in-process API to in-process logcat -T N; the value is a constructor-provided Int, not user input.
  • Performance: Resizing is O(n) only when shrinking below current size, and only the difference is evicted. No issues.
    · feat/issue-245

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a39f1bc8e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +57 to +67
/**
* Maximum number of entries retained in the in-memory buffer and the count
* requested from logcat on next subscription. The currently-running subprocess
* keeps its original `-T N` arg until [WhileSubscribed][SharingStarted.WhileSubscribed]
* restarts the producer (panel reopen).
*/
var maxEntries: Int
get() = entries.capacity
set(value) {
entries.capacity = value
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thread-safety of maxEntries property

Reads/writes here delegate to entries.capacity, which is @Synchronized — so each individual get/set is atomic. Good.

However, the producerSignal flow at line 97 and captureLogcatOnce() at line 172 read entries.capacity without locking around the surrounding operation. That means:

  • setLogcatMaxEntries(N) called concurrently from DebugOverlay.config = ... (any thread, since config setter has no thread restriction) can change the value between the read and the exec() call. Not actually a problem here — whatever value is read is valid.

The KDoc accurately documents the "subprocess keeps its original -T N until panel reopen" behavior, which is the right call (interrupting an active stream just to apply a new cap would be disruptive). 👍

Minor nit: Consider adding @IntRange(from = 1) on the public maxEntries setter as well, to mirror the constraint advertised on Config.maxLogcatEntries. This is a lint hint only, but it's consistent.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/EvictingQueue.kt`:
- Around line 19-37: The capacity invariant must be enforced at runtime: in the
EvictingQueue<T> constructor validate initialCapacity >= 1 and throw an
IllegalArgumentException if not, and in the public var capacity setter validate
the new value >= 1 before assigning/evicting (throw IllegalArgumentException for
invalid values); keep the `@Synchronized` semantics and the existing eviction loop
(queue.removeFirst()) but only run it after the validated assignment in the
capacity setter so add()/removeFirst() cannot be driven by a zero/negative
capacity.

In
`@debugoverlay-core/src/test/kotlin/com/ms/square/debugoverlay/internal/data/EvictingQueueTest.kt`:
- Around line 129-176: Add tests asserting that EvictingQueue's constructor and
the capacity setter reject non-positive values: call the constructor
EvictingQueue<T>(0) and EvictingQueue<T>(-1) expecting IllegalArgumentException
(or the project's preferred exception), and set queue.capacity = 0 and
queue.capacity = -1 expecting the same; reference the EvictingQueue class, its
constructor, and the capacity property/ setter in your tests to ensure both
initialization and runtime changes validate capacity > 0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bf68df9e-6b77-4559-a984-c195ca738321

📥 Commits

Reviewing files that changed from the base of the PR and between 86db4ce and a39f1bc.

📒 Files selected for processing (7)
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/DebugOverlay.kt
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/DebugOverlayDataRepository.kt
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/EvictingQueue.kt
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt
  • debugoverlay-core/src/test/kotlin/com/ms/square/debugoverlay/DebugOverlayTest.kt
  • debugoverlay-core/src/test/kotlin/com/ms/square/debugoverlay/internal/data/EvictingQueueTest.kt
  • debugoverlay-core/src/test/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSourceTest.kt

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 15, 2026

Qodana for JVM

It seems all right 👌

No new problems were found according to the checks applied

💡 Qodana analysis was run in the pull request mode: only the changed files were checked
☁️ View the detailed Qodana report

Contact Qodana team

Contact us at qodana-support@jetbrains.com

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt (2)

99-99: ⚖️ Poor tradeoff

Static analysis: Runtime.exec() command construction.

The static analysis tool flags these Runtime.exec() calls because the command is built via string interpolation, which could be vulnerable to injection. However, in this case entries.capacity is internally controlled and validated by @IntRange(from = 1), making actual injection impossible.

Best practice would be to use ProcessBuilder with an explicit argument list to avoid shell interpretation entirely:

ProcessBuilder("logcat", "-v", "threadtime,printable,epoch", "-T", entries.capacity.toString())
  .start()

This would make the intent clearer and eliminate the static analysis warning, but given the current code is functionally safe, this can be deferred.

Also applies to: 174-174

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt`
at line 99, Replace the Runtime.getRuntime().exec(...) string-interpolated calls
in LogcatDataSource (the assignment that creates "process") with a
ProcessBuilder that passes each logcat argument as a separate element (e.g.
"logcat", "-v", "threadtime,printable,epoch", "-T", entries.capacity.toString())
and then call start(); update both occurrences (the one assigning val process at
the earlier creation and the second occurrence around line 174) so the command
is constructed without shell interpolation to satisfy static analysis and avoid
injection risks.

42-42: ⚡ Quick win

Add @IntRange(from = 1) annotation to the constructor parameter for consistency.

The maxEntries property already uses @IntRange(from = 1) on both getter and setter (lines 65, 67). Apply the same annotation to the initialMaxEntries constructor parameter to provide consistent IDE validation and documentation hints to callers.

Suggested fix
-  initialMaxEntries: Int,
+  `@IntRange`(from = 1) initialMaxEntries: Int,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt`
at line 42, Add the annotation `@IntRange`(from = 1) to the LogcatDataSource
constructor parameter initialMaxEntries to match the existing annotations on the
maxEntries getter/setter; ensure the import for IntRange
(androidx.annotation.IntRange) is present so the IDE and lint pick up the
validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt`:
- Line 99: Replace the Runtime.getRuntime().exec(...) string-interpolated calls
in LogcatDataSource (the assignment that creates "process") with a
ProcessBuilder that passes each logcat argument as a separate element (e.g.
"logcat", "-v", "threadtime,printable,epoch", "-T", entries.capacity.toString())
and then call start(); update both occurrences (the one assigning val process at
the earlier creation and the second occurrence around line 174) so the command
is constructed without shell interpolation to satisfy static analysis and avoid
injection risks.
- Line 42: Add the annotation `@IntRange`(from = 1) to the LogcatDataSource
constructor parameter initialMaxEntries to match the existing annotations on the
maxEntries getter/setter; ensure the import for IntRange
(androidx.annotation.IntRange) is present so the IDE and lint pick up the
validation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3b0a6178-bc6e-47ab-9f2f-87a697847a12

📥 Commits

Reviewing files that changed from the base of the PR and between a39f1bc and e75cfa5.

📒 Files selected for processing (3)
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/DebugOverlay.kt
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/data/source/LogcatDataSource.kt
  • debugoverlay-core/src/test/kotlin/com/ms/square/debugoverlay/DebugOverlayTest.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/DebugOverlay.kt

@Manabu-GT Manabu-GT merged commit 2bdfc2e into main May 16, 2026
5 checks passed
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.

1 participant