diff --git a/dashboard/backend/router/router.go b/dashboard/backend/router/router.go index 0683cb64..a6ec0c8a 100644 --- a/dashboard/backend/router/router.go +++ b/dashboard/backend/router/router.go @@ -201,7 +201,25 @@ func Setup(cfg *config.Config) *http.ServeMux { if middleware.HandleCORSPreflight(w, r) { return } - log.Printf("Proxying Chat UI login: %s %s", r.Method, r.URL.Path) + // Check if this is a Grafana login request by: + // 1. Query parameter redirectTo with "goto" (GET requests) + // 2. Referer header containing "/embedded/grafana" or "/monitoring" + // 3. Content-Type: application/json (Grafana uses JSON for login POST) + redirectTo := r.URL.Query().Get("redirectTo") + referer := r.Header.Get("Referer") + contentType := r.Header.Get("Content-Type") + + isGrafanaRequest := (redirectTo != "" && strings.Contains(redirectTo, "goto")) || + strings.Contains(referer, "/embedded/grafana") || + strings.Contains(referer, "/monitoring") || + strings.Contains(contentType, "application/json") + + if isGrafanaRequest && grafanaStaticProxy != nil { + log.Printf("Proxying Grafana login: %s %s (redirectTo=%s, referer=%s, contentType=%s)", r.Method, r.URL.Path, redirectTo, referer, contentType) + grafanaStaticProxy.ServeHTTP(w, r) + return + } + log.Printf("Proxying Chat UI login: %s %s (contentType=%s)", r.Method, r.URL.Path, contentType) chatUIProxy.ServeHTTP(w, r) }) mux.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) { diff --git a/dashboard/frontend/src/pages/MonitoringPage.tsx b/dashboard/frontend/src/pages/MonitoringPage.tsx index 45ff50e4..3639f54d 100644 --- a/dashboard/frontend/src/pages/MonitoringPage.tsx +++ b/dashboard/frontend/src/pages/MonitoringPage.tsx @@ -31,38 +31,15 @@ const MonitoringPage: React.FC = () => { return () => observer.disconnect() }, [theme]) - // Build initial Grafana URL - load the root path first - const buildInitialGrafanaUrl = () => { - // Start with Grafana root path - const url = `/embedded/grafana/?orgId=1&theme=${theme}` - console.log('Initial Grafana URL:', url) - return url - } - - // Build dashboard URL using goto endpoint - this is what Grafana uses internally - const buildDashboardUrl = () => { - // Use Grafana's goto endpoint to navigate by UID - // This mimics the internal navigation when clicking Home + // Build Grafana dashboard URL directly + const buildGrafanaUrl = () => { + // Load the dashboard directly using the goto endpoint + // This is the cleanest approach and avoids redirect loops const url = `/embedded/grafana/goto/llm-router-metrics?orgId=1&theme=${theme}&refresh=30s` - console.log('Dashboard goto URL:', url) + console.log('Grafana URL:', url) return url } - // Add effect to handle automatic redirect to dashboard - useEffect(() => { - // After initial page load, wait a bit then redirect to dashboard using goto - const timer = setTimeout(() => { - if (iframeRef.current) { - console.log('Redirecting to dashboard using goto...') - // Use goto endpoint to navigate to dashboard (mimics clicking Home) - iframeRef.current.src = buildDashboardUrl() - } - setLoading(false) - }, 100) // Wait 0.1 seconds after initial load - - return () => clearTimeout(timer) - }, [theme]) - const handleIframeLoad = () => { @@ -95,7 +72,7 @@ const MonitoringPage: React.FC = () => {