voonhous commented on code in PR #13152:
URL: https://github.com/apache/hudi/pull/13152#discussion_r3563380805


##########
rfc/rfc-94/rfc-94.md:
##########
@@ -0,0 +1,545 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+# RFC-94: Hudi Timeline User Interface (UI)
+
+## Proposers
+
+- @voonhous
+
+## Approvers
+
+- @danny0405
+- @rahil-c
+- @yihua
+
+## Status
+
+JIRA: [HUDI-9315](https://issues.apache.org/jira/browse/HUDI-9315)
+
+## Abstract
+
+Hudi Timeline metadata is stored as timestamped files representing state 
transitions of actions like `commit`,
+`deltacommit` and `compaction`. These files are accessible via the CLI or a 
file explorer, but it's hard to visualize
+concurrent actions, spot missing transitions, or tell how long each step took. 
Debugging timeline issues by reading
+filenames is tedious.
+
+This RFC proposes a UI-based timeline visualization tool that parses these 
metadata files, groups related actions, and
+renders them in a time-ordered, interactive view. Users can track the 
lifecycle of each operation, see concurrency
+patterns, and spot anomalies or long-running tasks. The implementation extends 
`hudi-timeline-service` with new `/v2/`
+REST APIs and a static HTML + JavaScript frontend powered by 
[vis-timeline](https://github.com/visjs/vis-timeline),
+served via Javalin's built-in static file serving with zero new Java 
compile-time dependencies.
+
+## Background
+
+Today, we rely on the CLI or direct filesystem inspection to understand 
timeline state through metadata files. These
+files represent different actions (e.g., `deltacommit`, `compaction`) and 
their lifecycle states (`requested`,
+`inflight`, `completed`), encoded in file names like:
+
+```shell
+20250409102118815.deltacommit.inflight
+20250409102118815.deltacommit.requested
+20250409102118815_20250409102124339.deltacommit
+20250409102121593.compaction.inflight
+20250409102121593.compaction.requested
+20250409102121593_20250409102122232.commit
+20250409102124581.deltacommit.inflight
+20250409102124581.deltacommit.requested
+20250409102124581_20250409102125667.deltacommit
+20250409102124612.compaction.inflight
+20250409102124612.compaction.requested
+20250409102124612_20250409102124892.commit
+20250409102127348.deltacommit.inflight
+20250409102127348.deltacommit.requested
+20250409102127348_20250409102128481.deltacommit
+20250409102127500.compaction.inflight
+20250409102127500.compaction.requested
+20250409102127500_20250409102127721.commit
+```
+
+This works, but has a few problems:
+
+1. No visibility into concurrency
+    - Multiple actions (e.g., `deltacommit` and `compaction`) often run 
concurrently.
+    - The CLI doesn't help correlate or visualize overlapping operations.
+2. Lack of temporal context
+    - Timestamps are embedded in filenames but are hard to compare visually - 
year, month and day can be quickly
+      determined, but minutes and seconds are harder to parse.
+    - No easy way to tell how long an action took or whether it's stalling 
unless you manually calculate the difference
+      between requested and completion time.
+3. Hard to spot inconsistencies or missing states
+    - An `inflight` compaction without a corresponding `commit` can indicate a 
starved/stuck compaction, which usually
+      blocks archiving/cleaning.
+    - These gaps are easy to miss when scanning filenames.
+
+On top of that, all timeline files are now stored as Avro binaries. Inspecting 
their contents requires custom Avro
+readers to convert the binaries to JSON.
+
+## Scope
+
+This RFC covers visualization of metadata available in Hudi tables. All 
features are **READ-ONLY** - there is no support
+for starting or spawning jobs that mutate a Hudi table.
+
+Alongside the timeline, the UI surfaces two additional read-only metadata 
views: the table's configuration
+(`hoodie.properties`) and its schema-change history.
+
+The following are **out of scope**:
+
+- **Archived timeline:** Only the active timeline is rendered. Loading 
instants from LSM-based archive files is left for
+  future work.
+- **Metadata table overlay:** The metadata table's own timeline is not shown 
alongside the main table timeline.
+- **Write/mutation operations:** The UI cannot trigger compactions, 
clustering, or any write action.
+- **Authentication/authorization:** No access control is added. The timeline 
server is assumed to run in a trusted
+  network, same as today.
+
+  **Threat model:** The UI does not widen the timeline server's exposure 
surface. The `/v2/` endpoints read the same
+  active-timeline and filesystem metadata that the existing `/v1/` REST APIs 
already serve, on the same network
+  interface (the server binds to all interfaces on the driver/standalone 
host). The UI is also opt-in and off by default
+  (`--enable-ui`). Operators on untrusted networks should front the server 
with a reverse proxy or restrict it to a
+  private interface / localhost via network policy.
+
+## Implementation
+
+Keeping the implementation lightweight is a priority - we should add as few 
dependencies as possible. Changes go into
+the existing `hudi-timeline-service` module, which contains a Javalin 
web-application that caches filesystem metadata of
+a Hudi table for job executors during tagging/writing.
+
+The first cut runs the UI on the Timeline Server in **STANDALONE** mode (see 
[Configuration](#configuration)) and is
+self-contained within `hudi-timeline-service`. Enabling the UI on the 
**EMBEDDED** timeline server inside a Spark
+driver, together with a Spark UI tab, requires cross-module wiring 
(`hudi-client-common`, `hudi-spark-client`); it is
+designed below but deferred to a follow-up to keep the initial PR small and 
focused. The standalone UI lands first; the
+embedded/Spark linking lands next.
+
+The Hudi Timeline UI has two parts: the frontend and backend.
+
+### Architecture
+
+The timeline server can run standalone or embedded inside a Spark driver. In 
embedded mode, a tab in the Spark UI links
+directly to the Hudi Timeline UI. The embedded mode and Spark UI tab (right 
side of the diagram below) are a planned
+follow-up; the first cut is standalone-only.
+
+```mermaid
+graph LR
+    Browser["Browser"]
+
+    subgraph Driver["Standalone / Spark Driver"]
+        subgraph TimelineServer["Javalin (Timeline Server)"]
+            Static["/ui + assets at root\n(HTML, JS, CSS)"]
+            API["/v2/hoodie/view/* - TimelineHandler"]
+            FSVM["FileSystemViewManager"]
+            Meta["HoodieTimeline / MetaClient"]
+
+            API --> FSVM --> Meta
+        end
+
+        subgraph SparkUI["Spark UI (:4040) - embedded mode (follow-up)"]
+            direction TB
+            SparkUIPad[ ] ~~~ Tabs["[Jobs] [Stages] ... [Hudi Timeline]"]
+        end
+
+        style SparkUIPad fill:none,stroke:none,color:none
+
+        Tabs -- "link" --> Static
+    end
+
+    Browser -- "HTTP" --> Static
+    Browser -- "HTTP" --> API
+    Browser -. "HTTP\n(embedded mode)" .-> SparkUI
+```
+
+There are two categories of requests:
+
+1. **Static file requests** - Javalin serves HTML, JavaScript, and CSS files 
from the classpath
+   (`src/main/resources/public/`) at the server root; `UiHandler` serves 
`index.html` at `/ui`. No server-side
+   rendering or template engine is needed.
+2. **REST API requests** (`/v2/hoodie/view/*`) - `TimelineHandler` processes 
these requests, reading timeline data from
+   the `FileSystemViewManager` (and a per-basepath `HoodieTableMetaClient` for 
table config/schema), returning JSON.
+
+### Frontend
+
+The frontend is static HTML pages with vanilla JavaScript, similar to the 
Spark Web UI. Javalin's built-in static file
+serving handles files from the classpath - no template engine (e.g., 
Thymeleaf) is needed and no new Java compile-time
+dependencies are added.
+
+No frontend build pipeline (npm, webpack, vite) is needed. Contributing to the 
UI requires only a text editor. The only
+external library is vis-timeline for timeline rendering.

Review Comment:
   Good catch -- fixed. Bootstrap 5 and renderjson are both vendored under 
`lib/` alongside vis-timeline. Updated the File Structure tree and Dependency 
Impact to list all three:
   
   | Library | Size | License |
   |---|---|---|
   | vis-timeline | ~575KB | Apache-2.0 OR MIT |
   | Bootstrap 5 | ~305KB | MIT |
   | renderjson | ~11KB | ISC |
   
   Also corrected the footprint -- the ~300KB was vis-timeline-only; actual 
total is ~890KB. Added a LICENSE/NOTICE bullet: all three are Category A, so 
each needs a `This product bundles ...` stanza in the top-level `LICENSE` and 
the `hudi-timeline-server-bundle` LICENSE. No `NOTICE` changes needed -- 
MIT/ISC don't require them and vis-timeline is taken under its MIT option.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to