From f1e4c001a9735b4b9c4ac84c552fda8eeb9f3f8e Mon Sep 17 00:00:00 2001 From: Apostol Apostolov Date: Wed, 27 May 2026 23:04:49 +0300 Subject: [PATCH] feat(logs): add clean history button (#2799) Integrated into release/v3.8.6 --- src/app/(dashboard)/dashboard/logs/page.tsx | 81 ++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/src/app/(dashboard)/dashboard/logs/page.tsx b/src/app/(dashboard)/dashboard/logs/page.tsx index b26cb92c26..79105e13c5 100644 --- a/src/app/(dashboard)/dashboard/logs/page.tsx +++ b/src/app/(dashboard)/dashboard/logs/page.tsx @@ -2,7 +2,7 @@ import { useState, useRef, useEffect } from "react"; import { useSearchParams } from "next/navigation"; -import { RequestLoggerV2, ProxyLogger, SegmentedControl } from "@/shared/components"; +import { ConfirmModal, RequestLoggerV2, ProxyLogger, SegmentedControl } from "@/shared/components"; import ConsoleLogViewer from "@/shared/components/ConsoleLogViewer"; import EmailPrivacyToggle from "@/shared/components/EmailPrivacyToggle"; import ActiveRequestsPanel from "@/shared/components/ActiveRequestsPanel"; @@ -31,6 +31,10 @@ export default function LogsPage() { ); const [showExport, setShowExport] = useState(false); const [exporting, setExporting] = useState(false); + const [showCleanHistory, setShowCleanHistory] = useState(false); + const [cleaningHistory, setCleaningHistory] = useState(false); + const [cleanHistoryStatus, setCleanHistoryStatus] = useState(null); + const [requestLogKey, setRequestLogKey] = useState(0); const dropdownRef = useRef(null); const t = useTranslations("logs"); @@ -73,6 +77,36 @@ export default function LogsPage() { } } + async function handleCleanHistory() { + setCleaningHistory(true); + setShowCleanHistory(false); + setCleanHistoryStatus(null); + try { + const res = await fetch("/api/settings/purge-logs", { method: "POST" }); + const data = await res.json().catch(() => null); + + if (!res.ok) { + throw new Error(data?.error || "Failed to clean log history."); + } + + const deleted = typeof data?.deleted === "number" ? data.deleted : 0; + const deletedArtifacts = typeof data?.deletedArtifacts === "number" ? data.deletedArtifacts : 0; + setRequestLogKey((key) => key + 1); + setCleanHistoryStatus( + deleted || deletedArtifacts + ? `Cleaned ${deleted} log entr${deleted === 1 ? "y" : "ies"} and ${deletedArtifacts} artifact${ + deletedArtifacts === 1 ? "" : "s" + }.` + : "No expired log history needed cleanup." + ); + } catch (err) { + console.error("Failed to clean log history", err); + setCleanHistoryStatus(err instanceof Error ? err.message : "Failed to clean log history."); + } finally { + setCleaningHistory(false); + } + } + return (
@@ -90,6 +124,32 @@ export default function LogsPage() {
+ +
+ {cleanHistoryStatus && ( +
+ {cleanHistoryStatus} +
+ )} + {activeTab === "request-logs" && (
- +
)} {activeTab === "proxy-logs" && } {activeTab === "audit-logs" && } {activeTab === "console" && } + + setShowCleanHistory(false)} + onConfirm={handleCleanHistory} + title="Clean log history?" + message="This clears expired log history and prunes related artifacts using the current retention policy. The live page will refresh after cleanup." + confirmText="Clean history" + cancelText="Cancel" + loading={cleaningHistory} + />
); }