import { Alert, AlertDescription } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { prometheusFormSchema, type PrometheusFormSchema } from "@/lib/types/schemas"; import { RbacOperation, RbacResource, useRbac } from "@enterprise/lib"; import { zodResolver } from "@hookform/resolvers/zod"; import { Switch } from "@/components/ui/switch"; import { useCopyToClipboard } from "@/hooks/useCopyToClipboard"; import { AlertTriangle, Copy, Eye, EyeOff, Info, Plus, Trash, Trash2 } from "lucide-react"; import { useEffect, useState } from "react"; import { useForm, type Resolver } from "react-hook-form"; interface PrometheusFormFragmentProps { currentConfig?: { enabled?: boolean; push_gateway_url?: string; job_name?: string; instance_id?: string; push_interval?: number; basic_auth?: { username?: string; password?: string; }; }; onSave: (config: PrometheusFormSchema) => Promise; onDelete?: () => void; isDeleting?: boolean; isLoading?: boolean; metricsEndpoint?: string; } export function PrometheusFormFragment({ currentConfig: initialConfig, onSave, onDelete, isDeleting = false, isLoading = false, metricsEndpoint, }: PrometheusFormFragmentProps) { const hasPrometheusAccess = useRbac(RbacResource.Observability, RbacOperation.Update); const [showPassword, setShowPassword] = useState(false); const [isSaving, setIsSaving] = useState(false); const { copy, copied } = useCopyToClipboard(); const [showBasicAuth, setShowBasicAuth] = useState(!!(initialConfig?.basic_auth?.username || initialConfig?.basic_auth?.password)); const form = useForm({ resolver: zodResolver(prometheusFormSchema) as Resolver, mode: "onChange", reValidateMode: "onChange", defaultValues: { enabled: initialConfig?.enabled ?? true, prometheus_config: { push_gateway_url: initialConfig?.push_gateway_url ?? "", job_name: initialConfig?.job_name ?? "bifrost", instance_id: initialConfig?.instance_id ?? "", push_interval: initialConfig?.push_interval ?? 15, basic_auth_username: initialConfig?.basic_auth?.username ?? "", basic_auth_password: initialConfig?.basic_auth?.password ?? "", }, }, }); const onSubmit = (data: PrometheusFormSchema) => { setIsSaving(true); onSave(data).finally(() => setIsSaving(false)); }; useEffect(() => { form.reset({ enabled: initialConfig?.enabled ?? true, prometheus_config: { push_gateway_url: initialConfig?.push_gateway_url ?? "", job_name: initialConfig?.job_name ?? "bifrost", instance_id: initialConfig?.instance_id ?? "", push_interval: initialConfig?.push_interval ?? 15, basic_auth_username: initialConfig?.basic_auth?.username ?? "", basic_auth_password: initialConfig?.basic_auth?.password ?? "", }, }); setShowBasicAuth(!!(initialConfig?.basic_auth?.username || initialConfig?.basic_auth?.password)); }, [form, initialConfig]); const handleCopyEndpoint = () => { if (metricsEndpoint) { copy(metricsEndpoint); } }; const handleRemoveBasicAuth = () => { form.setValue("prometheus_config.basic_auth_username", "", { shouldDirty: true }); form.setValue("prometheus_config.basic_auth_password", "", { shouldDirty: true }); setShowBasicAuth(false); }; return (
{/* Pull-based Scraping Section */}

Pull-based Scraping

Prometheus can scrape metrics from the /metrics endpoint

Metrics Endpoint {metricsEndpoint || "http://:/metrics"}
{metricsEndpoint && ( )}

Configure your Prometheus server to scrape this endpoint. This is always available when Bifrost is running.

{/* Push-based Section */}

Push-based (Push Gateway) BETA

Push metrics to a Prometheus Push Gateway for proper aggregation in cluster deployments

{/* Warning note for multi-node deployments */} If you are running multiple Bifrost nodes, use push gateway for accurate metrics. Pull-based /metrics scraping may miss nodes behind a load balancer.
( Push Gateway URL URL of your Prometheus Push Gateway )} />
( Job Name Job label for metrics )} /> ( Push Interval (seconds) field.onChange(parseInt(e.target.value) || 15)} /> How often to push (1-300s) )} />
( Instance ID

Used to identify this Bifrost instance in metrics. If not set, hostname is used automatically.

)} /> {/* Basic Auth Section */}
{!showBasicAuth ? ( ) : ( <>
Basic Authentication
( Username )} /> ( Password
)} />
)}
{/* Form Actions */}
( Enabled )} />
{onDelete && ( )} {(!form.formState.isDirty || !form.formState.isValid) && (

{!form.formState.isDirty && !form.formState.isValid ? "No changes made and validation errors present" : !form.formState.isDirty ? "No changes made" : "Please fix validation errors"}

)}
); }