Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Langfuse Langfuse Event Query Builder

From Leeroopedia
Knowledge Sources
Domains ClickHouse, Query Building
Last Updated 2026-02-14 00:00 GMT

Overview

Provides a fluent, type-safe query builder hierarchy for constructing ClickHouse SQL queries against the events table, supporting field sets, aggregations, CTEs, JOINs, filtering, ordering, and pagination.

Description

This is the largest and most central query building module in Langfuse. It provides a class hierarchy for constructing all ClickHouse queries against the events table:

Field Definitions: The module defines EVENTS_FIELDS -- a complete mapping of field names to their SELECT expressions (e.g., id maps to e.span_id as id). It also defines FIELD_SETS -- predefined groupings of fields for common query patterns (base, calculated, io, metadata, tools, export, public API v2 groups, etc.). For trace-level aggregation, EVENTS_AGGREGATION_FIELDS provides field expressions using ClickHouse aggregation functions like argMaxIf, sumMap, groupUniqArrayIf, etc.

Class Hierarchy:

  1. AbstractQueryBuilder: Base class providing WHERE, ORDER BY, LIMIT, LIMIT BY, conditional chaining (when), and buildWithParams().
  2. AbstractCTEQueryBuilder: Extends the base with CTE (WITH clause) and LEFT JOIN support.
  3. BaseEventsQueryBuilder: Adds events-table-specific logic including automatic project_id filtering, orderByColumns with automatic project_id prepending for ClickHouse sort optimization, and the template method pattern for SELECT/GROUP BY.
  4. EventsQueryBuilder: The primary builder for observation-level queries. Supports selectFieldSet for predefined column groups, I/O field selection with truncation control, metadata expansion, direct metadata access for exports, and raw SELECT expressions.
  5. EventsAggregationQueryBuilder: For trace-level aggregation queries with GROUP BY trace_id, using aggregation fields.
  6. EventsAggQueryBuilder: For observation-level aggregation queries (e.g., filter option lookups) with custom GROUP BY and SELECT expressions.

The NoProjectId symbol allows explicitly opting out of automatic project_id filtering for cross-project queries.

Usage

Use EventsQueryBuilder for standard observation queries (list, detail, export). Use EventsAggregationQueryBuilder for trace-level queries that aggregate across observations. Use EventsAggQueryBuilder for filter option lookups. Chain methods fluently and call buildWithParams() to get the final SQL and parameters.

Code Reference

Source Location

Signature

export type OrderByDirection = "ASC" | "DESC";
export type OrderByEntry = { column: string; direction: OrderByDirection };
export type FieldSetName = keyof typeof FIELD_SETS;

export const NoProjectId: unique symbol;
export type NoProjectIdType = typeof NoProjectId;

// Abstract base classes (not exported but form the hierarchy)
// abstract class AbstractQueryBuilder
// abstract class AbstractCTEQueryBuilder extends AbstractQueryBuilder
// abstract class BaseEventsQueryBuilder<TFields> extends AbstractCTEQueryBuilder

export class EventsQueryBuilder extends BaseEventsQueryBuilder<typeof EVENTS_FIELDS> {
  constructor(options: { projectId: string | NoProjectIdType });
  selectFieldSet(...setNames: FieldSetName[]): this;
  selectIO(include: boolean, charLimit?: number): this;
  selectMetadataExpanded(keys: string[]): this;
  selectMetadataDirect(): this;
  selectRaw(...expressions: string[]): this;
  // Inherited: whereRaw, where, orderBy, orderByColumns, orderByDefault,
  //   limit, limitBy, when, withCTE, leftJoin, buildWithParams
}

export class EventsAggregationQueryBuilder extends BaseEventsQueryBuilder<typeof EVENTS_AGGREGATION_FIELDS> {
  constructor(options: { projectId: string | NoProjectIdType });
  selectFieldSet(...setNames: Array<keyof typeof AGGREGATION_FIELD_SETS>): this;
  // Inherited: same chainable methods
}

export class EventsAggQueryBuilder extends AbstractCTEQueryBuilder {
  constructor(options: {
    projectId: string;
    groupByColumn: string;
    selectExpression: string;
  });
  // Inherited: whereRaw, where, orderBy, limit, withCTE, leftJoin, buildWithParams
}

Import

import {
  EventsQueryBuilder,
  EventsAggregationQueryBuilder,
  EventsAggQueryBuilder,
  NoProjectId,
  type FieldSetName,
  type OrderByEntry,
} from "@langfuse/shared/src/server/queries/clickhouse-sql/event-query-builder";

I/O Contract

Inputs

Name Type Required Description
projectId string or NoProjectIdType Yes Project ID for automatic WHERE filtering, or NoProjectId to skip
setNames FieldSetName[] No Predefined field set names to include in SELECT (e.g., "base", "calculated", "io")
condition string No Raw WHERE clause condition with ClickHouse parameter syntax
params Record<string, any> No Parameter values for parameterized conditions
entries OrderByEntry[] No Structured ORDER BY entries with column and direction
limit / offset number No Pagination parameters

Outputs

Name Type Description
query string Complete ClickHouse SQL query string with parameterized placeholders
params Record<string, any> All accumulated parameter values for query execution

Usage Examples

import { EventsQueryBuilder } from "@langfuse/shared/src/server/queries/clickhouse-sql/event-query-builder";

// Build an observation list query
const builder = new EventsQueryBuilder({ projectId: "my-project-id" })
  .selectFieldSet("base", "calculated")
  .selectIO(true, 1000)
  .whereRaw("e.type = {type: String}", { type: "GENERATION" })
  .orderByColumns([
    { column: "e.start_time", direction: "DESC" },
    { column: "e.event_ts", direction: "DESC" },
  ])
  .limit(50, 0);

const { query, params } = builder.buildWithParams();
// Execute with ClickHouse client: clickhouse.query({ query, params })

// Aggregation query for traces
import { EventsAggregationQueryBuilder } from "...";

const aggBuilder = new EventsAggregationQueryBuilder({ projectId: "my-project-id" })
  .selectFieldSet("all")
  .whereRaw("e.start_time >= {from: DateTime64(3)}", { from: Date.now() - 86400000 })
  .orderByDefault()
  .limit(100, 0);

const { query: aggQuery, params: aggParams } = aggBuilder.buildWithParams();

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment