Quiet the logs and capture the errors that were missing

- Activity page: "Delete all" empties the open tab (api/admin/logs/clear-logs,
  super admin only, logged under system)
- Stop logging every WebSocket connect
- Log unexpected API errors (safeErrorMessage -> logUnexpectedError), every
  failed bot job attempt and every job the queue lost
- Drop the cron jobs' console output; a failed model sync goes to the logs

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-25 05:11:31 +01:00
co-authored by Claude Opus 5.5
parent 3a9e57f682
commit e6c278198b
16 changed files with 245 additions and 47 deletions
@@ -0,0 +1,36 @@
import fetchApi from "@moduletrace/twui/utils/fetch/fetchApi";
import type { APIResponseObject } from "@moduletrace/bunext/types";
import type { ClearLogsRequest } from "@/src/schemas/log-schema";
type Params = {
category?: ClearLogsRequest["category"];
/**
* The tab's name, for the confirmation.
*/
title: string;
count?: number;
};
/**
* Deletes every log in the open tab, after asking.
*/
export default async function clearLogs({ category, title, count }: Params) {
const amount = typeof count == "number" ? `${count} ` : "";
const confirm_msg = category
? `Delete all ${amount}${title} logs? This cannot be undone.`
: `Delete all ${amount}logs? This cannot be undone.`;
if (!window.confirm(confirm_msg)) {
return { success: false, cancelled: true };
}
const res = await fetchApi<ClearLogsRequest, APIResponseObject<{ deleted: number }>>(
`/api/admin/logs/clear-logs`,
{ method: "POST", body: { category } },
);
return {
success: Boolean(res?.success),
msg: res?.success ? undefined : res?.msg || `Couldn't delete logs`,
};
}
@@ -78,6 +78,20 @@ export default function useLogsListInit(_props?: Props) {
setRes(undefined);
};
/**
* The tab was emptied: back to its first page, reloaded.
*/
const afterClear = () => {
setSelectedIds([]);
if (page > 1) {
setPage(1);
return;
}
setRes(undefined);
};
const all_selected =
Boolean(logs?.[0]) && selected_ids.length == logs?.length;
@@ -100,6 +114,7 @@ export default function useLogsListInit(_props?: Props) {
toggleSelectAll,
all_selected,
afterDelete,
afterClear,
active_log,
openLog,
log_modal_open,
@@ -0,0 +1,61 @@
import { Trash2 } from "lucide-react";
import Button from "@moduletrace/twui/layout/Button";
import Tag from "@moduletrace/twui/elements/Tag";
import Row from "@moduletrace/twui/layout/Row";
import Span from "@moduletrace/twui/layout/Span";
import useStatus from "@moduletrace/twui/hooks/useStatus";
import { LogCategoryFilters } from "../(data)/log-category-filters";
import type { LogCategoryValue } from "../(data)/log-category-styles";
import clearLogs from "../(functions)/clear-logs";
type Props = {
category?: LogCategoryValue;
count?: number;
afterClear: () => void;
};
/**
* Deletes every log in the open tab ("All" deletes every log).
*/
export default function ClearLogsButton({ category, count, afterClear }: Props) {
const { loading, setLoading, status, setStatus } = useStatus();
const title = LogCategoryFilters.find((filter) => filter.value == category)?.title || "All";
const clear_logs = async () => {
setStatus(undefined);
setLoading(true);
const res = await clearLogs({ category, title, count });
setLoading(false);
if (res.success) {
afterClear();
} else if (res.msg) {
setStatus({ error: true, msg: res.msg });
}
};
return (
<Row className="gap-2! flex-nowrap">
{status?.error && <Tag color="error">{status.msg}</Tag>}
<Button
title={category ? `Delete all ${title} logs` : "Delete all logs"}
variant="ghost"
color="error"
size="small"
loading={loading}
disabled={!count}
onClick={() => {
clear_logs();
}}
>
<Row className="gap-2! flex-nowrap">
<Trash2 size={15} />
<Span>{category ? `Delete all ${title}` : "Delete all"}</Span>
</Row>
</Button>
</Row>
);
}
@@ -4,6 +4,7 @@ import Row from "@moduletrace/twui/layout/Row";
import Span from "@moduletrace/twui/layout/Span";
import Stack from "@moduletrace/twui/layout/Stack";
import type useLogsListInit from "../(hooks)/use-logs-list-init";
import ClearLogsButton from "./clear-logs-button";
import DeleteLogsButton from "./delete-logs-button";
import LogCategoryFilter from "./log-category-filter";
@@ -18,6 +19,7 @@ export default function LogsToolbar({ init }: Props) {
selectCategory,
selected_ids,
afterDelete,
afterClear,
} = init;
return (
@@ -33,20 +35,27 @@ export default function LogsToolbar({ init }: Props) {
? `${count} log${count == 1 ? "" : "s"}`
: "--"}
</Span>
{selected_ids[0] ? (
<DeleteLogsButton
ids={selected_ids}
afterDelete={afterDelete}
title="Delete Selected Logs"
variant="outlined"
size="small"
>
<Row className="gap-2! flex-nowrap">
<Trash2 size={15} />
<Span>Delete selected ({selected_ids.length})</Span>
</Row>
</DeleteLogsButton>
) : null}
<Row className="gap-2! flex-nowrap">
{selected_ids[0] ? (
<DeleteLogsButton
ids={selected_ids}
afterDelete={afterDelete}
title="Delete Selected Logs"
variant="outlined"
size="small"
>
<Row className="gap-2! flex-nowrap">
<Trash2 size={15} />
<Span>Delete selected ({selected_ids.length})</Span>
</Row>
</DeleteLogsButton>
) : null}
<ClearLogsButton
category={category}
count={count}
afterClear={afterClear}
/>
</Row>
</Row>
</Stack>
</Paper>