feat(LAM-1411): Add ability to filter based on custom SQL column in traces table#1570
Conversation
…races table Custom SQL columns can now be used as filter criteria in the traces table. When a user creates a custom column (e.g. a Token Ratio expression), it automatically appears in both the DataTableFilter and AdvancedSearch filter dropdowns with the correct data type (string or number operators). On the backend, custom column filter processors are dynamically built using the column's SQL expression and data type, so the WHERE clause uses the same SQL as the SELECT clause. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR enables custom SQL columns to appear in the filter dropdown for the traces table, covering both the Key changes:
Issues found:
Confidence Score: 3/5Safe to merge for the core filter feature, but the stats chart will visibly show unfiltered data when a custom column filter is active. The main traces table query is correctly updated. However, buildTracesStatsWhereConditions, buildTracesCountQueryWithParams, and buildTracesIdsQueryWithParams still use the static filter config, causing custom column filters to be silently ignored in those code paths. The stats chart inconsistency is immediately user-visible and was not possible before this PR, making it a clear regression introduced here. frontend/lib/actions/traces/utils.ts — buildTracesStatsWhereConditions (line 395), buildTracesCountQueryWithParams, and buildTracesIdsQueryWithParams all need to use buildFilterConfigWithCustomColumns. Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as TracesTableContent
participant DF as DataTableFilter / AdvancedSearch
participant API as /api/traces
participant QB as buildTracesQueryWithParams
participant SB as buildTracesStatsWhereConditions
UI->>DF: allFilters (staticFilters + customColumnFilters)
DF->>UI: filter URL param (e.g. custom:Token Ratio gt 0)
UI->>API: GET /traces?filter=custom:Token+Ratio:gt:0&customColumns=[...]
API->>QB: buildTracesQueryWithParams({ filters, customColumns })
QB->>QB: buildFilterConfigWithCustomColumns(customColumns)
QB-->>API: filtered SQL query ✅
UI->>API: GET /traces/stats?filter=custom:Token+Ratio:gt:0
API->>SB: buildTracesStatsWhereConditions({ filters })
SB->>SB: tracesColumnFilterConfig.processors.get("custom:Token Ratio") → undefined
SB-->>API: filter silently ignored ❌
API-->>UI: unfiltered stats data
|
Pass customColumns through to buildTracesCountQueryWithParams and buildTracesStatsWhereConditions so custom column filter processors are registered for all query paths, not just the main traces query. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Validate dbType against ["String", "Float64", "Int64"] in both the Zod schemas (input validation) and in buildFilterConfigWithCustomColumns (defense-in-depth fallback) to prevent arbitrary values from being interpolated into ClickHouse query templates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The useTimeSeriesStatsUrl hook was not including customColumns in the URL params, causing the stats/chart endpoint to silently drop custom column filters while the table correctly applied them. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sanitize filter.column in buildTracesStatsWhereConditions to match the pattern in buildColumnFilters (replace non-alphanumeric chars with underscore), preventing malformed ClickHouse parameter syntax for custom column keys like "custom:Token Ratio". - Extract parseCustomColumnsJson() helper in utils.ts to deduplicate the identical Zod schema + try/catch parsing block from getTraces, countTraces, and getTraceStats. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Both comments have been addressed: Comment 1 (Medium - unsanitized paramKey): Valid bug. Comment 2 (Low - duplicated parsing logic): Valid concern. The identical Zod schema + try/catch parsing block was copy-pasted in |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Export toColumnsPayload from the traces table store and use it in index.tsx instead of duplicating the column-to-payload mapping logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Summary
DataTableFilterandAdvancedSearch) with correct data types (string/number operators)dbTypeto custom column meta so the filter config can use the correct ClickHouse type for parameterized queriesChanges
frontend/lib/actions/traces/utils.ts: AddedbuildFilterConfigWithCustomColumns()that clones the static filter config and adds dynamic processors for each custom column. Used inbuildTracesQueryWithParamsinstead of the static config.frontend/components/traces/traces-table/index.tsx: Renamedfiltersimport tostaticFilters, addedallFiltersmemo that merges static filters with custom column filters (derived fromcustomColumnsstate). PassedallFiltersto bothDataTableFilterandAdvancedSearch.frontend/components/traces/traces-table/traces-table-store.ts: AddeddbTypeto custom column meta (Float64for number,Stringfor string) so the filter processor can cast parameters correctly.Screenshots
1. Custom column "Token Ratio" added to the table
2. Custom column appears in filter dropdown
3. Filter configured: Token Ratio > 0
4. Filtered results showing only traces with tokens
Video demo
Custom column filter demo (WebM)
Test plan
if(total_tokens > 0, input_tokens * 100 / total_tokens, 0), type Number)tsc --noEmit)Closes LAM-1411
🤖 Generated with Claude Code
Note
Medium Risk
Adds dynamic, user-defined column filtering that feeds into ClickHouse query construction; incorrect SQL/type handling could cause query errors or unexpected filtering. Changes touch both traces list and stats endpoints, affecting core query paths.
Overview
Custom SQL columns are now first-class filter targets in the traces UI: the traces table merges static filter definitions with persisted custom columns and passes them to both
DataTableFilterandAdvancedSearch.The backend now accepts a
customColumnspayload for traces list/count and stats queries, validates it viaparseCustomColumnsJson, and dynamically extends the column filter processor map to generate parameterized ClickHouse conditions (with basic type casting and safer parameter keys). Custom columns also carry adbType(Float64/String) so filters are typed correctly end-to-end.Written by Cursor Bugbot for commit 4922656. This will update automatically on new commits. Configure here.