Skip to content

feat(analysis): live stage progress + packet-based time estimate#567

Merged
NotYuSheng merged 3 commits into
mainfrom
feature/analysis-progress-and-eta
Jul 19, 2026
Merged

feat(analysis): live stage progress + packet-based time estimate#567
NotYuSheng merged 3 commits into
mainfrom
feature/analysis-progress-and-eta

Conversation

@NotYuSheng

@NotYuSheng NotYuSheng commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Problem

While a capture is analysing, the loading view showed:

  • a time estimate derived only from file size (~0.5 s/MB) that ignored the nDPI / Suricata / file-extraction choices made at upload, and
  • a progress bar driven by a local timer — it implied measured progress it didn't have.

What changed

Real stage progress

  • New in-memory AnalysisProgressService publishes per-stage progress from the pipeline. It's out-of-band because analyzeFile runs in one long transaction, so nothing it writes is visible to pollers until commit.
  • Exposed at GET /analysis/{id}/progress (200 with {stageIndex, totalStages, stage, percent}, 204 when nothing is tracked).
  • The bar now advances on true milestones (weighted by stage) and holds during opaque external stages (Suricata/nDPI/file-extraction expose no interior progress) — the striped animation conveys ongoing work without faking movement. Skipped stages are excluded, so "Stage 6 of 6" reflects the actual plan.

Packet-based time estimate

  • Analysis cost tracks packet count, not bytes (a small dense capture can take far longer than its size implies). Packet count is captured at upload via capinfos -M -c - (best-effort stdin stream, ~ms; null → size-based fallback) and stored on FileEntity.packetCount.
  • FileMapper computes the estimate from packet count, weighted per enabled stage, and it's surfaced on the file metadata the loading view already fetches.

Frontend

  • AnalysisLoadingView polls progress, shows "Stage X of Y: …", drives the bar off real percent, and notes which stages the estimate includes.

Testing

Verified end-to-end on the running stack with editcap.427fbe9e.pcap (13 MB, 21,364 packets):

  • Progress endpoint reported the real sequence 1/7 → 7/7, holding at 23% during Suricata and clearing to 204 on completion.
  • Old size-based estimate: 10s. New estimate: 82s all-stages, 32s with Suricata off (same file) — responds to the toggle.
  • capinfos count matched tshark's post-analysis count exactly (both 21364).
  • Calibrated against a clean offline run (GEO_FORCE_OFFLINE=true, so geo uses the bundled MMDB): per-stage logs showed Extract 55s dominant, geo just 1.5s; tuned estimate 69s vs 65s actual (~6% conservative).

Notes / follow-ups

  • Coefficients are fit to one clean offline run; recalibrate from the [1/7]…[7/7] logs across more captures over time.
  • On an internet-connected box, the geo stage hits ipinfo.io and adds latency the estimate can't predict — not the offline/air-gapped production target. The stage-progress bar stays accurate regardless.
  • No DB migration (reuses the existing packetCount column).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added live analysis progress updates, including the current stage and completion percentage.
    • Enhanced the analysis loading view with stage details and more accurate progress estimates.
    • Added estimated analysis time and enabled-stage information to file metadata.
    • Improved estimates using packet counts and analysis options when available.

The analysis loading view previously showed a size-only time estimate
(~0.5 s/MB) that ignored the nDPI / Suricata / file-extraction options,
and a progress bar driven by a local timer rather than real work.

Backend:
- Report live stage progress from the pipeline via an in-memory
  AnalysisProgressService (out-of-band, since analyzeFile runs in one
  long transaction), exposed at GET /analysis/{id}/progress. Bar advances
  on true milestones and holds during opaque external stages.
- Capture packet count at upload via `capinfos -M -c -` (best-effort,
  stdin stream, ~ms) and base the time estimate on packet count — cost
  tracks packets, not bytes — weighted per enabled stage. Falls back to
  the size-based formula when the count is unknown. Coefficients
  calibrated against a clean offline run (69s est vs 65s actual).

Frontend:
- AnalysisLoadingView polls progress, shows "Stage X of Y", drives the
  bar off real percent, and lists which stages the estimate includes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@NotYuSheng, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1bf4377f-e330-4bef-ba93-18027d000c9c

📥 Commits

Reviewing files that changed from the base of the PR and between bec3090 and 60f497e.

📒 Files selected for processing (4)
  • backend/src/main/java/com/tracepcap/analysis/service/AnalysisService.java
  • backend/src/main/java/com/tracepcap/file/service/FileServiceImpl.java
  • frontend/src/services/api/endpoints.ts
  • openapi/baseline.json
📝 Walkthrough

Walkthrough

Changes

Analysis progress and estimation

Layer / File(s) Summary
Packet-count estimation and metadata
backend/src/main/java/com/tracepcap/file/...
Upload and merge flows record packet counts, while metadata mapping computes stage-aware analysis duration estimates and applies effective Suricata enablement.
Weighted progress publication
backend/src/main/java/com/tracepcap/analysis/...
A thread-safe progress service stores per-file updates; AnalysisService publishes weighted milestones and clears them after completion or failure.
Progress endpoint and loading view
backend/src/main/java/com/tracepcap/analysis/controller/AnalysisController.java, frontend/src/pages/Analysis/AnalysisLoadingView.tsx, frontend/src/services/api/endpoints.ts
The backend exposes progress via GET /analysis/{fileId}/progress; the loading view polls it, displays stages, and falls back to estimate-based interpolation.

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

Sequence Diagram(s)

sequenceDiagram
  participant AnalysisService
  participant AnalysisProgressService
  participant AnalysisController
  participant AnalysisLoadingView
  AnalysisService->>AnalysisProgressService: Publish weighted stage progress
  AnalysisLoadingView->>AnalysisController: GET /analysis/{fileId}/progress
  AnalysisController->>AnalysisProgressService: Read latest progress
  AnalysisProgressService-->>AnalysisController: 200 progress or 204 no content
  AnalysisController-->>AnalysisLoadingView: AnalysisProgressResponse
  AnalysisLoadingView->>AnalysisLoadingView: Render stage or estimate fallback
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% 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 summarizes the two main changes: live analysis-stage progress and packet-based time estimates.
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.

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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces live analysis progress tracking and more accurate analysis time estimates. It adds an in-memory AnalysisProgressService to track progress through weighted pipeline stages, exposes a new progress endpoint, and integrates it into the frontend's loading view. Additionally, it utilizes capinfos to count packets up front for a packet-count-based time estimate. The review feedback highlights critical issues where calling readAllBytes() before process.waitFor() can block threads indefinitely and bypass timeouts. It also identifies a potential memory leak in AnalysisService if temp file creation fails, and suggests adding defensive guard clauses to prevent index out of bounds errors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

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

Actionable comments posted: 3

🤖 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 `@backend/src/main/java/com/tracepcap/file/service/FileServiceImpl.java`:
- Around line 91-101: The synchronous countPackets call currently runs inside
the transactional uploadFile and mergeFiles flows, holding database and request
resources during capinfos execution. Move packet-count computation outside the
transaction or schedule it asynchronously after commit, while preserving the
metadata update and using a shorter best-effort timeout so packet counting
cannot block these transactions for the full analysis timeout.
- Around line 417-486: Update both countPackets overloads to execute capinfos
against a file path, writing MultipartFile content to a temporary file and
cleaning it up afterward instead of piping stdin. In each method, drain stdout
and stderr concurrently while enforcing the 60-second process timeout, then
parse stdout only after successful completion; forcibly terminate timed-out
processes and preserve the existing best-effort null behavior.

In `@frontend/src/services/api/endpoints.ts`:
- Around line 10-12: Update the section comment above ANALYSIS_SUMMARY,
ANALYSIS_PROGRESS, and PROTOCOL_STATS to remove the claim that the analysis
endpoints are not implemented in the backend, while leaving the endpoint
definitions unchanged.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: 880ad3b4-e0de-4131-9a81-64c69f122070

📥 Commits

Reviewing files that changed from the base of the PR and between 4007904 and bec3090.

📒 Files selected for processing (9)
  • backend/src/main/java/com/tracepcap/analysis/controller/AnalysisController.java
  • backend/src/main/java/com/tracepcap/analysis/dto/AnalysisProgressResponse.java
  • backend/src/main/java/com/tracepcap/analysis/service/AnalysisProgressService.java
  • backend/src/main/java/com/tracepcap/analysis/service/AnalysisService.java
  • backend/src/main/java/com/tracepcap/file/dto/FileMetadataDto.java
  • backend/src/main/java/com/tracepcap/file/mapper/FileMapper.java
  • backend/src/main/java/com/tracepcap/file/service/FileServiceImpl.java
  • frontend/src/pages/Analysis/AnalysisLoadingView.tsx
  • frontend/src/services/api/endpoints.ts

Comment thread frontend/src/services/api/endpoints.ts Outdated
NotYuSheng and others added 2 commits July 19, 2026 15:50
Address PR review + schema-drift workflow:
- countPackets: drain capinfos stdout on a daemon thread so a hung
  process can't block past waitFor's timeout; use UTF-8 (both overloads).
- reportStage: guard out-of-range stage index instead of crashing.
- Clear live progress on early-failure paths that skip the inner finally
  (e.g. createTempFile throwing after the first stage report).
- Regenerate openapi/baseline.json for the new /analysis/{id}/progress
  endpoint + estimatedAnalysisSeconds field (additive only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Shorten the best-effort capinfos packet-count timeout 60s -> 15s so it
  can't hold a request thread / DB connection long inside the upload/merge
  transaction (CodeRabbit). capinfos -c only scans record headers; on
  timeout we fall back to the size-based estimate.
- Drop the stale "Not yet implemented in backend" comment on the analysis
  endpoints — summary/progress/protocols are all implemented.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@NotYuSheng
NotYuSheng merged commit 75ce6ee into main Jul 19, 2026
6 checks passed
@NotYuSheng
NotYuSheng deleted the feature/analysis-progress-and-eta branch July 19, 2026 07:59
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