Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 89 additions & 23 deletions ui/app/workspace/logs/views/columns.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { formatCost, formatLatency } from "@/app/workspace/dashboard/utils/chartUtils";
import { formatCompactNumber } from "@/lib/utils/numbers";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdownMenu";
import { ProviderIconType, RenderProviderIcon } from "@/lib/constants/icons";
import { getProviderLabel, ProviderName, RequestTypeColors, RequestTypeLabels, Status, StatusBarColors } from "@/lib/constants/logs";
import { ChatMessageContent, LogEntry, ResponsesMessageContentBlock } from "@/lib/types/logs";
import { cn } from "@/lib/utils";
import { formatCompactNumber } from "@/lib/utils/numbers";
import { ColumnDef } from "@tanstack/react-table";
import { format, formatDistanceToNow } from "date-fns";
import { ArrowUpDown, MoreHorizontal, Trash2 } from "lucide-react";
Expand Down Expand Up @@ -178,7 +178,7 @@ export function LogMessageCell({ log, contentClassName = "max-w-full" }: { log:
</span>
)}
{realtimeMessages &&
(realtimeMessages.tool || realtimeMessages.user || realtimeMessages.assistantToolCall || realtimeMessages.assistant) ? (
(realtimeMessages.tool || realtimeMessages.user || realtimeMessages.assistantToolCall || realtimeMessages.assistant) ? (
<div className={cn(contentClassName, "font-mono text-sm font-normal leading-5")}>
{realtimeMessages.tool ? <div className="truncate">Tool Result: {realtimeMessages.tool}</div> : null}
{realtimeMessages.user ? <div className="truncate">User: {realtimeMessages.user}</div> : null}
Expand All @@ -199,6 +199,53 @@ export function LogMessageCell({ log, contentClassName = "max-w-full" }: { log:
);
}

const MAX_ATTRIBUTION_LINES = 1;

// AttributionCell resolves an attribution value using a plural-first fallback:
// plural names -> singular name -> plural ids -> singular id. When a plural
// (array) source is used, values render one per line, capped at
// MAX_ATTRIBUTION_LINES with a "+N more" indicator for the remainder.
function AttributionCell({
names,
name,
ids,
id,
}: {
names?: string[];
name?: string | null;
ids?: string[];
id?: string | null;
}) {
let values: string[] = [];
if (Array.isArray(names) && names.filter(Boolean).length > 0) {
values = names.filter(Boolean);
} else if (name) {
values = [name];
} else if (Array.isArray(ids) && ids.filter(Boolean).length > 0) {
values = ids.filter(Boolean);
} else if (id) {
values = [id];
}

if (values.length === 0) {
return <div className="max-w-[180px] truncate font-mono text-xs">-</div>;
}

const visible = values.slice(0, MAX_ATTRIBUTION_LINES);
const remaining = values.length - visible.length;

return (
<div className="flex max-w-[180px] flex-col gap-0.5 font-mono text-xs leading-tight" title={values.join("\n")}>
{visible.map((value, index) => (
<span key={index} className="truncate">
{value}
</span>
))}
{remaining > 0 && <span className="text-muted-foreground">+{remaining} more</span>}
</div>
);
}

export const createColumns = (
onDelete: (log: LogEntry) => void,
hasDeleteAccess = true,
Expand Down Expand Up @@ -367,44 +414,63 @@ export const createColumns = (
},
];

const attributionCell = (value?: string | null) => <div className="max-w-[180px] truncate font-mono text-xs">{value || "-"}</div>;

const attributionColumns: ColumnDef<LogEntry>[] = [
{
id: "virtual_key",
header: "Virtual Key",
size: 170,
cell: ({ row }) => attributionCell(row.original.virtual_key?.name ?? row.original.virtual_key_id),
cell: ({ row }) => <AttributionCell name={row.original.virtual_key_name} id={row.original.virtual_key_id} />,
},
{
id: "routing_rule",
header: "Routing Rule",
size: 170,
cell: ({ row }) => attributionCell(row.original.routing_rule?.name ?? row.original.routing_rule_id),
cell: ({ row }) => <AttributionCell name={row.original.routing_rule_name} id={row.original.routing_rule_id} />,
Comment thread
impoiler marked this conversation as resolved.
},
{
id: "team",
header: "Team",
size: 150,
cell: ({ row }) => attributionCell(row.original.team_name ?? row.original.team_id),
cell: ({ row }) => (
<AttributionCell
names={row.original.team_names}
name={row.original.team_name}
ids={row.original.team_ids}
id={row.original.team_id}
/>
),
},
{
id: "customer",
header: "Customer",
size: 150,
cell: ({ row }) => attributionCell(row.original.customer_name ?? row.original.customer_id),
cell: ({ row }) => (
<AttributionCell
names={row.original.customer_names}
name={row.original.customer_name}
ids={row.original.customer_ids}
id={row.original.customer_id}
/>
),
},
{
id: "user",
header: "User",
size: 150,
cell: ({ row }) => attributionCell(row.original.user_name ?? row.original.user_id),
cell: ({ row }) => <AttributionCell name={row.original.user_name} id={row.original.user_id} />,
},
{
id: "business_unit",
header: "Business Unit",
size: 150,
cell: ({ row }) => attributionCell(row.original.business_unit_name ?? row.original.business_unit_id),
cell: ({ row }) => (
<AttributionCell
names={row.original.business_unit_names}
name={row.original.business_unit_name}
ids={row.original.business_unit_ids}
id={row.original.business_unit_id}
/>
),
},
];

Expand All @@ -420,20 +486,20 @@ export const createColumns = (

const actionsColumn: ColumnDef<LogEntry>[] = hasDeleteAccess
? [
{
id: "actions",
header: "",
size: 56,
cell: ({ row }) => {
const log = row.original;
return (
<div className="flex justify-center">
<LogActionsMenu log={log} onDelete={onDelete} />
</div>
);
},
{
id: "actions",
header: "",
size: 56,
cell: ({ row }) => {
const log = row.original;
return (
<div className="flex justify-center">
<LogActionsMenu log={log} onDelete={onDelete} />
</div>
);
},
]
},
]
: [];

return [...baseColumns, ...attributionColumns, ...metadataColumns, ...actionsColumn];
Expand Down
2 changes: 2 additions & 0 deletions ui/lib/types/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,8 +529,10 @@ export interface LogEntry {
user_id?: string;
user_name?: string;
virtual_key_id?: string;
virtual_key_name?: string;
routing_engines_used?: string[];
routing_rule_id?: string;
routing_rule_name?: string;
routing_engine_logs?: string; // Human-readable routing decision logs
plugin_logs?: string; // JSON string of plugin execution logs grouped by plugin name
selected_key?: DBKey;
Expand Down
Loading