@@ -18,7 +18,7 @@ import {
1818 convertClickhouseDateTime64ToJsDate ,
1919} from "~/v3/eventRepository/clickhouseEventRepository.server" ;
2020
21- export type LogLevel = "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "LOG " ;
21+ export type LogLevel = "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "CANCELLED " ;
2222
2323export type LogsListOptions = {
2424 userId ?: string ;
@@ -78,9 +78,17 @@ function decodeCursor(cursor: string): LogCursor | null {
7878}
7979
8080// Convert ClickHouse kind to display level
81- function kindToLevel (
82- kind : string
83- ) : "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "LOG" {
81+ function kindToLevel ( kind : string , status : string ) : LogLevel {
82+ // CANCELLED status takes precedence
83+ if ( status === "CANCELLED" ) {
84+ return "CANCELLED" ;
85+ }
86+
87+ // ERROR can come from either kind or status
88+ if ( kind === "LOG_ERROR" || status === "ERROR" ) {
89+ return "ERROR" ;
90+ }
91+
8492 switch ( kind ) {
8593 case "DEBUG_EVENT" :
8694 case "LOG_DEBUG" :
@@ -89,10 +97,8 @@ function kindToLevel(
8997 return "INFO" ;
9098 case "LOG_WARN" :
9199 return "WARN" ;
92- case "LOG_ERROR" :
93- return "ERROR" ;
94100 case "LOG_LOG" :
95- return "LOG" ;
101+ return "INFO" ; // Changed from "LOG"
96102 case "SPAN" :
97103 case "ANCESTOR_OVERRIDE" :
98104 case "SPAN_EVENT" :
@@ -101,21 +107,23 @@ function kindToLevel(
101107 }
102108}
103109
104- // Convert display level to ClickHouse kinds
105- function levelToKinds ( level : LogLevel ) : string [ ] {
110+ // Convert display level to ClickHouse kinds and statuses
111+ function levelToKindsAndStatuses (
112+ level : LogLevel
113+ ) : { kinds ?: string [ ] ; statuses ?: string [ ] } {
106114 switch ( level ) {
107115 case "DEBUG" :
108- return [ "DEBUG_EVENT" , "LOG_DEBUG" ] ;
116+ return { kinds : [ "DEBUG_EVENT" , "LOG_DEBUG" ] } ;
109117 case "INFO" :
110- return [ "LOG_INFO" ] ;
118+ return { kinds : [ "LOG_INFO" , "LOG_LOG" ] } ;
111119 case "WARN" :
112- return [ "LOG_WARN" ] ;
120+ return { kinds : [ "LOG_WARN" ] } ;
113121 case "ERROR" :
114- return [ "LOG_ERROR" ] ;
115- case "LOG " :
116- return [ "LOG_LOG" ] ;
122+ return { kinds : [ "LOG_ERROR" ] , statuses : [ "ERROR" ] } ;
123+ case "CANCELLED " :
124+ return { statuses : [ "CANCELLED" ] } ;
117125 case "TRACE" :
118- return [ "SPAN" , "ANCESTOR_OVERRIDE" , "SPAN_EVENT" ] ;
126+ return { kinds : [ "SPAN" , "ANCESTOR_OVERRIDE" , "SPAN_EVENT" ] } ;
119127 }
120128}
121129
@@ -395,10 +403,45 @@ export class LogsListPresenter {
395403 ) ;
396404 }
397405
398- // Level filter (map display levels to ClickHouse kinds)
406+ // Level filter (map display levels to ClickHouse kinds/statuses )
399407 if ( levels && levels . length > 0 ) {
400- const kinds = levels . flatMap ( levelToKinds ) ;
401- queryBuilder . where ( "kind IN {kinds: Array(String)}" , { kinds } ) ;
408+ const conditions : string [ ] = [ ] ;
409+ const params : Record < string , unknown > = { } ;
410+ const hasTraceLevel = levels . includes ( "TRACE" ) ;
411+ const hasErrorOrCancelledLevel = levels . includes ( "ERROR" ) || levels . includes ( "CANCELLED" ) ;
412+
413+ for ( const level of levels ) {
414+ const filter = levelToKindsAndStatuses ( level ) ;
415+ const levelConditions : string [ ] = [ ] ;
416+
417+ if ( filter . kinds && filter . kinds . length > 0 ) {
418+ const kindsKey = `kinds_${ level } ` ;
419+ let kindCondition = `kind IN {${ kindsKey } : Array(String)}` ;
420+
421+ // For TRACE: exclude error/cancelled traces if ERROR/CANCELLED not explicitly selected
422+ if ( level === "TRACE" && ! hasErrorOrCancelledLevel ) {
423+ kindCondition += ` AND status NOT IN {excluded_statuses: Array(String)}` ;
424+ params [ "excluded_statuses" ] = [ "ERROR" , "CANCELLED" ] ;
425+ }
426+
427+ levelConditions . push ( kindCondition ) ;
428+ params [ kindsKey ] = filter . kinds ;
429+ }
430+
431+ if ( filter . statuses && filter . statuses . length > 0 ) {
432+ const statusesKey = `statuses_${ level } ` ;
433+ levelConditions . push ( `status IN {${ statusesKey } : Array(String)}` ) ;
434+ params [ statusesKey ] = filter . statuses ;
435+ }
436+
437+ if ( levelConditions . length > 0 ) {
438+ conditions . push ( `(${ levelConditions . join ( " OR " ) } )` ) ;
439+ }
440+ }
441+
442+ if ( conditions . length > 0 ) {
443+ queryBuilder . where ( `(${ conditions . join ( " OR " ) } )` ) ;
444+ }
402445 }
403446
404447 // Exclude DEBUG logs if not included
@@ -474,7 +517,7 @@ export class LogsListPresenter {
474517 kind : log . kind ,
475518 status : log . status ,
476519 duration : typeof log . duration === "number" ? log . duration : Number ( log . duration ) ,
477- level : kindToLevel ( log . kind ) ,
520+ level : kindToLevel ( log . kind , log . status ) ,
478521 } ) ) ;
479522
480523 return {
0 commit comments