Skip to content

Commit f1ffbc7

Browse files
committed
improve bucket selection script
1 parent 77fc12a commit f1ffbc7

File tree

1 file changed

+65
-52
lines changed
  • packages/services/api/src/modules/operations/providers

1 file changed

+65
-52
lines changed

packages/services/api/src/modules/operations/providers/traces.ts

Lines changed: 65 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -238,32 +238,35 @@ export class Traces {
238238
const endDate = filter.period?.to ?? new Date();
239239
const startDate = filter.period?.from ?? subDays(endDate, 14);
240240

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);
250242

243+
const [countStr, unit] = d.candidate.name.split(' ');
251244
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',
257250
};
258251

252+
const addIntervalFn = sql.raw(
253+
bucketStepFunctionName[unit as keyof typeof bucketStepFunctionName],
254+
);
255+
259256
const result = await this.clickHouse.query<unknown>({
260257
query: sql`
261258
WITH "time_bucket_list" AS (
262259
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"
264267
FROM
265268
"system"."numbers"
266-
WHERE "system"."numbers"."number" < ${String(rangeUnits)}
269+
WHERE "system"."numbers"."number" < ${String(d.buckets)}
267270
)
268271
SELECT
269272
replaceOne(concat(toDateTime64("time_bucket_list"."time_bucket", 9, 'UTC'), 'Z'), ' ', 'T') AS "timeBucket"
@@ -276,7 +279,7 @@ export class Traces {
276279
LEFT JOIN
277280
(
278281
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"
280283
, sumIf(1, "graphql_error_count" = 0) AS "ok_count_total"
281284
, sumIf(1, "graphql_error_count" != 0) AS "error_count_total"
282285
, sumIf(1, "graphql_error_count" = 0 ${filterSQLFragment}) AS "ok_count_filtered"
@@ -288,11 +291,11 @@ export class Traces {
288291
AND "otel_traces_normalized"."timestamp" >= toDateTime(${formatDate(startDate)}, 'UTC')
289292
AND "otel_traces_normalized"."timestamp" <= toDateTime(${formatDate(endDate)}, 'UTC')
290293
GROUP BY
291-
"time_bucket"
294+
"time_bucket"
292295
) AS "t"
293296
ON "t"."time_bucket" = "time_bucket_list"."time_bucket"
294297
`,
295-
queryId: `trace_status_breakdown_for_target_id_${unit}_${rangeUnits}`,
298+
queryId: `trace_status_breakdown_for_target_id_`,
296299
timeout: 10_000,
297300
});
298301

@@ -519,45 +522,55 @@ export type Span = z.TypeOf<typeof SpanModel>;
519522
type BucketResult = {
520523
unit: 'minutes' | 'hours' | 'days' | 'weeks' | 'months';
521524
count: number;
525+
interval: number;
526+
};
527+
528+
type BucketCandidate = {
529+
name: string;
530+
seconds: number;
522531
};
523532

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),
530556
};
531557

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+
}
558571
}
559572

560-
return { unit, count };
573+
return best;
561574
}
562575

563576
/**

0 commit comments

Comments
 (0)