@@ -238,32 +238,35 @@ export class Traces {
238
238
const endDate = filter . period ?. to ?? new Date ( ) ;
239
239
const startDate = filter . period ?. from ?? subDays ( endDate , 14 ) ;
240
240
241
- const { unit, count : rangeUnits } = getBucketUnitAndCount ( startDate , endDate ) ;
242
-
243
- const bucketFunctionName = {
244
- minutes : 'MINUTE' ,
245
- hours : 'HOUR' ,
246
- days : 'DAY' ,
247
- weeks : 'WEEK' ,
248
- months : 'MONTH' ,
249
- } ;
241
+ const d = getBucketUnitAndCountNew ( startDate , endDate ) ;
250
242
243
+ const [ countStr , unit ] = d . candidate . name . split ( ' ' ) ;
251
244
const bucketStepFunctionName = {
252
- minutes : 'addMinutes' ,
253
- hours : 'addHours' ,
254
- days : 'addDays' ,
255
- weeks : 'addWeeks' ,
256
- months : 'addMonths' ,
245
+ MINUTE : 'addMinutes' ,
246
+ HOUR : 'addHours' ,
247
+ DAY : 'addDays' ,
248
+ WEEK : 'addWeeks' ,
249
+ MONTH : 'addMonths' ,
257
250
} ;
258
251
252
+ const addIntervalFn = sql . raw (
253
+ bucketStepFunctionName [ unit as keyof typeof bucketStepFunctionName ] ,
254
+ ) ;
255
+
259
256
const result = await this . clickHouse . query < unknown > ( {
260
257
query : sql `
261
258
WITH "time_bucket_list" AS (
262
259
SELECT
263
- ${ sql . raw ( bucketStepFunctionName [ unit ] ) } (toStartOfInterval(toDateTime(${ formatDate ( startDate ) } , 'UTC'), INTERVAL 1 ${ sql . raw ( bucketFunctionName [ unit ] ) } ), "number" + 1) AS "time_bucket"
260
+ ${ addIntervalFn } (
261
+ toStartOfInterval(
262
+ toDateTime(${ formatDate ( startDate ) } , 'UTC')
263
+ , INTERVAL ${ sql . raw ( d . candidate . name ) }
264
+ )
265
+ , "number" * ${ sql . raw ( countStr ) }
266
+ ) AS "time_bucket"
264
267
FROM
265
268
"system"."numbers"
266
- WHERE "system"."numbers"."number" < ${ String ( rangeUnits ) }
269
+ WHERE "system"."numbers"."number" < ${ String ( d . buckets ) }
267
270
)
268
271
SELECT
269
272
replaceOne(concat(toDateTime64("time_bucket_list"."time_bucket", 9, 'UTC'), 'Z'), ' ', 'T') AS "timeBucket"
@@ -276,7 +279,7 @@ export class Traces {
276
279
LEFT JOIN
277
280
(
278
281
SELECT
279
- toStartOfInterval("timestamp", INTERVAL 1 ${ sql . raw ( bucketFunctionName [ unit ] ) } ) AS "time_bucket"
282
+ toStartOfInterval("timestamp", INTERVAL ${ sql . raw ( d . candidate . name ) } ) AS "time_bucket"
280
283
, sumIf(1, "graphql_error_count" = 0) AS "ok_count_total"
281
284
, sumIf(1, "graphql_error_count" != 0) AS "error_count_total"
282
285
, sumIf(1, "graphql_error_count" = 0 ${ filterSQLFragment } ) AS "ok_count_filtered"
@@ -288,11 +291,11 @@ export class Traces {
288
291
AND "otel_traces_normalized"."timestamp" >= toDateTime(${ formatDate ( startDate ) } , 'UTC')
289
292
AND "otel_traces_normalized"."timestamp" <= toDateTime(${ formatDate ( endDate ) } , 'UTC')
290
293
GROUP BY
291
- "time_bucket"
294
+ "time_bucket"
292
295
) AS "t"
293
296
ON "t"."time_bucket" = "time_bucket_list"."time_bucket"
294
297
` ,
295
- queryId : `trace_status_breakdown_for_target_id_${ unit } _ ${ rangeUnits } ` ,
298
+ queryId : `trace_status_breakdown_for_target_id_` ,
296
299
timeout : 10_000 ,
297
300
} ) ;
298
301
@@ -519,45 +522,55 @@ export type Span = z.TypeOf<typeof SpanModel>;
519
522
type BucketResult = {
520
523
unit : 'minutes' | 'hours' | 'days' | 'weeks' | 'months' ;
521
524
count : number ;
525
+ interval : number ;
526
+ } ;
527
+
528
+ type BucketCandidate = {
529
+ name : string ;
530
+ seconds : number ;
522
531
} ;
523
532
524
- function getBucketUnitAndCount ( startDate : Date , endDate : Date ) : BucketResult {
525
- const MS_IN = {
526
- minute : 60 * 1000 ,
527
- hour : 60 * 60 * 1000 ,
528
- day : 24 * 60 * 60 * 1000 ,
529
- week : 7 * 24 * 60 * 60 * 1000 ,
533
+ const bucketCanditates : Array < BucketCandidate > = [
534
+ {
535
+ name : '1 MINUTE' ,
536
+ seconds : 60 ,
537
+ } ,
538
+ {
539
+ name : '5 MINUTE' ,
540
+ seconds : 60 * 5 ,
541
+ } ,
542
+ { name : '1 HOUR' , seconds : 60 * 60 } ,
543
+ { name : '4 HOUR' , seconds : 60 * 60 * 4 } ,
544
+ { name : '6 HOUR' , seconds : 60 * 60 * 6 } ,
545
+ { name : '1 DAY' , seconds : 60 * 60 * 24 } ,
546
+ { name : '1 WEEK' , seconds : 60 * 60 * 24 * 7 } ,
547
+ { name : '1 MONTH' , seconds : 60 * 60 * 24 * 30 } ,
548
+ ] ;
549
+
550
+ function getBucketUnitAndCountNew ( startDate : Date , endDate : Date , targetBuckets : number = 50 ) {
551
+ const diffSeconds = Math . floor ( ( endDate . getTime ( ) - startDate . getTime ( ) ) / 1000 ) ;
552
+
553
+ let best = {
554
+ candidate : bucketCanditates [ 0 ] ,
555
+ buckets : Math . floor ( diffSeconds / bucketCanditates [ 0 ] . seconds ) ,
530
556
} ;
531
557
532
- const diffMs = endDate . getTime ( ) - startDate . getTime ( ) ;
533
- const diffMinutes = diffMs / MS_IN . minute ;
534
-
535
- let unit : BucketResult [ 'unit' ] ;
536
- let count : BucketResult [ 'count' ] ;
537
-
538
- if ( diffMinutes <= 60 ) {
539
- unit = 'minutes' ;
540
- count = Math . ceil ( diffMs / MS_IN . minute ) ;
541
- } else if ( diffMinutes <= 60 * 24 ) {
542
- unit = 'hours' ;
543
- count = Math . ceil ( diffMs / MS_IN . hour ) ;
544
- } else if ( diffMinutes <= 60 * 24 * 30 ) {
545
- unit = 'days' ;
546
- count = Math . ceil ( diffMs / MS_IN . day ) ;
547
- } else if ( diffMinutes <= 60 * 24 * 30 * 90 ) {
548
- unit = 'weeks' ;
549
- count = Math . ceil ( diffMs / MS_IN . week ) ;
550
- } else {
551
- unit = 'months' ;
552
- // Calculate full months difference:
553
- const startYear = startDate . getFullYear ( ) ;
554
- const startMonth = startDate . getMonth ( ) ;
555
- const endYear = endDate . getFullYear ( ) ;
556
- const endMonth = endDate . getMonth ( ) ;
557
- count = ( endYear - startYear ) * 12 + ( endMonth - startMonth ) + 1 ;
558
+ let bestDiff = Number . POSITIVE_INFINITY ;
559
+
560
+ for ( const candidate of bucketCanditates ) {
561
+ const buckets = Math . floor ( diffSeconds / candidate . seconds ) ;
562
+
563
+ const diff = Math . abs ( buckets - targetBuckets ) ;
564
+ if ( diff < bestDiff ) {
565
+ bestDiff = diff ;
566
+ best = {
567
+ candidate,
568
+ buckets,
569
+ } ;
570
+ }
558
571
}
559
572
560
- return { unit , count } ;
573
+ return best ;
561
574
}
562
575
563
576
/**
0 commit comments