Implementation:Langfuse Langfuse ClickHouse Filter Factory
| Knowledge Sources | |
|---|---|
| Domains | Query Building, ClickHouse, Filtering |
| Last Updated | 2026-02-14 00:00 GMT |
Overview
Factory module that converts frontend filter state into type-safe ClickHouse SQL filter objects, preventing SQL injection by validating columns against UI column mappings and parameterizing user-supplied values.
Description
The ClickHouse Filter Factory is the central bridge between the Langfuse web UI filter state and ClickHouse query execution. It takes an array of FilterCondition objects (representing user-selected filters on traces, observations, scores, etc.) and produces an array of typed filter objects (e.g., StringFilter, DateTimeFilter, NumberFilter) that can be safely applied to ClickHouse queries.
Key security measures include:
- Column validation: Each filter column is matched against a whitelist of
UiColumnMappingsto ensure only valid ClickHouse columns are referenced. - Table name validation: The
isValidTableNameutility verifies that ClickHouse table names are legitimate, guarding against injection. - Parameterized values: All user-supplied filter values are sent as ClickHouse query parameters rather than inlined SQL, preventing SQL injection.
The module also exports getProjectIdDefaultFilter, a convenience function that creates default project-scoped filter lists for the three primary ClickHouse tables (traces, scores, observations).
A custom QueryBuilderError class is defined for descriptive error reporting when invalid columns or filter types are encountered.
Usage
Use createFilterFromFilterState whenever building a ClickHouse query that incorporates user-defined table filters from the Langfuse UI. Use getProjectIdDefaultFilter to quickly create the mandatory project ID filters required by virtually all ClickHouse queries.
Code Reference
Source Location
- Repository: Langfuse
- File: packages/shared/src/server/queries/clickhouse-sql/factory.ts
- Lines: 1-225
Signature
export class QueryBuilderError extends Error {
constructor(message: string);
}
export const createFilterFromFilterState = (
filter: FilterCondition[],
columnMapping: UiColumnMappings,
) => (StringFilter | DateTimeFilter | NumberFilter | /* ... other filter types */)[];
export function getProjectIdDefaultFilter(
projectId: string,
opts: { tracesPrefix: string },
): {
tracesFilter: FilterList;
scoresFilter: FilterList;
observationsFilter: FilterList;
};
Import
import {
createFilterFromFilterState,
getProjectIdDefaultFilter,
QueryBuilderError,
} from "@langfuse/shared/src/server/queries/clickhouse-sql/factory";
I/O Contract
Inputs
createFilterFromFilterState
| Name | Type | Required | Description |
|---|---|---|---|
| filter | FilterCondition[] |
Yes | Array of frontend filter conditions from the UI filter state |
| columnMapping | UiColumnMappings |
Yes | Whitelist of valid UI-to-ClickHouse column mappings for the target table |
getProjectIdDefaultFilter
| Name | Type | Required | Description |
|---|---|---|---|
| projectId | string |
Yes | The project ID to filter on |
| opts.tracesPrefix | string |
Yes | SQL prefix/alias for the traces table (e.g., "t") |
Outputs
createFilterFromFilterState
| Name | Type | Description |
|---|---|---|
| (return) | Array of filter objects | Array of typed filter instances (StringFilter, DateTimeFilter, NumberFilter, etc.) each with an apply() method returning { query, params }
|
getProjectIdDefaultFilter
| Name | Type | Description |
|---|---|---|
| tracesFilter | FilterList |
Project ID filter for the traces table |
| scoresFilter | FilterList |
Project ID filter for the scores table |
| observationsFilter | FilterList |
Project ID filter for the observations table |
Usage Examples
import { createFilterFromFilterState, getProjectIdDefaultFilter } from "./factory";
import { tracesTableUiColumnDefinitions } from "../../../tableDefinitions";
// Convert UI filter state to ClickHouse filters
const filters = createFilterFromFilterState(
[{ column: "name", type: "string", operator: "=", value: "my-trace" }],
tracesTableUiColumnDefinitions,
);
// Get default project ID filters for all tables
const { tracesFilter, scoresFilter, observationsFilter } =
getProjectIdDefaultFilter("project-123", { tracesPrefix: "t" });