Skip to content

feat(timeline-ui): [HUDI-9315] Add Hudi Timeline UI#13147

Open
voonhous wants to merge 1 commit into
apache:masterfrom
voonhous:hudi-ui
Open

feat(timeline-ui): [HUDI-9315] Add Hudi Timeline UI#13147
voonhous wants to merge 1 commit into
apache:masterfrom
voonhous:hudi-ui

Conversation

@voonhous

@voonhous voonhous commented Apr 15, 2025

Copy link
Copy Markdown
Member

Describe the issue this Pull Request addresses

Visualizing the timeline via console and finder/explorer is often challenging as files are often sorted via naming convention. With completion time thrown into completed instants, it makes grouping of instants even harder when looking at it via console.

Hence, a timeline visualizer can oftentimes make one able to understand the timeline better, especially for concurrent/long writes.

The timeline-ui page is accessible via http://timeline_server__host:timeline_server__port/ui after starting the timeline service.

Summary and Changelog

Attached below is an example of how it looks like for now, functionalities are there, but it is a little rough:

Main page

The main page allow users to input the the table paths and the timeline will be visualised.

image

Hovering over instants

Hovering over the instant bars will show you additional details like duration an action took.

image

Selecting an instant

Since commit details are saved to the filesystem as avro binaries, the commit information are not easily readable. Selecting the commit/deltacommit will return the details in json format.

image

Clean range

Upon selection of a clean commit/plan that uses KEEP_LATEST_COMMITS, clean range will be displayed.

image

Configs page

Table configurations are displayed in the Table Config tab:

image

Schema History

Schema related changelogs are also displayed (only when schema operations are done using hoodie.schema.on.read.enable=true under the Shcema History tab.

image

The schema changelog can also be expanded to see what column changed at which schemacommit.

image

Impact

Describe any public API or user-facing feature change or any performance impact.

Added 4 API endpoints on the /v2/hoodie/view path:

  1. timeline/instants/all?basepath={basepath} - all instants (v2 format)
  2. timeline/instant?basepath={basepath}&instant={instant}&instantaction={action}&instantstate={state} - instant details
  3. table/config?basepath={basepath} - table configuration
  4. table/schema/history?basepath={basepath}&limit={limit} - schema evolution history

The UI is served at /ui (previously redirected to /index.html).

Risk Level

None

Documentation Update

We do not have any documentations for timeline service, hence, i suppose no documentation changes are required.

Contributor's checklist

  • Read through contributor's guide
  • Change Logs and Impact were stated clearly
  • Adequate tests were added if applicable
  • CI passed

@github-actions github-actions Bot added the size:L PR with lines of changes in (300, 1000] label Apr 15, 2025
@danny0405

Copy link
Copy Markdown
Contributor

@voonhous Nice feature, do you think it deserves a RFC then?

@voonhous

voonhous commented Apr 16, 2025

Copy link
Copy Markdown
Member Author

Sure, will create a new RFC for this.

Note: Calling out that this feature is not to be confused with RFC-05:
https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=130027233

@hudi-bot hudi-bot mentioned this pull request Dec 9, 2025
@github-actions github-actions Bot added size:XL PR with lines of changes > 1000 and removed size:L PR with lines of changes in (300, 1000] labels Mar 27, 2026
@voonhous voonhous force-pushed the hudi-ui branch 2 times, most recently from 18a627f to d6feff9 Compare April 9, 2026 06:53
@voonhous voonhous changed the title [HUDI-9315] Add Hudi Timeline UI to aid debugging feat: [HUDI-9315] Add Hudi Timeline UI Apr 9, 2026
@voonhous voonhous changed the title feat: [HUDI-9315] Add Hudi Timeline UI feat(timeline-ui): [HUDI-9315] Add Hudi Timeline UI Apr 9, 2026

@yihua yihua 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 review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Style & Readability Review — Code is generally clean and readable. One naming convention suggestion: the variable suffix "Obj" is non-standard in Java.

@yihua yihua 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 review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for contributing! The timeline UI is a nice addition for debugging and understanding Hudi timelines. A few functional issues to address: the hardcoded InstantComparatorV1 in getInstantDetails could cause lookup failures on V2-layout tables, the broad catch (Exception) silently swallows errors returning null with HTTP 200, and Integer.parseInt on the user-provided limit param can throw uncaught exceptions. See inline comments for details.

@nsivabalan

Copy link
Copy Markdown
Contributor

This is pretty amazing @voonhous 👏

@hudi-agent hudi-agent 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 review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

The new change in this update is a single pom.xml addition that excludes **/resources/public/lib/** from the Apache RAT license-header check, with a comment noting that the bundled third-party UI libraries (Bootstrap, renderjson, vis-timeline) ship with their own licenses. The change looks appropriate and well-scoped. The prior inline findings (hardcoded InstantComparatorV1 in getInstantDetails, broad catch (Exception) returning null, unsafe Integer.parseInt on the limit param, default metadata config flip in buildFileSystemViewManager, ungated v2 API endpoints, and per-request HoodieTableMetaClient construction) do not appear to have been addressed in this update — please take another look at those when you get a chance. Please take a look at any inline comments, and this should be ready for a Hudi committer or PMC member to take it from here.

@hudi-agent hudi-agent 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 review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

CodeRabbit Walkthrough: This PR introduces a web-based timeline explorer UI for the Hudi Timeline Service. It adds v2 API endpoints to expose timeline and instant data as DTOs, implements backend handlers to serve timeline/config/schema information, and provides a complete frontend with Bootstrap/vis-timeline for interactive timeline visualization, filtering, and instant detail inspection.

Sequence Diagram (CodeRabbit):

sequenceDiagram
    participant Browser as Browser / UI
    participant TimelineService as Timeline Service
    participant FileSystemView as FileSystem View<br/>(Metadata Cache)
    participant HoodieTimeline as HoodieTimeline

    Browser->>TimelineService: GET /v2/hoodie/view/timeline/instants
    TimelineService->>FileSystemView: getTimeline()
    FileSystemView->>HoodieTimeline: getInstantsAsStream()
    HoodieTimeline-->>FileSystemView: stream of HoodieInstant
    FileSystemView-->>TimelineService: HoodieTimeline
    TimelineService->>TimelineService: TimelineDTO.fromTimeline()
    TimelineService-->>Browser: TimelineDTO (JSON)

    Browser->>Browser: vis.Timeline render<br/>with instants

    Browser->>TimelineService: GET /v2/hoodie/view/instants/details?instant=...&action=COMMIT
    TimelineService->>FileSystemView: getTimeline()
    FileSystemView->>HoodieTimeline: readCommitted() or readPending()
    HoodieTimeline-->>FileSystemView: SpecificRecordBase (metadata/plan)
    FileSystemView-->>TimelineService: Avro record
    TimelineService->>TimelineService: JsonUtils.convert to Map
    TimelineService-->>Browser: Detail JSON

    Browser->>Browser: Render detail card<br/>+ compute clean range<br/>if KEEP_LATEST_COMMITS
Loading

CodeRabbit: hudi-agent#24 (review)

Comment thread hudi-timeline-service/src/main/resources/public/index.html
Comment thread pom.xml

@hudi-agent hudi-agent 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 review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! This PR adds a Timeline UI feature and supporting v2 endpoints (timeline, instant details, table config, schema history) to the timeline service. Prior review rounds have already flagged the key issues (parameter validation, error handling, script-fallback race, license exclusion). No new critical correctness issues flagged from this automated pass — a Hudi committer or PMC member can take it from here for a final review. A few naming and consistency suggestions below — two hard-coded URL strings that should be constants, a fully-qualified return type caused by a class name collision, and a minor variable naming nit.

cc @yihua

@voonhous voonhous added this to the release-1.3.0 milestone Jun 7, 2026
@voonhous voonhous force-pushed the hudi-ui branch 2 times, most recently from 708ced4 to f8b116f Compare June 12, 2026 08:42
Add a read-only Timeline UI, served by hudi-timeline-service, for visualizing a
Hudi table's active timeline.

Backend:
- New v2 endpoints (timeline, instant details, table config, schema history) in
  TimelineHandler, registered via registerTimelineV2API() and gated behind the
  --enable-ui flag.
- Per-basepath HoodieTableMetaClient caching; layout-aware InstantGenerator when
  reading instant details; request-parameter validation (400 for missing or
  malformed params, bounded schema-history limit) and proper error responses
  instead of returning null.

Frontend:
- Static HTML/JS/CSS (vis-timeline, Bootstrap, renderjson) served from bundled
  assets only, with no external/CDN calls.

Integration:
- Embedded-mode startup and a Spark UI "Hudi Timeline" tab.
- Exclude bundled UI libraries from the apache-rat check.
@hudi-bot

Copy link
Copy Markdown
Collaborator

CI report:

Bot commands @hudi-bot supports the following commands:
  • @hudi-bot run azure re-run the last Azure build

@hudi-agent hudi-agent 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 review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for iterating on this! At this point the timeline UI plumbing — v2 DTOs, the gated /v2 routes, the new /ui static handler, instant-detail/table-config/schema-history endpoints, and the metaClient cache — looks consistent with how it's exercised by the bundled timeline.js. I traced the timeline source (viewManager.getFileSystemView(basePath).getTimeline() resolves to visibleActiveTimeline from IncrementalTimelineSyncFileSystemView, which is filterCompletedAndCompactionInstants() — so completed clean/rollback/restore/savepoint actions plus all compaction states are visible to the UI as expected), the completion-time lookup path in getInstantFileName, the ConcurrentHashMap.computeIfAbsent semantics for the metaClient cache, and the Thread.currentThread().join() shutdown pattern, and didn't surface anything new beyond what prior rounds already flagged and the author addressed. No correctness issues found. A few style/readability suggestions in the inline comments. Please take a look, and this should be ready for a Hudi committer or PMC member to take it from here. A few naming and simplification suggestions below.

cc @yihua

}

public static HoodieInstant toInstant(InstantDTO dto, InstantGenerator factory) {
if (null == dto) {

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.

🤖 nit: could you rename factory to instantGenerator here? The same type is referred to as instantGenerator in TimelineDTOV2.toTimeline and in TimelineHandler, so calling it factory in this one spot breaks the naming convention and makes readers wonder whether it's a different object.

- AI-generated; verify before applying. React 👍/👎 to flag quality.


app.get(RemoteHoodieTableFileSystemView.SCHEMA_HISTORY_V2_URL, new ViewHandler(ctx -> {
metricsRegistry.add("SCHEMA_HISTORY", 1);
int limit;

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.

🤖 nit: the limit parsing and validation is done inline here, while every other query param in this class is extracted to a private helper (getInstantParam, getBasePathParam, etc.). It might be worth pulling this out to something like getLimitParam(Context ctx) to keep the pattern consistent and make the lambda body easier to scan.

- AI-generated; verify before applying. React 👍/👎 to flag quality.


Map<String, Object> result = new HashMap<>();

// Get current schema

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.

🤖 nit: throws Exception is broader than needed here — every checked exception in the method body is caught internally (either swallowed or rethrown as HoodieException/BadRequestResponse). Could you narrow this to throws IOException or remove the throws clause entirely? As-is, callers see throws Exception and have to decide what to catch unnecessarily.

- AI-generated; verify before applying. React 👍/👎 to flag quality.

@voonhous voonhous closed this Jun 14, 2026
@voonhous voonhous reopened this Jun 14, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 3.50877% with 165 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.94%. Comparing base (1f20fd4) to head (d1f48a2).
⚠️ Report is 11 commits behind head on master.

Files with missing lines Patch % Lines
...udi/timeline/service/handlers/TimelineHandler.java 2.12% 92 Missing ⚠️
...g/apache/hudi/timeline/service/RequestHandler.java 0.00% 30 Missing and 1 partial ⚠️
...org/apache/hudi/timeline/service/ui/UiHandler.java 0.00% 13 Missing ⚠️
.../hudi/common/table/timeline/dto/v2/InstantDTO.java 0.00% 12 Missing ⚠️
.../apache/hudi/timeline/service/TimelineService.java 0.00% 7 Missing and 2 partials ⚠️
...di/common/table/timeline/dto/v2/TimelineDTOV2.java 0.00% 8 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #13147      +/-   ##
============================================
- Coverage     68.25%   67.94%   -0.31%     
- Complexity    29477    30365     +888     
============================================
  Files          2542     2565      +23     
  Lines        142541   147754    +5213     
  Branches      17798    18973    +1175     
============================================
+ Hits          97293   100395    +3102     
- Misses        37242    39061    +1819     
- Partials       8006     8298     +292     
Flag Coverage Δ
common-and-other-modules 44.85% <3.50%> (+0.07%) ⬆️
hadoop-mr-java-client 45.00% <3.50%> (+0.26%) ⬆️
spark-client-hadoop-common 48.27% <3.50%> (+0.21%) ⬆️
spark-java-tests 48.68% <3.50%> (-0.08%) ⬇️
spark-scala-tests 44.80% <3.50%> (-0.02%) ⬇️
utilities 37.67% <3.50%> (+0.44%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...on/table/view/RemoteHoodieTableFileSystemView.java 82.19% <100.00%> (+0.33%) ⬆️
...di/common/table/timeline/dto/v2/TimelineDTOV2.java 0.00% <0.00%> (ø)
.../apache/hudi/timeline/service/TimelineService.java 45.74% <0.00%> (-3.69%) ⬇️
.../hudi/common/table/timeline/dto/v2/InstantDTO.java 0.00% <0.00%> (ø)
...org/apache/hudi/timeline/service/ui/UiHandler.java 0.00% <0.00%> (ø)
...g/apache/hudi/timeline/service/RequestHandler.java 82.73% <0.00%> (-5.78%) ⬇️
...udi/timeline/service/handlers/TimelineHandler.java 4.04% <2.12%> (-35.96%) ⬇️

... and 72 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

size:XL PR with lines of changes > 1000

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants