import { DataTable } from "@/src/components/table/data-table"; import { type LangfuseColumnDef } from "@/src/components/table/types"; import { api } from "@/src/utils/api"; import { safeExtract } from "@/src/utils/map-utils"; import { useQueryParams, withDefault, NumberParam } from "use-query-params"; import { IOTableCell } from "@/src/components/ui/IOTableCell"; import { Avatar, AvatarFallback, AvatarImage, } from "@/src/components/ui/avatar"; import { cn } from "@/src/utils/tailwind"; import { useRowHeightLocalStorage } from "@/src/components/table/data-table-row-height-switch"; import { DataTableToolbar } from "@/src/components/table/data-table-toolbar"; import { type RouterOutputs } from "@/src/utils/api"; import { SettingsTableCard } from "@/src/components/layouts/settings-table-card"; import { BatchExportTableButton } from "@/src/components/BatchExportTableButton"; import { BatchExportTableName } from "@langfuse/shared"; // Both endpoints return the same shape type AuditLogRow = RouterOutputs["auditLogs"]["all"]["data"][number]; type AuditLogsTableProps = | { scope: "project"; projectId: string } | { scope: "organization"; orgId: string }; export function AuditLogsTable(props: AuditLogsTableProps) { const [paginationState, setPaginationState] = useQueryParams({ pageIndex: withDefault(NumberParam, 0), pageSize: withDefault(NumberParam, 50), }); // Use the appropriate query based on scope const projectAuditLogs = api.auditLogs.all.useQuery( { projectId: props.scope === "project" ? props.projectId : "", page: paginationState.pageIndex, limit: paginationState.pageSize, }, { enabled: props.scope === "project" }, ); const orgAuditLogs = api.auditLogs.allByOrg.useQuery( { orgId: props.scope === "organization" ? props.orgId : "", page: paginationState.pageIndex, limit: paginationState.pageSize, }, { enabled: props.scope === "organization" }, ); const auditLogs = props.scope === "project" ? projectAuditLogs : orgAuditLogs; const tableId = props.scope === "project" ? "auditLogs" : "orgAuditLogs"; const [rowHeight, setRowHeight] = useRowHeightLocalStorage(tableId, "s"); const columns: LangfuseColumnDef[] = [ { accessorKey: "createdAt", header: "Time", cell: (row) => { const date = row.getValue() as Date; return date.toLocaleString(); }, }, { accessorKey: "actor", header: "Actor", headerTooltip: { description: "The actor within Langfuse who performed the action.", }, cell: (row) => { const actor = row.getValue() as AuditLogRow["actor"]; if (actor?.type === "USER") { const user = actor.body; return (
{user?.image && ( )} {user?.name?.charAt(0) ?? user?.email?.charAt(0) ?? "U"} {user?.name ?? user?.email ?? user.id}
); } if (actor?.type === "API_KEY") { const apiKey = actor.body; return (
{apiKey?.publicKey ?? apiKey?.id}
); } return null; }, }, { accessorKey: "resourceType", header: "Resource Type", }, { accessorKey: "resourceId", header: "Resource ID", }, { accessorKey: "action", header: "Action", }, { accessorKey: "before", header: "Before", size: 300, cell: (row) => { const value = row.getValue() as string | null; if (!value) return null; return ; }, }, { accessorKey: "after", header: "After", size: 300, cell: (row) => { const value = row.getValue() as string | null; if (!value) return null; return ; }, }, ]; return ( <> , ] : [] } className="px-0" /> ); }