Add UI Support for Admins to Call /cache/ping and View Cache Analytics (#8475) (#8519)
All checks were successful
Read Version from pyproject.toml / read-version (push) Successful in 1m19s

* [Bug] UI: Newly created key does not display on the View Key Page (#8039)

- Fixed issue where all keys appeared blank for admin users.
- Implemented filtering of data via team settings to ensure all keys are displayed correctly.

* Fix:
- Updated the validator to allow model editing when `keyTeam.team_alias === "Default Team"`.
- Ensured other teams still follow the original validation rules.

* - added some classes in global.css
- added text wrap in output of request,response and metadata in index.tsx
- fixed styles of table in table.tsx

* - added full payload when we open single log entry
- added Combined Info Card in index.tsx

* fix: keys not showing on refresh for internal user

* merge

* main merge

* cache page

* ca remove

* terms change

* fix:places caching inside exp
This commit is contained in:
Taha Ali 2025-02-14 04:31:16 +05:30 committed by GitHub
parent 2c8c1de948
commit 1d22052f47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 123 additions and 6 deletions

View file

@ -12,10 +12,28 @@ import {
DateRangePickerValue, DateRangePickerValue,
MultiSelect, MultiSelect,
MultiSelectItem, MultiSelectItem,
Button,
TabPanel,
TabPanels,
TabGroup,
TabList,
Tab,
TextInput,
Icon,
Text,
} from "@tremor/react"; } from "@tremor/react";
import {
Button as Button2,
message,
} from "antd";
import {
RefreshIcon,
} from "@heroicons/react/outline";
import { import {
adminGlobalCacheActivity, adminGlobalCacheActivity,
cachingHealthCheckCall,
healthCheckCall,
} from "./networking"; } from "./networking";
const formatDateWithoutTZ = (date: Date | undefined) => { const formatDateWithoutTZ = (date: Date | undefined) => {
@ -86,6 +104,8 @@ const CacheDashboard: React.FC<CachePageProps> = ({
to: new Date(), to: new Date(),
}); });
const [lastRefreshed, setLastRefreshed] = useState("");
const [healthCheckResponse, setHealthCheckResponse] = useState<string>("");
useEffect(() => { useEffect(() => {
if (!accessToken || !dateValue) { if (!accessToken || !dateValue) {
@ -96,6 +116,9 @@ const CacheDashboard: React.FC<CachePageProps> = ({
setData(response); setData(response);
}; };
fetchData(); fetchData();
const currentDate = new Date();
setLastRefreshed(currentDate.toLocaleString());
}, [accessToken]); }, [accessToken]);
const uniqueApiKeys = Array.from(new Set(data.map((item) => item?.api_key ?? ""))); const uniqueApiKeys = Array.from(new Set(data.map((item) => item?.api_key ?? "")));
@ -208,7 +231,49 @@ const CacheDashboard: React.FC<CachePageProps> = ({
}, [selectedApiKeys, selectedModels, dateValue, data]); }, [selectedApiKeys, selectedModels, dateValue, data]);
const handleRefreshClick = () => {
// Update the 'lastRefreshed' state to the current date and time
const currentDate = new Date();
setLastRefreshed(currentDate.toLocaleString());
};
const runCachingHealthCheck = async () => {
try {
message.info("Running cache health check...");
setHealthCheckResponse("");
const response = await cachingHealthCheckCall(accessToken !== null ? accessToken : "");
console.log("CACHING HEALTH CHECK RESPONSE", response);
setHealthCheckResponse(response);
} catch (error) {
console.error("Error running health check:", error);
setHealthCheckResponse("Error running health check");
}
};
return ( return (
<TabGroup className="gap-2 p-8 h-full w-full mt-2 mb-8">
<TabList className="flex justify-between mt-2 w-full items-center">
<div className="flex">
<Tab>Cache Analytics</Tab>
<Tab>
<pre>Cache Health</pre>
</Tab>
</div>
<div className="flex items-center space-x-2">
{lastRefreshed && <Text>Last Refreshed: {lastRefreshed}</Text>}
<Icon
icon={RefreshIcon} // Modify as necessary for correct icon name
variant="shadow"
size="xs"
className="self-center"
onClick={handleRefreshClick}
/>
</div>
</TabList>
<TabPanels>
<TabPanel>
<Card> <Card>
<Grid numItems={3} className="gap-4 mt-4"> <Grid numItems={3} className="gap-4 mt-4">
<Col> <Col>
@ -314,11 +379,28 @@ const CacheDashboard: React.FC<CachePageProps> = ({
</Card> </Card>
</TabPanel>
<TabPanel>
<Card className="mt-4">
<Text>
Cache health will run a very small request through API /cache/ping
configured on litellm
</Text>
<Button onClick={runCachingHealthCheck} className="mt-4">Run cache health</Button>
{healthCheckResponse && (
<pre className="mt-4" style={{
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
maxWidth: '100%'
}}>
{JSON.stringify(healthCheckResponse, null, 2)}
</pre>
)}
</Card>
</TabPanel>
</TabPanels>
</TabGroup>
); );
}; };

View file

@ -58,6 +58,8 @@ const menuItems: MenuItem[] = [
{ key: "14", page: "api_ref", label: "API Reference", icon: <ApiOutlined /> }, { key: "14", page: "api_ref", label: "API Reference", icon: <ApiOutlined /> },
{ key: "16", page: "model-hub", label: "Model Hub", icon: <AppstoreOutlined /> }, { key: "16", page: "model-hub", label: "Model Hub", icon: <AppstoreOutlined /> },
{ key: "15", page: "logs", label: "Logs", icon: <LineChartOutlined />, roles: all_admin_roles }, { key: "15", page: "logs", label: "Logs", icon: <LineChartOutlined />, roles: all_admin_roles },
{ {
key: "experimental", key: "experimental",
page: "experimental", page: "experimental",
@ -68,6 +70,7 @@ const menuItems: MenuItem[] = [
{ key: "9", page: "caching", label: "Caching", icon: <DatabaseOutlined />, roles: all_admin_roles }, { key: "9", page: "caching", label: "Caching", icon: <DatabaseOutlined />, roles: all_admin_roles },
{ key: "10", page: "budgets", label: "Budgets", icon: <BankOutlined />, roles: all_admin_roles }, { key: "10", page: "budgets", label: "Budgets", icon: <BankOutlined />, roles: all_admin_roles },
{ key: "11", page: "guardrails", label: "Guardrails", icon: <SafetyOutlined />, roles: all_admin_roles }, { key: "11", page: "guardrails", label: "Guardrails", icon: <SafetyOutlined />, roles: all_admin_roles },
] ]
}, },
{ {

View file

@ -3210,6 +3210,38 @@ export const healthCheckCall = async (accessToken: String) => {
} }
}; };
export const cachingHealthCheckCall = async (accessToken: String) => {
/**
* Get all the models user has access to
*/
try {
let url = proxyBaseUrl ? `${proxyBaseUrl}/cache/ping` : `/cache/ping`;
//message.info("Requesting model data");
const response = await fetch(url, {
method: "GET",
headers: {
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
const errorData = await response.text();
handleError(errorData);
throw new Error("Network response was not ok");
}
const data = await response.json();
//message.info("Received model data");
return data;
// Handle success - you might want to update some state or UI based on the created key
} catch (error) {
console.error("Failed to call /cache/ping:", error);
throw error;
}
};
export const getProxyUISettings = async ( export const getProxyUISettings = async (
accessToken: String, accessToken: String,
) => { ) => {