6.3 KiB
6.3 KiB
Chunk 7: Jobs Pages
Parent: Build Graph Dashboard
Previous: Chunk 6: Partition Pages
Next: Chunk 8: Graph Analysis
Overview
Implement job listing and individual job metrics pages with performance data, success rates, and execution history.
Scope
In Scope
- Jobs listing page with high-level metadata
- Individual job metrics and performance pages
- Success rate tracking and trends
- Recent job runs with execution details
- Average duration and timing analysis
- Job label URL encoding for safe navigation
Out of Scope
- Complex performance analytics
- Historical trend analysis beyond recent runs
- Job configuration editing
- Advanced filtering beyond basic search
Technical Approach
Data Sources
From Build Graph Service API and build event log:
- Job list from graph analysis
- Job execution history from build events
- Performance metrics aggregated from event data
- Success/failure rates from job events
URL Encoding
// Handle job labels in URLs (similar to partition refs)
function encodeJobLabel(label: string): string {
return btoa(label).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
function decodeJobLabel(encoded: string): string {
const padded = encoded.replace(/-/g, '+').replace(/_/g, '/');
return atob(padded);
}
Component Structure
const JobsList = {
oninit: () => {
this.jobs = [];
this.searchTerm = '';
this.loadJobs();
},
view: () => [
m('.jobs-header', [
m('h1', 'Jobs'),
m('input', {
placeholder: 'Search jobs...',
oninput: (e) => this.searchTerm = e.target.value,
})
]),
m('.jobs-table', [
m('table.table', [
m('thead', [
m('tr', [
m('th', 'Job Label'),
m('th', 'Success Rate'),
m('th', 'Avg Duration'),
m('th', 'Recent Runs'),
m('th', 'Last Run'),
])
]),
m('tbody', this.filteredJobs().map(job =>
m('tr', [
m('td', m('a', {
href: `/jobs/${encodeJobLabel(job.label)}`
}, job.label)),
m('td', [
m('.badge', job.success_rate >= 0.9 ? 'success' : 'warning'),
` ${Math.round(job.success_rate * 100)}%`
]),
m('td', formatDuration(job.avg_duration)),
m('td', job.recent_runs),
m('td', formatTime(job.last_run)),
])
))
])
])
]
};
const JobMetrics = {
oninit: (vnode) => {
this.jobLabel = decodeJobLabel(vnode.attrs.label);
this.metrics = null;
this.recentRuns = [];
this.loadJobMetrics();
},
view: () => [
m('.job-header', [
m('h1', this.jobLabel),
m('.job-stats', [
m('.stat', [
m('.stat-title', 'Success Rate'),
m('.stat-value', `${Math.round(this.metrics?.success_rate * 100)}%`),
]),
m('.stat', [
m('.stat-title', 'Avg Duration'),
m('.stat-value', formatDuration(this.metrics?.avg_duration)),
]),
m('.stat', [
m('.stat-title', 'Total Runs'),
m('.stat-value', this.metrics?.total_runs),
]),
])
]),
m('.job-content', [
m('.performance-chart', [
m('h2', 'Performance Trends'),
m('.chart-placeholder', 'Success rate and duration trends over time'),
// Simple trend visualization or table
m('table.table', [
m('thead', [
m('tr', [
m('th', 'Date'),
m('th', 'Success Rate'),
m('th', 'Avg Duration'),
])
]),
m('tbody', this.metrics?.daily_stats?.map(stat =>
m('tr', [
m('td', formatDate(stat.date)),
m('td', `${Math.round(stat.success_rate * 100)}%`),
m('td', formatDuration(stat.avg_duration)),
])
))
])
]),
m('.recent-runs', [
m('h2', 'Recent Runs'),
m('table.table', [
m('thead', [
m('tr', [
m('th', 'Build Request'),
m('th', 'Partitions'),
m('th', 'Status'),
m('th', 'Duration'),
m('th', 'Started'),
])
]),
m('tbody', this.recentRuns.map(run =>
m('tr', [
m('td', m('a', { href: `/builds/${run.build_id}` }, run.build_id)),
m('td', run.partitions.join(', ')),
m('td', m('.badge', run.status)),
m('td', formatDuration(run.duration)),
m('td', formatTime(run.started_at)),
])
))
])
])
])
]
};
Metrics Calculation
From build event log:
- Success rate: completed jobs / total jobs
- Average duration: mean time from SCHEDULED to COMPLETED/FAILED
- Recent runs: last 50 job executions
- Daily aggregations for trend analysis
Implementation Strategy
-
Create Data Layer
- API integration for job data
- Metrics calculation from build events
- Search and filtering logic
-
Build Jobs List Page
- Job table with search
- High-level metrics display
- Performance indicators
-
Individual Job Pages
- Detailed metrics display
- Performance trends
- Recent runs history
-
Performance Visualization
- Simple trend charts or tables
- Success rate indicators
- Duration analysis
Deliverables
- Jobs listing page with search and metrics
- Individual job metrics pages
- Success rate tracking and display
- Performance trends visualization
- Recent job runs history
- Job label URL encoding/decoding
Success Criteria
- Jobs list loads with accurate metrics
- Individual job pages show detailed performance data
- Success rates are calculated correctly
- Performance trends are meaningful
- Recent runs link to build details
- URL encoding handles all job label formats
Testing
- Test jobs list search functionality
- Verify individual job pages load correctly
- Validate metrics calculations against known data
- Test performance trend accuracy
- Check recent runs links and data
- Validate URL encoding with complex job labels
- Test with jobs that have no runs yet