Skip to content

ADFA-934: Build output timestamp - #1586

Open
dara-abijo-adfa wants to merge 9 commits into
stagefrom
ADFA-934-build-output-timestamp
Open

ADFA-934: Build output timestamp#1586
dara-abijo-adfa wants to merge 9 commits into
stagefrom
ADFA-934-build-output-timestamp

Conversation

@dara-abijo-adfa

Copy link
Copy Markdown
Contributor

Add time stamps, time deltas, and line numbers to the Build Output

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0bd508f4-bb95-4e34-bab0-a9b618bbd2d0

📥 Commits

Reviewing files that changed from the base of the PR and between 3dc82ea and 895601e.

📒 Files selected for processing (2)
  • app/src/main/java/com/itsaky/androidide/fragments/output/BuildOutputFragment.kt
  • resources/src/main/res/values/strings.xml
🚧 Files skipped from review as they are similar to previous changes (2)
  • resources/src/main/res/values/strings.xml
  • app/src/main/java/com/itsaky/androidide/fragments/output/BuildOutputFragment.kt

📝 Walkthrough
  • Added build output display options: per-line line numbers, timestamps, and elapsed-time (time delta) prefixes.
  • Updated the log filter bar UI with new toggles (line numbers, timestamps, deltas) and localized labels, including correct state restore and live updates.
  • Improved line filtering to operate on the displayed form of each line (respecting timestamp/delta hiding) while preserving prefix formatting and newline behavior.
  • Enhanced streamed build output timing/formatting by prefixing output lines with build timing information (including during the “run tasks” phase).
  • Hardened editor/session updates against races by using generation invalidation so cleared output and live filtering can’t be overwritten by stale streaming batches.
  • Added/updated unit tests covering prefix formatting, toggle-driven display changes, newline edge cases, query matching against displayed text, and long-build (>99 min) prefix stripping.
  • Risk: Expanded LogFilterBarController constructor and BuildOutputViewModel API surface—future callers may need updates if they rely on previous constructor/signature behavior.
  • Risk: Concurrency/timing-prefix parsing and rendering paths should receive regression testing, especially around rapid output clearing and long-running builds.

Walkthrough

Build output now includes timing prefixes, supports independent line-number, timestamp, and delta visibility controls, filters displayed text accordingly, and prevents stale asynchronous batches from being appended after output is cleared.

Changes

Build output controls

Layer / File(s) Summary
Display formatting and filtering contract
app/src/main/java/com/itsaky/androidide/viewmodel/BuildOutputViewModel.kt, app/src/test/java/com/itsaky/androidide/viewmodel/BuildOutputFilterTest.kt
Adds display-toggle state, prefix-aware formatting, filtering against displayed text, newline handling, and tests for hidden prefixes and edge cases.
Timed build output formatting
app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt
Tracks build and step timing, prefixes streamed non-blank output, preserves blank lines and trailing newlines, and retains build status handling.
Filter controls and generation-safe rendering
app/src/main/java/com/itsaky/androidide/fragments/output/BuildOutputFragment.kt, app/src/main/java/com/itsaky/androidide/fragments/output/LogFilterBarController.kt, app/src/main/res/layout/layout_log_filter_bar.xml, resources/src/main/res/values/strings.xml
Adds option chips and callbacks, wires display toggles into filtering and editor rendering, and rejects stale batches after clearOutput().

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BuildEventListener
  participant BuildOutputViewModel
  participant BuildOutputFragment
  participant LogFilterBarController
  BuildEventListener->>BuildOutputViewModel: Format output with timing prefixes
  BuildEventListener->>BuildOutputFragment: Append build output
  LogFilterBarController->>BuildOutputFragment: Report display-toggle changes
  BuildOutputFragment->>BuildOutputViewModel: Filter with timestamp and delta visibility
  BuildOutputViewModel-->>BuildOutputFragment: Return displayed editor text
Loading

Possibly related PRs

Suggested reviewers: fryanpan, jatezzz, hal-eisen-adfa, jomen-adfa, itsaky-adfa

Poem

A bunny watched the build lines hop,
With clocks and deltas in each crop.
Chips now hide what eyes don’t need,
Stale batches stop at clearing speed.
The editor stays neat and bright—
Hop, hop, review, all right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is related to the main change, but only highlights timestamps while the PR also adds deltas and line numbers.
Description check ✅ Passed The description accurately matches the changes by describing timestamps, deltas, and line numbers in Build Output.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ADFA-934-build-output-timestamp

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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🧹 Nitpick comments (2)
app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt (1)

183-197: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding unit test coverage for the new timing/formatting logic.

formatOutput contains non-trivial timing math (total/step deltas, blank-line/trailing-newline preservation) but no accompanying test file was included in this PR. As per coding guidelines, new/changed non-UI logic should target at least 50% line and branch coverage.

Based on learnings and coding guidelines: "Use unit tests for non-UI logic, cover error and edge paths, and target at least 50% line and branch coverage for new or changed non-UI code." Want me to draft a JUnit test class for formatOutput/resetBuildTimers?

🤖 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 `@app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt`
around lines 183 - 197, Add unit tests for the non-UI formatting logic in
formatOutput and timer behavior in resetBuildTimers. Cover total and step timing
prefixes, multi-line output, blank lines, inputs with and without trailing
newlines, and timer reset behavior, targeting at least 50% line and branch
coverage.

Source: Coding guidelines

app/src/main/java/com/itsaky/androidide/fragments/output/LogFilterBarController.kt (1)

69-92: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider wiring long-press tooltip help for the new toggle chips.

The three new chips (line numbers, timestamps, deltas) are new interactive elements with no evident long-press help wiring (e.g. via the TooltipTag-based mechanism used elsewhere, such as editor?.tag = TooltipTag.PROJECT_BUILD_OUTPUT in BuildOutputFragment.kt).

Based on coding guidelines: "New interactive elements and screens must provide long-press contextual help through idetooltips and the three-tier tooltip system." Please confirm whether an existing mechanism (not shown in this diff) already covers these chips, or whether tooltip tagging should be added here.

🤖 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
`@app/src/main/java/com/itsaky/androidide/fragments/output/LogFilterBarController.kt`
around lines 69 - 92, Verify whether chipLineNumbers, chipTimestamps, and
chipDeltas already receive long-press help through an existing tooltip
mechanism; if not, add the appropriate TooltipTag-based three-tier tooltip
wiring for each chip in the controller’s setup flow, using distinct contextual
tags and preserving the existing visibility, checked-state, and listener
behavior.

Source: Coding guidelines

🤖 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
`@app/src/main/java/com/itsaky/androidide/fragments/output/BuildOutputFragment.kt`:
- Around line 88-99: Separate the generation used for session-file persistence
from editorContentGeneration. Add a persistence generation that is incremented
only by clearOutput(), capture and propagate both generations through
processLogs and flushToEditor, and use the persistence generation to gate
buildOutputViewModel.append(text) while retaining editorContentGeneration for
visible appendBatch calls. Ensure filter and display-toggle re-renders cannot
discard drained output.

In
`@app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt`:
- Around line 79-104: Update prepareBuild and onProgressEvent to capture the
result of checkActivity(...) in a local activity instance and return when it is
null, then use that captured instance throughout each method instead of
re-reading the throwing activity accessor. Preserve the existing build-status,
timer, output, and progress behavior while eliminating the
time-of-check/time-of-use race.
- Around line 45-46: Update build elapsed-time tracking in
EditorBuildEventListener to use SystemClock.elapsedRealtime() for
buildStartTimeMs, lastOutputTimeMs, and all totalDeltaMs/stepDeltaMs
calculations, including the referenced later sections. Preserve
System.currentTimeMillis()/Instant only for displayed wall-clock timestamps,
ensuring duration values remain monotonic and non-negative.

In `@app/src/main/java/com/itsaky/androidide/viewmodel/BuildOutputViewModel.kt`:
- Around line 202-227: Update PREFIX_TIME_FORMAT used by formatLinePrefix to
apply an explicit ASCII DecimalStyle, ensuring the [HH:mm:ss.SSS] timestamp
always emits ASCII digits regardless of the device locale. Do not rely solely on
Locale.US; preserve the existing timestamp pattern and formatting behavior.

---

Nitpick comments:
In
`@app/src/main/java/com/itsaky/androidide/fragments/output/LogFilterBarController.kt`:
- Around line 69-92: Verify whether chipLineNumbers, chipTimestamps, and
chipDeltas already receive long-press help through an existing tooltip
mechanism; if not, add the appropriate TooltipTag-based three-tier tooltip
wiring for each chip in the controller’s setup flow, using distinct contextual
tags and preserving the existing visibility, checked-state, and listener
behavior.

In
`@app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt`:
- Around line 183-197: Add unit tests for the non-UI formatting logic in
formatOutput and timer behavior in resetBuildTimers. Cover total and step timing
prefixes, multi-line output, blank lines, inputs with and without trailing
newlines, and timer reset behavior, targeting at least 50% line and branch
coverage.
🪄 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 Plus

Run ID: d78f0844-2eb6-4697-a35e-eed2f14c5974

📥 Commits

Reviewing files that changed from the base of the PR and between 60a9b77 and 3dc82ea.

📒 Files selected for processing (7)
  • app/src/main/java/com/itsaky/androidide/fragments/output/BuildOutputFragment.kt
  • app/src/main/java/com/itsaky/androidide/fragments/output/LogFilterBarController.kt
  • app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt
  • app/src/main/java/com/itsaky/androidide/viewmodel/BuildOutputViewModel.kt
  • app/src/main/res/layout/layout_log_filter_bar.xml
  • app/src/test/java/com/itsaky/androidide/viewmodel/BuildOutputFilterTest.kt
  • resources/src/main/res/values/strings.xml

Comment on lines +45 to +46
private var buildStartTimeMs: Long = System.currentTimeMillis()
private var lastOutputTimeMs: Long = buildStartTimeMs

@coderabbitai coderabbitai Bot Jul 27, 2026

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate file and nearby symbols"
fd -a 'EditorBuildEventListener\.kt$|BuildOutputViewModel\.kt$' . || true
echo

if [ -f app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt ]; then
  echo "File size"
  wc -l app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt
  echo
  echo "Outline"
  ast-grep outline app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt || true
  echo
  echo "Relevant lines 1-240"
  cat -n app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt | sed -n '1,240p'
fi

echo
echo "Search BuildOutputViewModel and PREFIX_REGEX usage"
rg -n "BuildOutputViewModel|class BuildOutputViewModel|PREFIX_REGEX|timestamp|delta|elapsed|currentTimeMillis|elapsedRealtime" app/src/main/java || true

echo
echo "Search relevant ViewModel files"
fd -a 'BuildOutputViewModel|.*BuildOutput.*' app/src/main/java || true

Repository: appdevforall/CodeOnTheGo

Length of output: 1937


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate file and nearby symbols"
fd -a 'EditorBuildEventListener\.kt$|BuildOutputViewModel\.kt$' . || true
echo

if [ -f app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt ]; then
  echo "File size"
  wc -l app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt
  echo
  echo "Outline"
  ast-grep outline app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt || true
  echo
  echo "Relevant lines 1-240"
  cat -n app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt | sed -n '1,240p'
fi

echo
echo "Search BuildOutputViewModel and PREFIX_REGEX usage"
rg -n "BuildOutputViewModel|class BuildOutputViewModel|PREFIX_REGEX|timestamp|delta|elapsed|currentTimeMillis|elapsedRealtime" app/src/main/java || true

echo
echo "Search relevant ViewModel files"
fd -a 'BuildOutputViewModel|.*BuildOutput.*' app/src/main/java || true

Repository: appdevforall/CodeOnTheGo

Length of output: 1937


🏁 Script executed:

#!/bin/bash
set -u

echo "Current directory:"
pwd
echo

echo "Top-level entries:"
{ ls -la || true; } | head -100
echo

echo "Attempt locate repository files directly:"
for f in \
  app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt \
  app/src/main/java/com/itsaky/androidide/viewmodels/BuildOutputViewModel.kt \
  app/src/main/java/com/itsaky/androidide/ui/BuildOutputViewModel.kt
do
  if [ -f "$f" ]; then
    echo "FOUND $f"
    wc -l "$f"
    echo
  else
    echo "MISSING $f"
  fi
done
echo

echo "Search files by name in accessible tree:"
find . -type f \( -name 'EditorBuildEventListener.kt' -o -name 'BuildOutputViewModel.kt' -o -name '*BuildOutput*.kt' \) -print 2>/dev/null | head -50 || true

Repository: appdevforall/CodeOnTheGo

Length of output: 1937


🌐 Web query:

appdevforall AndroidIDE EditorBuildEventListener BuildOutputViewModel PREFIX_REGEX

💡 Result:

Code on the Go (formerly known as and based on the AndroidIDE project) is an open-source, offline-first integrated development environment maintained by the nonprofit organization App Dev for All [1][2][3]. The specific components you mentioned—EditorBuildEventListener, BuildOutputViewModel, and PREFIX_REGEX—are internal classes and constants associated with the build system and UI state management within the Code on the Go (and original AndroidIDE) codebase [4][5]. 1. EditorBuildEventListener: This class typically serves as a listener interface or implementation responsible for handling build events within the editor environment. It allows the IDE to respond to various stages of the Gradle build process (e.g., build started, failed, or successful) to update the UI or provide feedback to the developer [4][6]. 2. BuildOutputViewModel: This is a ViewModel component designed to manage and expose the build output data (logs, progress, status) to the UI layer in an Android architecture-compliant manner [5]. It holds the state of the build process, ensuring that build logs persist during configuration changes and are correctly observed by the UI [5]. 3. PREFIX_REGEX: In the context of build output parsing, this constant is commonly used as a regular expression to identify, filter, or categorize specific lines in Gradle build logs (e.g., matching common prefixes like "E:", "W:", or specific task names) so that the IDE can parse them for errors, warnings, or progress tracking [4]. These components are part of the internal architectural surface of the IDE and are not typically documented as public APIs for end-users, though they are accessible to those contributing to the open-source repository or developing custom plugins for the IDE [2][6]. You can find the source code for these components in the public GitHub repository at github.com/appdevforall/CodeOnTheGo [7][2].

Citations:


🌐 Web query:

site:github.com/appdevforall/CodeOnTheGo EditorBuildEventListener BuildOutputViewModel

💡 Result:

EditorBuildEventListener and BuildOutputViewModel are internal components associated with the CodeOnTheGo (CoGo) project, an Android IDE for mobile development [1][2]. These components are part of the application's infrastructure for managing build processes and UI feedback [1][3][4]. Specifically: - EditorBuildEventListener: This component is involved in monitoring build-related events [1]. It is often used to trigger actions in response to build lifecycle states, such as refreshing symbol indexes or updating source file metadata once a build operation completes [1][5]. - BuildOutputViewModel: This component serves as the ViewModel for the build output display within the application [3][4]. It manages the state and presentation of build logs, errors, and progress, ensuring that information from the build process is correctly rendered for the user [6]. These classes are not part of the standard Unity engine or mainstream Android SDK libraries but are custom implementations within the CodeOnTheGo codebase [1][2]. Developers working on or contributing to this project often interact with these types of classes when modifying how build feedback is processed, indexed, or displayed [5][2].

Citations:


🌐 Web query:

github appdevforall CodeOnTheGo "EditorBuildEventListener.kt" "System.currentTimeMillis()" "elapsedRealtime"

💡 Result:

In Android development, particularly within projects like CodeOnTheGo and AndroidIDE, EditorBuildEventListener.kt is a class responsible for listening to build lifecycle events (such as build preparation, success, failure, and output) and updating the IDE's UI or state accordingly [1][2]. When implementing time-based logic within Android applications, there is a critical distinction between System.currentTimeMillis and SystemClock.elapsedRealtime [3][4]: 1. System.currentTimeMillis: This provides the "wall" clock time (UTC), representing milliseconds since the Unix epoch [3][4]. Because this clock can be changed by the user, the network, or daylight savings adjustments, it is susceptible to unpredictable "jumps" [3][4]. It should be used exclusively for displaying dates or times to users [3][4]. 2. SystemClock.elapsedRealtime: This provides the time since the device booted, including deep sleep intervals [3][4]. It is guaranteed to be monotonic, meaning it only moves forward and is unaffected by user changes or network time synchronization [3][4]. For measuring elapsed durations (e.g., timing a build process or a code operation), SystemClock.elapsedRealtime is the authoritative and recommended API, as it ensures accuracy regardless of system time changes [3][5]. Using System.currentTimeMillis for duration measurement is considered an anti-pattern that can lead to incorrect calculations if the device time is adjusted while the operation is running [3][5]. In the context of the referenced IDE projects, EditorBuildEventListener.kt has historically required careful management of Activity lifecycle states to prevent crashes (e.g., when trying to update UI after an activity has been destroyed) [1][6][7]. Developers should ensure that any timed operations or asynchronous callbacks initiated by the build process verify the accessibility of the associated activity before attempting UI updates [1].

Citations:


Use a monotonic clock for build elapsed-time deltas.

buildStartTimeMs/lastOutputTimeMs are wall-clock values, so NTP or manual time changes during a build can make the derived totalDeltaMs/stepDeltaMs negative. This can produce negative or garbage durations and break regex parsing that expects unsigned timestamps. Keep System.currentTimeMillis()/Instant for the displayed wall-clock timestamp; use SystemClock.elapsedRealtime() for delta math. Also applies to lines 106-109 and 183-197.

🤖 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 `@app/src/main/java/com/itsaky/androidide/handlers/EditorBuildEventListener.kt`
around lines 45 - 46, Update build elapsed-time tracking in
EditorBuildEventListener to use SystemClock.elapsedRealtime() for
buildStartTimeMs, lastOutputTimeMs, and all totalDeltaMs/stepDeltaMs
calculations, including the referenced later sections. Preserve
System.currentTimeMillis()/Instant only for displayed wall-clock timestamps,
ensuring duration values remain monotonic and non-negative.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Claude thinks this is only minor

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.

@hal-eisen-adfa, agreed — this should be Minor, not Major.

The issue is limited to incorrect displayed deltas if the device wall clock changes during a build; it does not affect build execution or cause data loss. The elapsedRealtime() adjustment remains a worthwhile small correctness improvement, but it is not release-blocking.

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