diff --git a/apps/dashboard/components/logs/chart/index.tsx b/apps/dashboard/components/logs/chart/index.tsx index 0475a7871c..557076e2d6 100644 --- a/apps/dashboard/components/logs/chart/index.tsx +++ b/apps/dashboard/components/logs/chart/index.tsx @@ -11,10 +11,11 @@ import { formatNumber } from "@/lib/fmt"; import { Grid } from "@unkey/icons"; import { useEffect, useRef, useState } from "react"; import { Bar, BarChart, ReferenceArea, ResponsiveContainer, YAxis } from "recharts"; +import { createTimeIntervalFormatter } from "../overview-charts/utils"; import { LogsChartError } from "./components/logs-chart-error"; import { LogsChartLoading } from "./components/logs-chart-loading"; import { calculateTimePoints } from "./utils/calculate-timepoints"; -import { formatTimestampLabel, formatTimestampTooltip } from "./utils/format-timestamp"; +import { formatTimestampLabel } from "./utils/format-timestamp"; type Selection = { start: string | number; @@ -183,18 +184,7 @@ export function LogsTimeseriesBarChart({ } className="rounded-lg shadow-lg border border-gray-4" - labelFormatter={(_, tooltipPayload) => { - const originalTimestamp = tooltipPayload[0]?.payload?.originalTimestamp; - return originalTimestamp ? ( -
- - {formatTimestampTooltip(originalTimestamp)} - -
- ) : ( - "" - ); - }} + labelFormatter={(_, payload) => createTimeIntervalFormatter(data)(payload)} /> ); }} diff --git a/apps/dashboard/components/logs/overview-charts/overview-area-chart.tsx b/apps/dashboard/components/logs/overview-charts/overview-area-chart.tsx index db86019557..0a2d56aeb3 100644 --- a/apps/dashboard/components/logs/overview-charts/overview-area-chart.tsx +++ b/apps/dashboard/components/logs/overview-charts/overview-area-chart.tsx @@ -1,9 +1,6 @@ "use client"; import { calculateTimePoints } from "@/components/logs/chart/utils/calculate-timepoints"; -import { - formatTimestampLabel, - formatTimestampTooltip, -} from "@/components/logs/chart/utils/format-timestamp"; +import { formatTimestampLabel } from "@/components/logs/chart/utils/format-timestamp"; import { type ChartConfig, ChartContainer, @@ -24,6 +21,7 @@ import { import { OverviewAreaChartError } from "./overview-area-chart-error"; import { OverviewAreaChartLoader } from "./overview-area-chart-loader"; import type { Selection, TimeseriesData } from "./types"; +import { createTimeIntervalFormatter } from "./utils"; export type ChartMetric = { key: string; @@ -241,18 +239,9 @@ export const OverviewAreaChart = ({ label={label} active={active} className="rounded-lg shadow-lg border border-gray-4" - labelFormatter={(_, tooltipPayload) => { - const originalTimestamp = tooltipPayload[0]?.payload?.originalTimestamp; - return originalTimestamp ? ( -
- - {formatTimestampTooltip(originalTimestamp)} - -
- ) : ( - "" - ); - }} + labelFormatter={(_, tooltipPayload) => + createTimeIntervalFormatter(data)(tooltipPayload) + } /> ); }} diff --git a/apps/dashboard/components/logs/overview-charts/overview-bar-chart.tsx b/apps/dashboard/components/logs/overview-charts/overview-bar-chart.tsx index 3ad0a095f5..00d0fcece7 100644 --- a/apps/dashboard/components/logs/overview-charts/overview-bar-chart.tsx +++ b/apps/dashboard/components/logs/overview-charts/overview-bar-chart.tsx @@ -1,10 +1,7 @@ "use client"; import { calculateTimePoints } from "@/components/logs/chart/utils/calculate-timepoints"; -import { - formatTimestampLabel, - formatTimestampTooltip, -} from "@/components/logs/chart/utils/format-timestamp"; +import { formatTimestampLabel } from "@/components/logs/chart/utils/format-timestamp"; import { type ChartConfig, ChartContainer, @@ -18,6 +15,7 @@ import { Bar, BarChart, CartesianGrid, ReferenceArea, ResponsiveContainer, YAxis import { OverviewChartError } from "./overview-bar-chart-error"; import { OverviewChartLoader } from "./overview-bar-chart-loader"; import type { Selection, TimeseriesData } from "./types"; +import { createTimeIntervalFormatter } from "./utils"; type ChartTooltipItem = { label: string; @@ -244,18 +242,9 @@ export function OverviewBarChart({ } className="rounded-lg shadow-lg border border-gray-4" - labelFormatter={(_, tooltipPayload) => { - const originalTimestamp = tooltipPayload[0]?.payload?.originalTimestamp; - return originalTimestamp ? ( -
- - {formatTimestampTooltip(originalTimestamp)} - -
- ) : ( - "" - ); - }} + labelFormatter={(_, tooltipPayload) => + createTimeIntervalFormatter(data)(tooltipPayload) + } /> ); }} diff --git a/apps/dashboard/components/logs/overview-charts/utils.tsx b/apps/dashboard/components/logs/overview-charts/utils.tsx new file mode 100644 index 0000000000..56e0b84e18 --- /dev/null +++ b/apps/dashboard/components/logs/overview-charts/utils.tsx @@ -0,0 +1,70 @@ +// components/logs/chart/utils/format-interval.ts + +import { formatTimestampTooltip } from "../chart/utils/format-timestamp"; +import type { TimeseriesData } from "./types"; + +/** + * Creates a tooltip formatter that displays time intervals between data points + * + * @param data - The chart data array containing timestamp information + * @returns A formatter function for use with chart tooltips + */ +export function createTimeIntervalFormatter(data?: TimeseriesData[]) { + return (tooltipPayload: any[]) => { + // Basic validation checks + if (!tooltipPayload?.[0]?.payload) { + return ""; + } + + const currentPayload = tooltipPayload[0].payload; + const currentTimestamp = currentPayload.originalTimestamp; + const currentDisplayX = currentPayload.displayX; + + // If we don't have necessary data, fallback to displaying just the current point + if (!currentTimestamp || !currentDisplayX || !data?.length) { + return ( +
+ + {currentDisplayX || formatTimestampTooltip(currentTimestamp)} + +
+ ); + } + + // Find position in the data array + const currentIndex = data.findIndex((item) => item?.originalTimestamp === currentTimestamp); + + // If this is the last item or not found, just show current timestamp + if (currentIndex === -1 || currentIndex >= data.length - 1) { + return ( +
+ {currentDisplayX} +
+ ); + } + + // Get the next point in the sequence + const nextPoint = data[currentIndex + 1]; + if (!nextPoint) { + return ( +
+ {currentDisplayX} +
+ ); + } + + // Format the next timestamp + const nextDisplayX = + nextPoint.displayX || + (nextPoint.originalTimestamp ? formatTimestampTooltip(nextPoint.originalTimestamp) : ""); + + // Return formatted interval + return ( +
+ + {currentDisplayX} - {nextDisplayX} + +
+ ); + }; +} diff --git a/apps/dashboard/components/stats-card/components/chart/stats-chart.tsx b/apps/dashboard/components/stats-card/components/chart/stats-chart.tsx index 768db9b1a3..d81956cd91 100644 --- a/apps/dashboard/components/stats-card/components/chart/stats-chart.tsx +++ b/apps/dashboard/components/stats-card/components/chart/stats-chart.tsx @@ -1,6 +1,6 @@ "use client"; -import { formatTimestampTooltip } from "@/components/logs/chart/utils/format-timestamp"; +import { createTimeIntervalFormatter } from "@/components/logs/overview-charts/utils"; import { type ChartConfig, ChartContainer, @@ -97,18 +97,7 @@ export function StatsTimeseriesBarChart({ } className="rounded-lg shadow-lg border border-gray-4" - labelFormatter={(_, tooltipPayload) => { - const originalTimestamp = tooltipPayload[0]?.payload?.originalTimestamp; - return originalTimestamp ? ( -
- - {formatTimestampTooltip(originalTimestamp)} - -
- ) : ( - "" - ); - }} + labelFormatter={(_, payload) => createTimeIntervalFormatter(data)(payload)} /> ); }} diff --git a/internal/clickhouse/src/ratelimits.ts b/internal/clickhouse/src/ratelimits.ts index 498bf5043b..e9a844af78 100644 --- a/internal/clickhouse/src/ratelimits.ts +++ b/internal/clickhouse/src/ratelimits.ts @@ -126,7 +126,7 @@ function createTimeseriesQuery(interval: TimeInterval, whereClause: string) { ORDER BY x ASC WITH FILL FROM toUnixTimestamp64Milli(CAST(toStartOfInterval(toDateTime(fromUnixTimestamp64Milli({startTime: Int64})), INTERVAL ${interval.stepSize} ${interval.step}) AS DateTime64(3))) - TO toUnixTimestamp64Milli(CAST(toStartOfInterval(toDateTime(fromUnixTimestamp64Milli({endTime: Int64})), INTERVAL ${interval.stepSize} ${intervalUnit}) AS DateTime64(3))) + ${stepMs} + TO toUnixTimestamp64Milli(CAST(toStartOfInterval(toDateTime(fromUnixTimestamp64Milli({endTime: Int64})), INTERVAL ${interval.stepSize} ${interval.step}) AS DateTime64(3))) + ${stepMs} STEP ${stepMs}`; }