mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
[Feat] UI - Allow Viewing/Editing Team Based Callbacks (#12329)
* add logging settings view on UI * fix change ordering
This commit is contained in:
parent
6f27385edf
commit
78ee153545
3 changed files with 182 additions and 3 deletions
138
ui/litellm-dashboard/src/components/logging_settings_view.tsx
Normal file
138
ui/litellm-dashboard/src/components/logging_settings_view.tsx
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
import React from "react";
|
||||
import { Text, Badge } from "@tremor/react";
|
||||
import { CogIcon } from "@heroicons/react/outline";
|
||||
import { callbackInfo, callback_map } from "./callback_info_helpers";
|
||||
|
||||
interface LoggingConfig {
|
||||
callback_name: string;
|
||||
callback_type: string;
|
||||
callback_vars: Record<string, string>;
|
||||
}
|
||||
|
||||
interface LoggingSettingsViewProps {
|
||||
loggingConfigs?: LoggingConfig[];
|
||||
variant?: "card" | "inline";
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function LoggingSettingsView({
|
||||
loggingConfigs = [],
|
||||
variant = "card",
|
||||
className = ""
|
||||
}: LoggingSettingsViewProps) {
|
||||
const getLoggingDisplayName = (callbackName: string) => {
|
||||
// Find the display name for the callback
|
||||
const callbackDisplayName = Object.entries(callback_map).find(
|
||||
([_, value]) => value === callbackName
|
||||
)?.[0];
|
||||
return callbackDisplayName || callbackName;
|
||||
};
|
||||
|
||||
const getEventTypeColor = (eventType: string) => {
|
||||
switch (eventType) {
|
||||
case "success":
|
||||
return "green";
|
||||
case "failure":
|
||||
return "red";
|
||||
case "success_and_failure":
|
||||
return "blue";
|
||||
default:
|
||||
return "gray";
|
||||
}
|
||||
};
|
||||
|
||||
const getEventTypeLabel = (eventType: string) => {
|
||||
switch (eventType) {
|
||||
case "success":
|
||||
return "Success Only";
|
||||
case "failure":
|
||||
return "Failure Only";
|
||||
case "success_and_failure":
|
||||
return "Success & Failure";
|
||||
default:
|
||||
return eventType;
|
||||
}
|
||||
};
|
||||
|
||||
const content = (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<CogIcon className="h-4 w-4 text-blue-600" />
|
||||
<Text className="font-semibold text-gray-900">Logging Integrations</Text>
|
||||
<Badge color="blue" size="xs">
|
||||
{loggingConfigs.length}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{loggingConfigs.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
{loggingConfigs.map((config, index) => {
|
||||
const displayName = getLoggingDisplayName(config.callback_name);
|
||||
const logoUrl = callbackInfo[displayName]?.logo;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-center justify-between p-3 rounded-lg bg-blue-50 border border-blue-200"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
{logoUrl ? (
|
||||
<img
|
||||
src={logoUrl}
|
||||
alt={displayName}
|
||||
className="w-5 h-5 object-contain"
|
||||
/>
|
||||
) : (
|
||||
<CogIcon className="h-5 w-5 text-gray-400" />
|
||||
)}
|
||||
<div>
|
||||
<Text className="font-medium text-blue-800">{displayName}</Text>
|
||||
<Text className="text-xs text-blue-600">
|
||||
{Object.keys(config.callback_vars).length} parameters configured
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<Badge
|
||||
color={getEventTypeColor(config.callback_type)}
|
||||
size="sm"
|
||||
>
|
||||
{getEventTypeLabel(config.callback_type)}
|
||||
</Badge>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-gray-50 border border-gray-200">
|
||||
<CogIcon className="h-4 w-4 text-gray-400" />
|
||||
<Text className="text-gray-500 text-sm">No logging integrations configured</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (variant === "card") {
|
||||
return (
|
||||
<div className={`bg-white border border-gray-200 rounded-lg p-6 ${className}`}>
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<div>
|
||||
<Text className="font-semibold text-gray-900">Logging Settings</Text>
|
||||
<Text className="text-xs text-gray-500">
|
||||
Active logging integrations for this team
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${className}`}>
|
||||
<Text className="font-medium text-gray-900 mb-3">Logging Settings</Text>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default LoggingSettingsView;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import LoggingSettings from './LoggingSettings';
|
||||
|
||||
interface EditLoggingSettingsProps {
|
||||
value: any[];
|
||||
onChange: (value: any[]) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper component around LoggingSettings used for editing
|
||||
* a team's logging integrations.
|
||||
*/
|
||||
const EditLoggingSettings: React.FC<EditLoggingSettingsProps> = ({ value, onChange }) => {
|
||||
return <LoggingSettings value={value} onChange={onChange} />;
|
||||
};
|
||||
|
||||
export default EditLoggingSettings;
|
||||
|
|
@ -38,6 +38,8 @@ import VectorStoreSelector from "../vector_store_management/VectorStoreSelector"
|
|||
import MCPServerSelector from "../mcp_server_management/MCPServerSelector";
|
||||
import PremiumVectorStoreSelector from "../common_components/PremiumVectorStoreSelector";
|
||||
import { formatNumberWithCommas } from "@/utils/dataUtils";
|
||||
import EditLoggingSettings from "./EditLoggingSettings";
|
||||
import LoggingSettingsView from "../logging_settings_view";
|
||||
|
||||
export interface TeamMembership {
|
||||
user_id: string;
|
||||
|
|
@ -252,7 +254,8 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
budget_duration: values.budget_duration,
|
||||
metadata: {
|
||||
...parsedMetadata,
|
||||
guardrails: values.guardrails || []
|
||||
guardrails: values.guardrails || [],
|
||||
logging: values.logging_settings || []
|
||||
},
|
||||
organization_id: values.organization_id,
|
||||
};
|
||||
|
|
@ -366,6 +369,11 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
variant="card"
|
||||
accessToken={accessToken}
|
||||
/>
|
||||
|
||||
<LoggingSettingsView
|
||||
loggingConfigs={info.metadata?.logging || []}
|
||||
variant="card"
|
||||
/>
|
||||
</Grid>
|
||||
</TabPanel>
|
||||
|
||||
|
|
@ -419,7 +427,10 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
max_budget: info.max_budget,
|
||||
budget_duration: info.budget_duration,
|
||||
guardrails: info.metadata?.guardrails || [],
|
||||
metadata: info.metadata ? JSON.stringify(info.metadata, null, 2) : "",
|
||||
metadata: info.metadata
|
||||
? JSON.stringify((({ logging, ...rest }) => rest)(info.metadata), null, 2)
|
||||
: "",
|
||||
logging_settings: info.metadata?.logging || [],
|
||||
organization_id: info.organization_id,
|
||||
vector_stores: info.object_permission?.vector_stores || [],
|
||||
mcp_servers: info.object_permission?.mcp_servers || []
|
||||
|
|
@ -525,11 +536,18 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
placeholder="Select MCP servers"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Organization ID" name="organization_id">
|
||||
<Input type=""/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Logging Settings" name="logging_settings">
|
||||
<EditLoggingSettings
|
||||
value={form.getFieldValue('logging_settings')}
|
||||
onChange={(values) => form.setFieldValue('logging_settings', values)}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
|
||||
<Form.Item label="Metadata" name="metadata">
|
||||
<Input.TextArea rows={10} />
|
||||
</Form.Item>
|
||||
|
|
@ -606,6 +624,12 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
className="pt-4 border-t border-gray-200"
|
||||
accessToken={accessToken}
|
||||
/>
|
||||
|
||||
<LoggingSettingsView
|
||||
loggingConfigs={info.metadata?.logging || []}
|
||||
variant="inline"
|
||||
className="pt-4 border-t border-gray-200"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue