Conversation
- Added dedicated raw data SQL queries (getExportWebsiteEvents, getExportEventData, getExportSessionData) - Updated export API endpoint to output website_event.csv, session_data.csv, and event_data.csv - Ensured CSV headers are explicitly defined for empty data sets to match Cloud schema perfectly - Migrated export functionality UI to WebsiteData settings tab
|
@Yashh56 is attempting to deploy a commit to the Umami Software Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThe PR replaces aggregated export files with raw website-event, event-data, and session-data CSVs and adds a website-settings export workflow.
Confidence Score: 4/5The PR is not yet safe to merge because large exports still require the browser tab to materialize the complete ZIP before starting the download. The server now streams query and ZIP output, but the client awaits Files Needing Attention: src/app/(main)/websites/[websiteId]/settings/WebsiteExportForm.tsx
|
| Filename | Overview |
|---|---|
| src/app/(main)/websites/[websiteId]/settings/WebsiteExportForm.tsx | Adds token acquisition, error toasts, and download handling, but still buffers the complete ZIP in browser memory before saving it. |
| src/app/api/websites/[websiteId]/export/route.ts | Streams three raw CSV files into a ZIP and validates website-scoped download tokens. |
| src/app/api/websites/[websiteId]/export/token/route.ts | Issues stateless, short-lived JWTs bound to the authorized website. |
| src/queries/sql/export/getExportWebsiteEvents.ts | Adds raw website-event export queries with streaming ClickHouse output and precision-preserving PostgreSQL keyset pagination. |
| src/queries/sql/export/getExportEventData.ts | Adds raw event-data export queries for PostgreSQL and ClickHouse. |
| src/queries/sql/export/getExportSessionData.ts | Adds raw session-data export queries for PostgreSQL and ClickHouse. |
Sequence Diagram
sequenceDiagram
participant U as User
participant F as Export form
participant T as Token endpoint
participant E as Export endpoint
participant D as Database
U->>F: Select date range and export
F->>T: Request website-scoped token
T-->>F: Short-lived download token
F->>E: Fetch export with token
E->>D: Stream raw data
D-->>E: Query pages/result streams
E-->>F: Stream ZIP response
Note over F: Entire response is converted to a Blob
F-->>U: Start download after buffering completes
Reviews (16): Last reviewed commit: "fix: preserve microsecond precision for ..." | Re-trigger Greptile
- Refactored DB queries in export route to execute sequentially, allowing garbage collection of row arrays - Switched JSZip generator to output binary arraybuffer instead of nodebuffer/base64, reducing memory overhead by ~33% - Refactored frontend export logic to use native fetch and handle Blob streaming, bypassing useApi JSON parser limitations
- Wrapped export logic in try/catch - Display toast on failure so user is notified instead of silent failure - Moved modal onClose to the end of the success path
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
@greptileai, I disagree with this assessment. Let me address the three points:
|
|
Fair points on 2 and 3 — the preflight-then- On point 1, I want to be precise rather than just concede. The abort check IS wired in and IS correct in principle. The nuance is when it fires. The PostgreSQL path does: if (request.signal.aborted) break;
const data = await fetcher(websiteId, { ...filters, cursorDate, cursorId });The guard runs between iterations, not during the For typical export sizes this is probably acceptable, and the first request will self-terminate at the next iteration boundary. "The server instantly drops the cursor in milliseconds" slightly overstates what the code does; the more accurate description is "the first request terminates at the next batch boundary, which may be one 10 000-row page behind." That said, I agree the original "overlapping exports" framing was too alarming — it implied unbounded double-streaming, which isn't what happens. I'll remove that as a blocking concern. The architectural approach here is reasonable. |
…te duplicate DB workload
…x serverless cross-instance failures and enforce strict websiteId scoping
|
Hey @franciscao633, could you please review this PR and share your feedback when you get a chance? Thanks! |
- Switch from fire-and-forget anchor download to fetch-based download - Add error handling in the CSV generator to abort stream on DB/ClickHouse errors - Wrap ZIP assembly in try/catch to return 500 on pre-stream failures
What does this PR do?
This PR implements the highly requested "Data Export" feature for self-hosted instances of Umami, matching the functionality already provided in Umami Cloud. It transitions the export endpoint from generating aggregated metrics charts to outputting the raw data tables (
website_event.csv,event_data.csv, andsession_data.csv).Changes introduced:
getExportWebsiteEvents,getExportEventData,getExportSessionData) tosrc/queries/sql/exportwith support for both PostgreSQL and ClickHouse architectures.GET /api/websites/[websiteId]/exportto execute the raw queries and bundle them into a ZIP archive.WebsiteExportFormcomponent and moved the export button functionality into the Settings -> Data tab on the website dashboard.Resolves:
Closes: #4466
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.