mirror of
https://github.com/BerriAI/litellm.git
synced 2025-04-26 19:24:27 +00:00
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
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:
parent
2c8c1de948
commit
1d22052f47
3 changed files with 123 additions and 6 deletions
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
) => {
|
) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue