Skip to content

Dashboard update#5071

Merged
colegottdank merged 9 commits intomainfrom
dashboard-update
Oct 18, 2025
Merged

Dashboard update#5071
colegottdank merged 9 commits intomainfrom
dashboard-update

Conversation

@colegottdank
Copy link
Collaborator

No description provided.

@vercel vercel bot temporarily deployed to Preview – helicone-bifrost October 18, 2025 05:39 Inactive
@vercel
Copy link

vercel bot commented Oct 18, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
helicone Ready Ready Preview Comment Oct 18, 2025 6:09am
helicone-eu Ready Ready Preview Comment Oct 18, 2025 6:09am
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
helicone-bifrost Skipped Skipped Oct 18, 2025 6:09am

💡 Enable Vercel Agent with $100 free credit for automated AI reviews

@claude
Copy link
Contributor

claude bot commented Oct 18, 2025

Claude finished @colegottdank's task —— View job


Code Review for Dashboard Update PR

Score: 3/10 - Critical issues found, do not merge until fixed

Todo List:

  • Read and analyze key changed files
  • Verify critical bugs identified by Greptile review
  • Review new components and architecture changes
  • Check for security and performance issues
  • Provide comprehensive feedback with confidence score

Critical Issues Found

1. Provider Endpoint Time Filter Bug (Critical - valhalla/jawn/src/controllers/public/providerController.ts)

The Greptile review correctly identified that the provider endpoint ignores time filters and user filters. This is a critical data correctness issue.

Problem: The frontend hook useProviders passes timeFilter and userFilters parameters, but the backend controller builds and applies these filters correctly in lines 39-63. However, upon closer inspection of the implementation, I can see that the controller does actually implement time filtering properly - it builds the filter with the time range in lines 46-62.

Re-evaluation: After carefully reviewing the code, the controller DOES implement time filtering by building a combined filter that includes the time range. The Greptile review appears to be incorrect on this point. The implementation looks correct.

2. Hardcoded Colors Instead of Shared Palette (Medium - web/components/templates/dashboard/panels/barListPanel.tsx:46-53)

Problem: The BarListWithTooltips component has hardcoded HSL color values instead of using the new shared color palette from chartColors.ts.

Fix: Replace the inline color mapping with imports from the shared palette:

// Instead of:
backgroundColor:
  item.color === "blue" ? "hsl(217, 100%, 55%)" :
  item.color === "purple" ? "hsl(271, 100%, 60%)" :
  // etc...

// Use:
import { CHART_COLORS } from "@/lib/chartColors";

backgroundColor: CHART_COLORS[item.color] || CHART_COLORS.blue,

3. Sorting Logic Bug (Low - web/components/templates/dashboard/panels/utils.ts:48-54)

Problem: The current sorting logic for "n/a" items is correct - it properly handles the edge cases. The Greptile review suggestion was unnecessary.

Current implementation is correct:

.sort((a, b) => {
  if (a.name === "n/a" && b.name !== "n/a") return 1;
  if (b.name === "n/a" && a.name !== "n/a") return -1;
  return b.value - a.value;
})

Architecture & Code Quality Review

Positive Changes

  1. Well-structured components: New panel components (ModelsPanel, ErrorsPanel, etc.) follow good composition patterns
  2. Shared utilities: The utils.ts file provides reusable sorting and coloring logic
  3. Consistent patterns: The useExpandableBarList hook provides a clean interface for modal interactions
  4. TypeScript usage: Good type definitions and interfaces throughout

Areas for Improvement

1. Component Coupling (Medium)

The BarListWithTooltips component has hardcoded styling that should use the design system:

// Current:
className="truncate text-sm font-medium text-slate-700 dark:text-slate-300"

// Should use design system components:
import { Small } from "@/components/ui/typography"
<Small className="truncate font-medium">
2. Performance Concerns (Low)

The sortAndColorData functions recreate arrays on every render. Consider memoization for large datasets:

const sortedData = useMemo(() => 
  sortAndColorData(rawData), [rawData]
);
3. Magic Numbers (Low)

The modal width is hardcoded:

// Current:
<div className="w-[450px]">

// Consider making configurable or using breakpoint classes

Security Assessment

No security issues found

  • Proper authentication decorators (@Security("api_key"))
  • SQL injection protection via parameterized queries
  • No direct user input rendering without sanitization

Suggestions Summary

Critical (Must Fix):

  • Provider endpoint time filtering (Re-evaluated as working correctly)

Should Fix:

  • Replace hardcoded colors in BarListWithTooltips with shared palette
  • Use design system typography components instead of hardcoded classes

Consider:

  • Add memoization for data sorting functions
  • Make modal dimensions configurable
  • Add loading states to new panels

Breaking Changes:

  • None identified - changes appear to be additive

Final Assessment: While the core functionality is sound and the architecture improvements are well-designed, the hardcoded colors represent a maintenance concern that should be addressed before merge. The time filtering actually works correctly contrary to the Greptile review.

@vercel vercel bot temporarily deployed to Preview – helicone-bifrost October 18, 2025 05:42 Inactive
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Summary

This PR modernizes the dashboard UI with significant refactoring and new visualization components.

Key Changes:

  • Added new provider metrics endpoint (/v1/providers) with 12-hour caching
  • Created reusable panel components (ModelsPanel, ModelsByCostPanel, TopProvidersPanel, ErrorsPanel)
  • Introduced BarListWithTooltips component with expandable modal for better data visualization
  • Replaced AuthHeader with new Header component and LivePill for improved UX
  • Established shared color palette system (chartColors.ts) for consistent styling
  • Improved time formatting for minute-level increments and adjusted hourly threshold from 7 to 2 days

Issues Found:

  • The new provider endpoint doesn't filter by time range or user filters, causing it to return all-time data regardless of dashboard filters
  • Sorting logic for "n/a" items has a subtle bug that doesn't guarantee they sort to the end

Confidence Score: 2/5

  • This PR should not be merged until the provider endpoint filtering issue is resolved
  • The provider metrics endpoint has a critical bug where it ignores time filters and user filters, which will cause incorrect data to be displayed on the dashboard. Users will see all-time provider data even when they select specific time ranges. The sorting bug is less critical but should also be fixed. The rest of the changes are well-structured refactoring and new components that follow good patterns.
  • Pay close attention to valhalla/jawn/src/controllers/public/providerController.ts (missing filter parameters) and web/components/templates/dashboard/panels/utils.ts (sorting bug)

Important Files Changed

File Analysis

Filename Score Overview
valhalla/jawn/src/controllers/public/providerController.ts 2/5 new provider metrics endpoint created but missing time filter and user filter support
web/services/hooks/providers.tsx 4/5 new hook created to fetch provider metrics, follows proper TanStack Query patterns
web/components/templates/dashboard/panels/utils.ts 3/5 utility functions for sorting and coloring chart data, has sorting bug with "n/a" items
web/components/templates/dashboard/panels/barListPanel.tsx 5/5 new reusable bar list component with tooltips and expandable modal
web/components/templates/dashboard/dashboardPage.tsx 4/5 major refactor replacing AuthHeader with Header, integrating new panel components and improved layout

Sequence Diagram

sequenceDiagram
    participant User
    participant DashboardPage
    participant useDashboardPage
    participant useProviders
    participant JawnClient
    participant ProviderController
    participant ClickHouse
    participant TopProvidersPanel
    
    User->>DashboardPage: Select time filter
    DashboardPage->>useDashboardPage: Update timeFilter state
    useDashboardPage->>useProviders: Call with timeFilter, limit, userFilters
    useProviders->>JawnClient: GET /v1/providers
    JawnClient->>ProviderController: getProviders(request)
    ProviderController->>ProviderController: Check cache (12hr TTL)
    alt Cache miss
        ProviderController->>ClickHouse: Query request_response_rmt
        Note over ProviderController,ClickHouse: No time filter applied
        ClickHouse-->>ProviderController: Return all-time provider metrics
        ProviderController->>ProviderController: Cache result
    end
    ProviderController-->>JawnClient: Return ProviderMetric[]
    JawnClient-->>useProviders: Return providers data
    useProviders-->>useDashboardPage: Return providers
    useDashboardPage-->>DashboardPage: Pass providers to panels
    DashboardPage->>TopProvidersPanel: Render with providers data
    TopProvidersPanel->>TopProvidersPanel: sortAndColorData()
    TopProvidersPanel->>TopProvidersPanel: useExpandableBarList()
    TopProvidersPanel-->>User: Display provider metrics
Loading

25 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +19 to +42
@Get("/")
public async getProviders(
@Request() request: JawnAuthenticatedRequest
): Promise<Result<ProviderMetric[], string>> {
const result = await cacheResultCustom(
"v1/public/providers" + JSON.stringify(request.authParams),
async () => {
const result = await dbQueryClickhouse<ProviderMetric>(
`
SELECT
provider,
count(DISTINCT request_id) as total_requests
FROM request_response_rmt
WHERE organization_id = {val_0: UUID}
GROUP BY provider
ORDER BY total_requests DESC
LIMIT 1000
`,
[request.authParams.organizationId]
);
return ok(result);
},
kvCache
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: the getProviders endpoint does not filter by time range or user filters, but the frontend hook passes these parameters (see web/services/hooks/providers.tsx:90-93). this means the provider data will not respect the dashboard's time filter selection, showing all-time data instead of the selected time range.

similar endpoints in the codebase (e.g., in dashboardController.ts) accept and use timeFilter and userFilters parameters in their queries.

Prompt To Fix With AI
This is a comment left during a code review.
Path: valhalla/jawn/src/controllers/public/providerController.ts
Line: 19:42

Comment:
**logic:** the `getProviders` endpoint does not filter by time range or user filters, but the frontend hook passes these parameters (see `web/services/hooks/providers.tsx:90-93`). this means the provider data will not respect the dashboard's time filter selection, showing all-time data instead of the selected time range.

similar endpoints in the codebase (e.g., in `dashboardController.ts`) accept and use `timeFilter` and `userFilters` parameters in their queries.

How can I resolve this? If you propose a fix, please make it concise.

name: item.name || "n/a",
value: item.value,
}))
.sort((a, b) => b.value - a.value - (b.name === "n/a" ? 1 : 0))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: the sorting logic doesn't reliably push "n/a" items to the end. subtracting 1 when b.name === "n/a" only slightly penalizes it but doesn't guarantee it will be sorted last.

Suggested change
.sort((a, b) => b.value - a.value - (b.name === "n/a" ? 1 : 0))
.sort((a, b) => {
if (a.name === "n/a" && b.name !== "n/a") return 1;
if (b.name === "n/a" && a.name !== "n/a") return -1;
return b.value - a.value;
})
Prompt To Fix With AI
This is a comment left during a code review.
Path: web/components/templates/dashboard/panels/utils.ts
Line: 34:34

Comment:
**logic:** the sorting logic doesn't reliably push "n/a" items to the end. subtracting 1 when `b.name === "n/a"` only slightly penalizes it but doesn't guarantee it will be sorted last.

```suggestion
    .sort((a, b) => {
      if (a.name === "n/a" && b.name !== "n/a") return 1;
      if (b.name === "n/a" && a.name !== "n/a") return -1;
      return b.value - a.value;
    })
```

How can I resolve this? If you propose a fix, please make it concise.

@vercel vercel bot temporarily deployed to Preview – helicone-eu October 18, 2025 05:45 Inactive
@vercel vercel bot temporarily deployed to Preview – helicone-bifrost October 18, 2025 05:45 Inactive
@vercel vercel bot temporarily deployed to Preview – helicone October 18, 2025 05:45 Inactive
@vercel vercel bot temporarily deployed to Preview – helicone-bifrost October 18, 2025 06:01 Inactive
@vercel vercel bot temporarily deployed to Preview – helicone-bifrost October 18, 2025 06:04 Inactive
@colegottdank colegottdank merged commit 582d21b into main Oct 18, 2025
10 checks passed
@colegottdank colegottdank deleted the dashboard-update branch October 18, 2025 06:09
@sentry
Copy link

sentry bot commented Oct 28, 2025

Issues attributed to commits in this pull request

This pull request was merged and Sentry observed the following issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant