@@ -21,9 +21,9 @@ import {
2121} from "~/v3/eventRepository/clickhouseEventRepository.server" ;
2222import { ServiceValidationError } from "~/v3/services/baseService.server" ;
2323import {
24- escapeClickHouseLike ,
2524 hasMinimumLogsSearchLength ,
2625 logsSearchExpansionPeriod ,
26+ logsSearchPredicate ,
2727 LOGS_SEARCH_RETRY_OVERFETCH_FACTOR ,
2828 MIN_LOGS_SEARCH_LENGTH ,
2929 normalizeLogsSearchTerm ,
@@ -255,21 +255,26 @@ export class LogsListPresenter extends BasePresenter {
255255 `Log searches must be at least ${ MIN_LOGS_SEARCH_LENGTH } characters.`
256256 ) ;
257257 }
258- const searchTerm =
259- normalizedSearchTerm === "" ? undefined : escapeClickHouseLike ( normalizedSearchTerm ) ;
258+ const searchPredicate =
259+ normalizedSearchTerm === "" ? undefined : logsSearchPredicate ( normalizedSearchTerm ) ;
260260
261261 // Run exactly one bounded query. Broadening a search window is an explicit user action;
262262 // silently rescanning the same recent rows makes absence queries needlessly expensive.
263263 const runQuery = ( ) => {
264264 const queryBuilder = this . clickhouse . taskEventsSearch . logsListQueryBuilder ( {
265265 // Scoped to this query rather than the logs client, which other pages share. ClickHouse
266266 // skips lazy materialization when LIMIT exceeds the max, so pass this query's limit.
267- settings : env . CLICKHOUSE_LOGS_LIST_LAZY_MATERIALIZATION
268- ? {
269- query_plan_optimize_lazy_materialization : 1 ,
270- query_plan_max_limit_for_lazy_materialization : queryLimit ,
271- }
272- : undefined ,
267+ settings : {
268+ ...( env . CLICKHOUSE_LOGS_LIST_LAZY_MATERIALIZATION
269+ ? {
270+ query_plan_optimize_lazy_materialization : 1 ,
271+ query_plan_max_limit_for_lazy_materialization : queryLimit ,
272+ }
273+ : { } ) ,
274+ ...( searchPredicate && searchPredicate . kind !== "word"
275+ ? { ignore_data_skipping_indices : "idx_search_text,idx_search_words" }
276+ : { } ) ,
277+ } ,
273278 } ) ;
274279
275280 // The projector excludes events without a trace_id.
@@ -308,9 +313,13 @@ export class LogsListPresenter extends BasePresenter {
308313 queryBuilder . where ( "run_id = {runId: String}" , { runId } ) ;
309314 }
310315
311- if ( searchTerm !== undefined ) {
316+ if ( searchPredicate ?. kind === "word" ) {
317+ queryBuilder . where ( "hasAllTokens(concat(search_text, ''), {searchTokens: String})" , {
318+ searchTokens : searchPredicate . term ,
319+ } ) ;
320+ } else if ( searchPredicate ) {
312321 queryBuilder . where ( "search_text LIKE {searchPattern: String}" , {
313- searchPattern : `% ${ searchTerm } %` ,
322+ searchPattern : searchPredicate . pattern ,
314323 } ) ;
315324 }
316325
@@ -378,7 +387,7 @@ export class LogsListPresenter extends BasePresenter {
378387 if ( queryError ) {
379388 if ( isClickhouseResourceLimitError ( queryError ) ) {
380389 throw new ServiceValidationError (
381- searchTerm === undefined
390+ searchPredicate === undefined
382391 ? "These logs took too long to load. Try a shorter time range or add a filter."
383392 : "This search took too long. Try a shorter time range, a more specific search, or add a filter."
384393 ) ;
@@ -440,7 +449,7 @@ export class LogsListPresenter extends BasePresenter {
440449 } ) ;
441450
442451 const searchExpansion =
443- searchTerm !== undefined && time . isDefault && transformedLogs . length === 0
452+ searchPredicate !== undefined && time . isDefault && transformedLogs . length === 0
444453 ? logsSearchExpansionPeriod ( effectiveFrom , clampedTo , retentionLimitDays )
445454 : undefined ;
446455
0 commit comments