From 03b4a6c006cf04dbabc19db3629e55b7b278f758 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 14 Aug 2026 08:00:32 +0000 Subject: [PATCH 1/3] feat(ui): merge Slow Queries and Workload Analysis into Performance One sidebar destination with Query Trends, By Customer, Workload, and Settings. If no slow-query log source is attached, the page shows a Configure slow queries empty state that opens SlowQuerySourceModal. Co-authored-by: Venkat SF --- CLAUDE.md | 2 + src/components/layout/AppSidebar.jsx | 5 +- src/components/onboarding/StepQueryLogs.jsx | 2 +- .../sections/SlowQueriesSection.jsx | 122 +++++++++++++----- .../sections/SlowQueriesSection.module.css | 82 ++++++++++++ .../sections/WorkloadAnalysisSection.jsx | 38 +----- src/components/tabs/Brain/utils/helpText.js | 4 +- .../tabs/Core/ExplainAnalysisPanel.jsx | 2 +- .../tabs/Performance/WorkloadAnalysisPanel.js | 19 +-- src/components/tabs/admin/UsersTab.jsx | 3 +- src/lib/features.js | 10 +- src/pages/Home.jsx | 4 +- 12 files changed, 205 insertions(+), 88 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index cde5cf7..ac09ed4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,6 +93,8 @@ backend/ src/ # Frontend (React) components/ # UI components tabs/ # 40+ specialized tabs + sections/ # Top-level sidebar destinations (Agent, Dashboards, Brain, + # Performance = Slow Queries + Workload, Editor, Docs) lib/ api/client.js # Centralized API layer (axios, 25+ modules) stores/ # Zustand stores (dashboard, connection, chat, UI) diff --git a/src/components/layout/AppSidebar.jsx b/src/components/layout/AppSidebar.jsx index 8d901fc..b9b5c9e 100644 --- a/src/components/layout/AppSidebar.jsx +++ b/src/components/layout/AppSidebar.jsx @@ -1,5 +1,5 @@ import { useState, useEffect, useRef } from 'react' -import { BookOpen, Brain, Code2, Database, Settings, PanelLeftClose, PanelLeftOpen, LogOut, User, ChevronDown, Check, Newspaper, Gauge, Activity, MessageSquare, LayoutDashboard } from 'lucide-react' +import { BookOpen, Brain, Code2, Database, Settings, PanelLeftClose, PanelLeftOpen, LogOut, User, ChevronDown, Check, Newspaper, Gauge, MessageSquare, LayoutDashboard } from 'lucide-react' import { useActiveSection, useSetActiveSection } from '@/lib/stores/useNavStore' import { useConnectionManager } from '@/lib/hooks/useConnectionManager' import { AGENTS_ENABLED, canAccessHomeSection, getConnectionAccessBadge, getConnectionAccessLabel } from '@/lib/features' @@ -14,8 +14,7 @@ const NAV_ITEMS = [ { id: 'digest', label: 'Digest', icon: Newspaper }, ...(AGENTS_ENABLED ? [{ id: 'brain', label: 'Agents', icon: Brain }] : []), { id: 'company-knowledge', label: 'Brain', icon: Brain }, - { id: 'slow-queries', label: 'Slow Queries', icon: Gauge }, - { id: 'workload-analysis', label: 'Workload Analysis', icon: Activity }, + { id: 'performance', label: 'Performance', icon: Gauge }, { id: 'editor', label: 'Editor', icon: Code2 }, { id: 'docs', label: 'Docs', icon: BookOpen }, ] diff --git a/src/components/onboarding/StepQueryLogs.jsx b/src/components/onboarding/StepQueryLogs.jsx index b91ea60..2d59255 100644 --- a/src/components/onboarding/StepQueryLogs.jsx +++ b/src/components/onboarding/StepQueryLogs.jsx @@ -27,7 +27,7 @@ const SOURCES = [ id: 'other', icon: Zap, title: 'Other (Datadog, ELK…)', - sub: 'Configure after setup in the Slow Queries tab.', + sub: 'Configure after setup in the Performance tab.', badge: 'Coming soon', disabled: true, }, diff --git a/src/components/sections/SlowQueriesSection.jsx b/src/components/sections/SlowQueriesSection.jsx index f25d29b..c487551 100644 --- a/src/components/sections/SlowQueriesSection.jsx +++ b/src/components/sections/SlowQueriesSection.jsx @@ -1,73 +1,137 @@ import { useState } from 'react' -import { LineChart, Settings, Users } from 'lucide-react' +import { Activity, FileText, LineChart, Settings, Users } from 'lucide-react' import { useConnectionManager } from '@/lib/hooks/useConnectionManager' +import { useSlowLogSourceConfig } from '@/lib/hooks/queries' import QueryTrendsTab from '@/components/tabs/Performance/QueryTrendsTab' import CustomerExplorer from '@/components/tabs/Performance/CustomerExplorer' import SlowQuerySettingsPanel from '@/components/tabs/Performance/SlowQuerySettingsPanel' +import WorkloadAnalysisPanel from '@/components/tabs/Performance/WorkloadAnalysisPanel' +import SlowQuerySourceModal from '@/components/SlowQuerySourceModal' +import { HelpTooltip } from '@/components/tabs/Brain/components/HelpTooltip' import sectionStyles from './TopLevelSection.module.css' import styles from './SlowQueriesSection.module.css' const TABS = [ { id: 'trends', label: 'Query Trends', icon: LineChart }, { id: 'customers', label: 'By Customer', icon: Users }, + { id: 'workload', label: 'Workload', icon: Activity }, { id: 'settings', label: 'Settings', icon: Settings }, ] +const LOG_SOURCE_HELP = { + title: 'Slow query log', + description: + 'Query trends, per-customer load, and workload analysis all read from ingested slow-query logs. Attach CloudWatch, S3, Azure, GCP, Datadog, Elasticsearch, or a file upload before those views can run.', +} + /** - * Top-level "Slow Queries" section — the 30-day slow-query analytics surface, - * promoted out of the Brain tab strip into its own sidebar destination. + * Combined Performance section — Slow Queries + Workload Analysis. * - * Two sub-views: the query trends/timeline/regressions, and the settings - * panel where the tenant column for per-customer attribution is configured. + * Both surfaces need a slow-query log source. If none is attached, the page + * is a single empty state whose CTA opens SlowQuerySourceModal. */ export default function SlowQueriesSection() { - const { connectionId } = useConnectionManager() + const { connectionId, selectedConnection } = useConnectionManager() const [tab, setTab] = useState('trends') + const [logSourceModalOpen, setLogSourceModalOpen] = useState(false) + const logSourceQ = useSlowLogSourceConfig(connectionId) + const hasLogSource = Boolean(logSourceQ.data?.id) return (
-
Slow Queries
-

Slow query analytics

+
Performance
+

Slow queries & workload

- Per-query performance trends over the last 30 days, regression detection, - and per-customer breakdown. + Per-query trends, regressions, customer attribution, and a holistic + workload report — all from the same slow-query log.

{!connectionId ? (
- Select a database connection to see slow query analytics. + Select a database connection to see performance analytics. +
+ ) : logSourceQ.isLoading ? ( +
Checking slow query log source…
+ ) : logSourceQ.isError ? ( +
+ Could not load the slow query log configuration for this connection. +
+ ) : !hasLogSource ? ( +
+ +

+ + Configure slow queries + +

+

+ Attach a slow-query log source to unlock query trends, per-customer + breakdown, and workload analysis. DeepSQL pulls from CloudWatch, S3, + Azure Blob, GCP, Datadog, Elasticsearch, or a file you upload. +

+
) : ( <> -
- {TABS.map((t) => { - const Icon = t.icon - const active = tab === t.id - return ( - - ) - })} +
+
+ {TABS.map((t) => { + const Icon = t.icon + const active = tab === t.id + return ( + + ) + })} +
+
{tab === 'trends' && } {tab === 'customers' && } + {tab === 'workload' && } {tab === 'settings' && }
)} + + {logSourceModalOpen && connectionId && ( + { + setLogSourceModalOpen(false) + logSourceQ.refetch() + }} + /> + )}
) } diff --git a/src/components/sections/SlowQueriesSection.module.css b/src/components/sections/SlowQueriesSection.module.css index 9710cbb..1a7172c 100644 --- a/src/components/sections/SlowQueriesSection.module.css +++ b/src/components/sections/SlowQueriesSection.module.css @@ -8,6 +8,14 @@ width: fit-content; } +.toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + flex-wrap: wrap; +} + .tabButton { display: inline-flex; align-items: center; @@ -45,3 +53,77 @@ font-size: 13px; color: #9ca3af; } + +.setupCard { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + max-width: 560px; + margin: 24px auto 0; + padding: 40px 28px; + border: 1px solid #e5e7eb; + border-radius: 14px; + background: #fff; + text-align: center; +} + +.setupIcon { + opacity: 0.4; + margin-bottom: 4px; +} + +.setupTitle { + margin: 0; + font-size: 18px; + font-weight: 650; + letter-spacing: -0.02em; + color: #111827; +} + +.setupCopy { + margin: 0 0 10px; + font-size: 14px; + line-height: 1.55; + color: #6b7280; +} + +.setupCta { + display: inline-flex; + align-items: center; + gap: 8px; + margin-top: 6px; + padding: 10px 16px; + border: 1px solid #111827; + border-radius: 10px; + background: #111827; + color: #fff; + font: inherit; + font-size: 13px; + font-weight: 600; + cursor: pointer; +} + +.setupCta:hover { + opacity: 0.88; +} + +.logSourceBtn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 8px 12px; + border: 1px solid #e5e7eb; + border-radius: 10px; + background: #fff; + color: #374151; + font: inherit; + font-size: 13px; + font-weight: 600; + cursor: pointer; +} + +.logSourceBtn:hover { + border-color: #d1d5db; + color: #111827; +} diff --git a/src/components/sections/WorkloadAnalysisSection.jsx b/src/components/sections/WorkloadAnalysisSection.jsx index 4348441..b1807f4 100644 --- a/src/components/sections/WorkloadAnalysisSection.jsx +++ b/src/components/sections/WorkloadAnalysisSection.jsx @@ -1,38 +1,6 @@ -import { useConnectionManager } from '@/lib/hooks/useConnectionManager' -import WorkloadAnalysisPanel from '@/components/tabs/Performance/WorkloadAnalysisPanel' -import sectionStyles from './TopLevelSection.module.css' -import styles from './SlowQueriesSection.module.css' +export { default } from './SlowQueriesSection' /** - * Top-level "Workload Analysis" section — the holistic, on-demand report that - * composes index recommendations, query rewrites, pre-aggregations, and index - * cleanup over the most-impactful queries. Promoted out of the Slow Queries - * tab strip into its own sidebar destination (sits right below Slow Queries). + * @deprecated Workload Analysis now lives as a sub-tab of Performance + * (`SlowQueriesSection`). Kept as a re-export so old imports keep working. */ -export default function WorkloadAnalysisSection() { - const { connectionId } = useConnectionManager() - - return ( -
-
-
Workload Analysis
-

Holistic workload analysis

-

- One holistic pass over your most-impactful queries — index - recommendations, query rewrites, pre-aggregations, and index cleanup, - composed into a single report. -

-
- - {!connectionId ? ( -
- Select a database connection to analyze its workload. -
- ) : ( -
- -
- )} -
- ) -} diff --git a/src/components/tabs/Brain/utils/helpText.js b/src/components/tabs/Brain/utils/helpText.js index 0710849..262e742 100644 --- a/src/components/tabs/Brain/utils/helpText.js +++ b/src/components/tabs/Brain/utils/helpText.js @@ -738,7 +738,7 @@ export const QUERY_INTELLIGENCE = { panel: { title: 'Query Intelligence', description: 'ML-based learning system that builds pattern knowledge over time for smarter query optimization.', - differentiation: 'Unlike the Slow Queries tab (operational monitoring for immediate issues), Query Intelligence focuses on long-term pattern recognition and cardinality accuracy learning.', + differentiation: 'Unlike the Performance tab (operational monitoring for immediate issues), Query Intelligence focuses on long-term pattern recognition and cardinality accuracy learning.', }, // Buttons @@ -795,7 +795,7 @@ export const QUERY_INTELLIGENCE = { recommendations: { title: 'Recommendations', description: 'Actionable database maintenance commands to improve cardinality estimation accuracy.', - differentiation: 'These focus on optimizer statistics maintenance (ANALYZE TABLE, histograms). Query rewrites and index suggestions are in Database Advisor → Slow Queries.', + differentiation: 'These focus on optimizer statistics maintenance (ANALYZE TABLE, histograms). Query rewrites and index suggestions are in Performance → Workload.', impact: 'Accurate cardinality estimates lead to better query plans, reducing execution time for complex queries.', }, analyzeTable: { diff --git a/src/components/tabs/Core/ExplainAnalysisPanel.jsx b/src/components/tabs/Core/ExplainAnalysisPanel.jsx index e6bfb6a..c4e7e9a 100644 --- a/src/components/tabs/Core/ExplainAnalysisPanel.jsx +++ b/src/components/tabs/Core/ExplainAnalysisPanel.jsx @@ -363,7 +363,7 @@ export default function ExplainAnalysisPanel({ analysis }) { )} {indexBottleneck && (
- Note: index recommendations are workload-weighted across all queries — see Workload Analysis, + Note: index recommendations are workload-weighted across all queries — see Performance → Workload, not this single query.
)} diff --git a/src/components/tabs/Performance/WorkloadAnalysisPanel.js b/src/components/tabs/Performance/WorkloadAnalysisPanel.js index e66e0c1..ed6ef14 100644 --- a/src/components/tabs/Performance/WorkloadAnalysisPanel.js +++ b/src/components/tabs/Performance/WorkloadAnalysisPanel.js @@ -27,6 +27,7 @@ import { CheckCircle2, } from "lucide-react"; import { workloadAnalysisAPI } from "@/lib/api/client"; +import { HelpTooltip } from "@/components/tabs/Brain/components/HelpTooltip"; import styles from "./WorkloadAnalysisPanel.module.css"; const fmtMs = (v) => { @@ -341,14 +342,16 @@ export default function WorkloadAnalysisPanel({ connectionId }) { {REASON_LABEL[rec.candidateReason] || rec.candidateReason} )} {rec.fingerprint && ( - - fingerprint - {rec.fingerprint} - - + + + fingerprint + {rec.fingerprint} + + + )} {rec.estimatedImprovementPct != null && ( ~{Math.round(rec.estimatedImprovementPct)}% faster diff --git a/src/components/tabs/admin/UsersTab.jsx b/src/components/tabs/admin/UsersTab.jsx index 96d0b94..ff9a4d5 100644 --- a/src/components/tabs/admin/UsersTab.jsx +++ b/src/components/tabs/admin/UsersTab.jsx @@ -41,8 +41,7 @@ const ACCESS_MATRIX = [ { area: 'Brain', developer: 'Own + Full Access', admin: 'Full' }, { area: 'Schema Docs', developer: 'Own + Full Access', admin: 'Full' }, { area: 'Company Knowledge', developer: 'Own + Full Access', admin: 'Full' }, - { area: 'Slow Queries', developer: '—', admin: 'Full' }, - { area: 'Workload Analysis', developer: '—', admin: 'Full' }, + { area: 'Performance', developer: '—', admin: 'Full' }, ] const FALLBACK_ROLES = [ diff --git a/src/lib/features.js b/src/lib/features.js index 764f2d3..33975dc 100644 --- a/src/lib/features.js +++ b/src/lib/features.js @@ -15,8 +15,7 @@ const BASE_SECTION_MIN_ROLE = { ...(AGENTS_ENABLED ? { brain: ROLES.DEVELOPER } : {}), 'company-knowledge': ROLES.DEVELOPER, dashboards: ROLES.DEVELOPER, - 'slow-queries': ROLES.ADMIN, - 'workload-analysis': ROLES.ADMIN, + performance: ROLES.ADMIN, editor: ROLES.DEVELOPER, docs: ROLES.DEVELOPER, } @@ -38,6 +37,10 @@ function resolveSectionAlias(section) { // Schema Docs was folded into Company Knowledge → Schema Context tab. // Persisted nav state from older sessions still routes correctly. return 'company-knowledge' + case 'slow-queries': + case 'workload-analysis': + // Slow Queries and Workload Analysis were merged into Performance. + return 'performance' default: return section } @@ -75,8 +78,7 @@ export function getDefaultHomeSection(role, connection = null) { 'digest', ...(AGENTS_ENABLED ? ['brain'] : []), 'company-knowledge', - 'slow-queries', - 'workload-analysis', + 'performance', 'editor', 'docs', ] diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index be218bd..1ab662a 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -9,7 +9,6 @@ import DashboardsSection from '@/components/sections/DashboardsSection' import DocsSection from '@/components/sections/DocsSection' import EditorSection from '@/components/sections/EditorSection' import SlowQueriesSection from '@/components/sections/SlowQueriesSection' -import WorkloadAnalysisSection from '@/components/sections/WorkloadAnalysisSection' import PageTransitionBar from '@/components/layout/PageTransitionBar' import { useAuth } from '@/hooks/useAuth' import { AGENTS_ENABLED, canAccessHomeSection, normalizeHomeSection } from '@/lib/features' @@ -23,8 +22,7 @@ const SECTION_MAP = { digest: DigestFeedSection, ...(AGENTS_ENABLED ? { brain: BrainSection } : {}), 'company-knowledge': CompanyKnowledgeSection, - 'slow-queries': SlowQueriesSection, - 'workload-analysis': WorkloadAnalysisSection, + performance: SlowQueriesSection, editor: EditorSection, docs: DocsSection, } From cbcf45b751ad39c0792399067ec13cd29d4e44d8 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 14 Aug 2026 10:31:05 +0000 Subject: [PATCH 2/3] fix(ui): keep Configure slow queries CTA clickable Move HelpTooltip off the heading so it cannot cover the CTA, and add data-testid for the log-source button. Co-authored-by: Venkat SF --- src/components/sections/SlowQueriesSection.jsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/sections/SlowQueriesSection.jsx b/src/components/sections/SlowQueriesSection.jsx index c487551..eb320dd 100644 --- a/src/components/sections/SlowQueriesSection.jsx +++ b/src/components/sections/SlowQueriesSection.jsx @@ -61,19 +61,22 @@ export default function SlowQueriesSection() { ) : !hasLogSource ? (
-

+

Configure slow queries

+

- Configure slow queries + + Attach a slow-query log source to unlock query trends, per-customer + breakdown, and workload analysis. + - -

- Attach a slow-query log source to unlock query trends, per-customer - breakdown, and workload analysis. DeepSQL pulls from CloudWatch, S3, - Azure Blob, GCP, Datadog, Elasticsearch, or a file you upload. + {' '} + DeepSQL pulls from CloudWatch, S3, Azure Blob, GCP, Datadog, + Elasticsearch, or a file you upload.