Key alias filter on logs (#10905)

* key hash filter added

* key alias filter added
This commit is contained in:
tanjiro
2025-05-17 09:49:14 +09:00
committed by GitHub
parent bd1e0634bf
commit fdacf07ccb
2 changed files with 92 additions and 19 deletions
@@ -1,9 +1,9 @@
import moment from "moment";
import { useQuery } from "@tanstack/react-query";
import { useState, useRef, useEffect } from "react";
import { useState, useRef, useEffect, useCallback } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { uiSpendLogsCall, keyInfoV1Call, sessionSpendLogsCall } from "../networking";
import { uiSpendLogsCall, keyInfoV1Call, sessionSpendLogsCall, keyListCall } from "../networking";
import { DataTable } from "./table";
import { columns, LogEntry } from "./columns";
import { Row } from "@tanstack/react-table";
@@ -21,6 +21,7 @@ import { GuardrailViewer } from './GuardrailViewer';
import FilterComponent from "../common_components/filter";
import { FilterOption } from "../common_components/filter";
import { useLogFilterLogic } from "./log_filter_logic";
import { fetchAllKeyAliases } from "../key_team_helpers/filter_helpers";
interface SpendLogsTableProps {
accessToken: string | null;
@@ -154,7 +155,6 @@ export default function SpendLogsTable({
],
queryFn: async () => {
if (!accessToken || !token || !userRole || !userID) {
console.log("Missing required auth parameters");
return {
data: [],
total: 0,
@@ -241,18 +241,53 @@ export default function SpendLogsTable({
userRole
})
// Add this effect to update selectedTeamId and selectedStatus when team filter changes
const fetchKeyHashForAlias = useCallback(async (keyAlias: string) => {
if (!accessToken) return;
try {
const response = await keyListCall(
accessToken,
null,
null,
keyAlias,
null,
null,
currentPage,
pageSize
);
const selectedKey = response.keys.find(
(key: any) => key.key_alias === keyAlias
);
if (selectedKey) {
setSelectedKeyHash(selectedKey.token);
}
} catch (error) {
console.error("Error fetching key hash for alias:", error);
}
}, [accessToken, currentPage, pageSize]);
// Add this effect to update selected filters when filter changes
useEffect(() => {
if(!accessToken) return;
if (filters['Team ID']) {
setSelectedTeamId(filters['Team ID']);
} else {
setSelectedTeamId("");
}
setSelectedStatus(filters['Status'] || "");
setSelectedModel(filters['Model'] || "");
setSelectedKeyHash(filters['Key Hash'] || "");
}, [filters]);
if (filters['Key Hash']) {
setSelectedKeyHash(filters['Key Hash']);
} else if (filters['Key Alias']) {
fetchKeyHashForAlias(filters['Key Alias']);
} else {
setSelectedKeyHash("");
}
}, [filters, accessToken, fetchKeyHashForAlias]);
// Fetch logs for a session if selected
const sessionLogs = useQuery<PaginatedResponse>({
@@ -354,7 +389,7 @@ export default function SpendLogsTable({
const filtered = allTeams.filter((team: Team) =>{
return team.team_id.toLowerCase().includes(searchText.toLowerCase()) ||
(team.team_alias && team.team_alias.toLowerCase().includes(searchText.toLowerCase()))
});
});
return filtered.map((team: Team) => ({
label: `${team.team_alias || team.team_id} (${team.team_id})`,
value: team.team_id
@@ -385,6 +420,22 @@ export default function SpendLogsTable({
}));
}
},
{
name: 'Key Alias',
label: 'Key Alias',
isSearchable: true,
searchFn: async (searchText: string) => {
if (!accessToken) return [];
const keyAliases = await fetchAllKeyAliases(accessToken);
const filtered = keyAliases.filter(alias =>
alias.toLowerCase().includes(searchText.toLowerCase())
);
return filtered.map(alias => ({
label: alias,
value: alias
}));
}
},
{
name: 'Key Hash',
label: 'Key Hash',
@@ -15,6 +15,7 @@ export const FILTER_KEYS = {
MODEL: "Model",
USER_ID: "User ID",
STATUS: "Status",
KEY_ALIAS: "Key Alias",
} as const;
export type FilterKey = keyof typeof FILTER_KEYS;
@@ -47,7 +48,8 @@ export function useLogFilterLogic({
[FILTER_KEYS.REQUEST_ID]: "",
[FILTER_KEYS.MODEL]: "",
[FILTER_KEYS.USER_ID]: "",
[FILTER_KEYS.STATUS]: ""
[FILTER_KEYS.STATUS]: "",
[FILTER_KEYS.KEY_ALIAS]: ""
}), []);
const [filters, setFilters] = useState<LogFilterState>(defaultFilters);
@@ -96,6 +98,16 @@ export function useLogFilterLogic({
return () => debouncedSearch.cancel();
}, [debouncedSearch]);
const queryAllKeysQuery = useQuery({
queryKey: ['allKeys'],
queryFn: async () => {
if (!accessToken) throw new Error('Access token required');
return await fetchAllKeyAliases(accessToken);
},
enabled: !!accessToken
});
const allKeyAliases = queryAllKeysQuery.data || []
// Apply filters to keys whenever logs or filters change
useEffect(() => {
if (!logs || !logs.data) {
@@ -140,6 +152,24 @@ export function useLogFilterLogic({
);
}
// Add key alias filtering
if (filters[FILTER_KEYS.KEY_ALIAS]) {
// We need to fetch the key info to get the key hash for the selected alias
try {
// Get the key hash for the selected alias
const selectedKey = filters[FILTER_KEYS.KEY_ALIAS]
if (selectedKey) {
// Filter logs by the key hash
filteredData = filteredData.filter(
log => log.metadata?.user_api_key_alias === selectedKey
);
}
} catch (error) {
console.error("Error fetching key info for alias:", error);
}
}
const newFilteredLogs: PaginatedResponse = {
data: filteredData,
total: logs.total,
@@ -151,17 +181,9 @@ export function useLogFilterLogic({
if (JSON.stringify(newFilteredLogs) !== JSON.stringify(filteredLogs)) {
setFilteredLogs(newFilteredLogs);
}
}, [logs, filters, filteredLogs]);
}, [logs, filters, filteredLogs, accessToken]);
const queryAllKeysQuery = useQuery({
queryKey: ['allKeys'],
queryFn: async () => {
if (!accessToken) throw new Error('Access token required');
return await fetchAllKeyAliases(accessToken);
},
enabled: !!accessToken
});
const allKeyAliases = queryAllKeysQuery.data || []
// Fetch all teams and users for potential filter dropdowns (optional, can be adapted)
const { data: allTeams } = useQuery<Team[], Error>({