Skip to content

Commit ce4e637

Browse files
committed
add time range filter
1 parent f478439 commit ce4e637

File tree

5 files changed

+126
-20
lines changed

5 files changed

+126
-20
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Button } from '@/components/ui/button'
2+
import { cn } from '@/lib/utils'
3+
import { DateRange } from 'react-day-picker'
4+
import { DateRangePicker } from '@/components/ui/date-range-picker'
5+
6+
interface TimeRangeProps {
7+
timeRange: string
8+
onTimeRangeChange: (range: string) => void
9+
dateRange: DateRange | undefined
10+
onDateRangeChange: (range: DateRange | undefined) => void
11+
className?: string
12+
}
13+
14+
export function TimeRange({
15+
timeRange,
16+
onTimeRangeChange,
17+
dateRange,
18+
onDateRangeChange,
19+
className
20+
}: TimeRangeProps) {
21+
return (
22+
<div className={cn("flex items-center gap-2", className)}>
23+
<div className="flex gap-1">
24+
<Button
25+
variant={timeRange === 'hourly' ? 'default' : 'outline'}
26+
size="sm"
27+
onClick={() => onTimeRangeChange('hourly')}
28+
>
29+
Hourly
30+
</Button>
31+
<Button
32+
variant={timeRange === 'daily' ? 'default' : 'outline'}
33+
size="sm"
34+
onClick={() => onTimeRangeChange('daily')}
35+
>
36+
Daily
37+
</Button>
38+
<Button
39+
variant={timeRange === 'monthly' ? 'default' : 'outline'}
40+
size="sm"
41+
onClick={() => onTimeRangeChange('monthly')}
42+
>
43+
Monthly
44+
</Button>
45+
</div>
46+
<DateRangePicker
47+
initialDateRange={dateRange}
48+
onChange={onDateRangeChange}
49+
/>
50+
</div>
51+
)
52+
}

apps/web/src/components/tools/vercel_logs/dashboard.tsx

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import { CacheStatsChart } from './cache-stats-chart'
99
import { ResponseTimesChart } from './response-times-chart'
1010
import { TopPathsTable } from './top-paths-table'
1111
import { VercelFilters } from './filters'
12+
import { TimeRange } from '../shared/time-range'
13+
import { format } from 'date-fns'
14+
import { addDays } from 'date-fns'
15+
import { DateRange } from 'react-day-picker'
1216

1317
export default function VercelLogsDashboard() {
1418
const [token] = useQueryState('token')
@@ -30,6 +34,11 @@ export default function VercelLogsDashboard() {
3034
const [cacheStatsData, setCacheStatsData] = useState<any[]>([])
3135
const [topPathsPage, setTopPathsPage] = useState(0)
3236
const [topPathsLoading, setTopPathsLoading] = useState(false)
37+
const [timeRange, setTimeRange] = useState('daily')
38+
const [dateRange, setDateRange] = useState<DateRange>({
39+
from: addDays(new Date(), -7),
40+
to: new Date()
41+
})
3342

3443
const fetchTopPaths = async () => {
3544
if (!token) return
@@ -63,7 +72,10 @@ export default function VercelLogsDashboard() {
6372
host,
6473
project,
6574
event_type: eventType,
66-
source
75+
source,
76+
time_range: timeRange,
77+
...(dateRange?.from && { date_from: format(dateRange.from, 'yyyy-MM-dd HH:mm:ss') }),
78+
...(dateRange?.to && { date_to: format(dateRange.to, 'yyyy-MM-dd 23:59:59') })
6779
}
6880

6981
try {
@@ -93,28 +105,37 @@ export default function VercelLogsDashboard() {
93105

94106
useEffect(() => {
95107
fetchMetrics()
96-
}, [token, environment, host, project, eventType, source])
108+
}, [token, environment, host, project, eventType, source, timeRange, dateRange])
97109

98110
useEffect(() => {
99111
fetchTopPaths()
100-
}, [token, environment, host, project, eventType, source, topPathsPage])
112+
}, [token, environment, host, project, eventType, source, topPathsPage, timeRange, dateRange])
101113

102114
return (
103115
<div className="space-y-8">
104-
<VercelFilters
105-
token={token ?? ''}
106-
className="mb-8"
107-
environment={environment}
108-
host={host}
109-
project={project}
110-
eventType={eventType}
111-
source={source}
112-
onEnvironmentChange={setEnvironment}
113-
onHostChange={setHost}
114-
onProjectChange={setProject}
115-
onEventTypeChange={setEventType}
116-
onSourceChange={setSource}
117-
/>
116+
<div className="flex justify-between items-start">
117+
<VercelFilters
118+
token={token ?? ''}
119+
className="mb-8"
120+
environment={environment}
121+
host={host}
122+
project={project}
123+
eventType={eventType}
124+
source={source}
125+
onEnvironmentChange={setEnvironment}
126+
onHostChange={setHost}
127+
onProjectChange={setProject}
128+
onEventTypeChange={setEventType}
129+
onSourceChange={setSource}
130+
/>
131+
<TimeRange
132+
timeRange={timeRange}
133+
onTimeRangeChange={setTimeRange}
134+
dateRange={dateRange}
135+
onDateRangeChange={(range) => setDateRange(range || { from: new Date(), to: addDays(new Date(), 7) })}
136+
className="mb-8"
137+
/>
138+
</div>
118139
{/* Metrics Row */}
119140
<div className="grid gap-4 md:grid-cols-3">
120141
<Card>

tinybird/pipes/vercel_cache_stats.pipe

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,18 @@ NODE cache_stats
66
SQL >
77
%
88
SELECT
9-
toStartOfHour(event_time) as hour,
9+
{% if defined(time_range) %}
10+
{% if time_range == 'monthly' %}
11+
toStartOfMonth(event_time)
12+
{% elif time_range == 'daily' %}
13+
toDate(event_time)
14+
{% else %}
15+
toStartOfHour(event_time)
16+
{% end %}
17+
{% else %}
18+
toDate(event_time)
19+
{% end %}
20+
as hour,
1021
count() as total_requests,
1122
countIf(event.proxy.vercelCache = 'HIT') as cache_hits,
1223
round(countIf(event.proxy.vercelCache = 'HIT') * 100.0 / count(), 2) as hit_rate

tinybird/pipes/vercel_errors.pipe

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,18 @@ NODE errors_over_time
66
SQL >
77
%
88
SELECT
9-
toStartOfHour(event_time) as hour,
9+
{% if defined(time_range) %}
10+
{% if time_range == 'monthly' %}
11+
toStartOfMonth(event_time)
12+
{% elif time_range == 'daily' %}
13+
toDate(event_time)
14+
{% else %}
15+
toStartOfHour(event_time)
16+
{% end %}
17+
{% else %}
18+
toDate(event_time)
19+
{% end %}
20+
as hour,
1021
countIf(event.proxy.statusCode::Int32 >= 400) as error_count,
1122
count() as total_requests,
1223
round(countIf(event.proxy.statusCode::Int32 >= 400) * 100.0 / count(), 2) as error_rate

tinybird/pipes/vercel_response_times.pipe

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,18 @@ NODE response_times
66
SQL >
77
%
88
SELECT
9-
toStartOfHour(event_time) as hour,
9+
{% if defined(time_range) %}
10+
{% if time_range == 'monthly' %}
11+
toStartOfMonth(event_time)
12+
{% elif time_range == 'daily' %}
13+
toDate(event_time)
14+
{% else %}
15+
toStartOfHour(event_time)
16+
{% end %}
17+
{% else %}
18+
toDate(event_time)
19+
{% end %}
20+
as hour,
1021
round(avg(toFloat64OrZero(duration)), 2) as avg_duration,
1122
round(quantile(0.95)(toFloat64OrZero(duration)), 2) as p95_duration,
1223
round(max(toFloat64OrZero(duration)), 2) as max_duration

0 commit comments

Comments
 (0)