import { queryClickhouse, measureAndReturn, getTimeframesTracesAMT, } from "@langfuse/shared/src/server"; import { QueryBuilder } from "@/src/features/query/server/queryBuilder"; import { type QueryType } from "@/src/features/query/types"; /** * Execute a query using the QueryBuilder. * * @param projectId - The project ID * @param query - The query configuration as defined in QueryType * @returns The query result data */ export async function executeQuery( projectId: string, query: QueryType, ): Promise>> { const { query: compiledQuery, parameters } = new QueryBuilder( query.chartConfig, ).build(query, projectId); // Check if the query contains trace table references const usesTraceTable = compiledQuery.includes("traces"); if (!usesTraceTable) { // No trace table placeholders, execute normally const result = await queryClickhouse>({ query: compiledQuery, params: parameters, clickhouseConfigs: { clickhouse_settings: { date_time_output_format: "iso", }, }, tags: { feature: "custom-queries", type: query.view, kind: "analytic", projectId, }, }); return result; } // Use measureAndReturn for trace table queries return measureAndReturn({ operationName: "executeQuery", projectId, minStartTime: new Date(query.fromTimestamp), input: { query: compiledQuery, params: parameters, fromTimestamp: query.fromTimestamp, tags: { feature: "custom-queries", type: query.view, kind: "analytic", projectId, operation_name: "executeQuery", }, }, existingExecution: async (input) => { return queryClickhouse>({ query: input.query, params: input.params, clickhouseConfigs: { clickhouse_settings: { date_time_output_format: "iso", }, }, tags: { ...input.tags, experiment_amt: "original" }, }); }, newExecution: async (input) => { const traceTable = getTimeframesTracesAMT(new Date(input.fromTimestamp)); return queryClickhouse>({ query: input.query.replaceAll("traces", traceTable), params: input.params, clickhouseConfigs: { clickhouse_settings: { date_time_output_format: "iso", }, }, tags: { ...input.tags, experiment_amt: "new" }, }); }, }); }