Skip to content

Commit a1006d7

Browse files
committed
Add query stages view to Preview Web UI
1 parent 6f313c9 commit a1006d7

File tree

4 files changed

+578
-1
lines changed

4 files changed

+578
-1
lines changed

core/trino-web-ui/src/main/resources/webapp-preview/src/api/webapp/api.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,79 @@ export interface QueryRoutine {
217217
authorization: string
218218
}
219219

220+
export interface QueryStagePlan {
221+
id: string
222+
jsonRepresentation: string
223+
root: {
224+
id: string
225+
}
226+
}
227+
228+
export interface QueryStageStats {
229+
completedDrivers: number
230+
fullyBlocked: boolean
231+
totalCpuTime: string
232+
userMemoryReservation: string
233+
queuedDrivers: number
234+
runningDrivers: number
235+
processedInputDataSize: string
236+
processedInputPositions: number
237+
bufferedDataSize: string
238+
totalBlockedTime: string
239+
outputDataSize: string
240+
outputPositions: number
241+
totalScheduledTime: string
242+
failedScheduledTime: string
243+
failedCpuTime: string
244+
cumulativeUserMemory: number
245+
totalBufferedBytes: number
246+
failedCumulativeUserMemory: number
247+
peakUserMemoryReservation: string
248+
}
249+
250+
export interface QueryTask {
251+
lastHeartbeat: string
252+
needsPlan: boolean
253+
estimatedMemory: string
254+
outputBuffers: {
255+
totalBufferedBytes: number
256+
}
257+
stats: {
258+
createTime: string
259+
elapsedTime: string
260+
fullyBlocked: boolean
261+
blockedDrivers: number
262+
completedDrivers: number
263+
queuedDrivers: number
264+
peakUserMemoryReservation: string
265+
runningDrivers: number
266+
processedInputDataSize: string
267+
processedInputPositions: number
268+
totalCpuTime: string
269+
userMemoryReservation: string
270+
}
271+
taskStatus: {
272+
nodeId: string
273+
taskId: string
274+
self: string
275+
state: string
276+
}
277+
}
278+
279+
export interface QueryStage {
280+
coordinatorOnly: boolean
281+
plan: QueryStagePlan
282+
stageId: string
283+
state: string
284+
stageStats: QueryStageStats
285+
tasks: QueryTask[]
286+
}
287+
288+
export interface QueryStages {
289+
outputStageId: string
290+
stages: QueryStage[]
291+
}
292+
220293
export interface QueryStatusInfo extends QueryInfoBase {
221294
session: Session
222295
query: string
@@ -227,6 +300,11 @@ export interface QueryStatusInfo extends QueryInfoBase {
227300
finalQueryInfo: boolean
228301
referencedTables: QueryTable[]
229302
routines: QueryRoutine[]
303+
stages: QueryStages
304+
}
305+
306+
export interface WorkerTaskInfo {
307+
dummy: string
230308
}
231309

232310
export async function statsApi(): Promise<ApiResponse<Stats>> {
@@ -241,6 +319,10 @@ export async function workerStatusApi(nodeId: string): Promise<ApiResponse<Worke
241319
return await api.get<WorkerStatusInfo>(`/ui/api/worker/${nodeId}/status`)
242320
}
243321

322+
export async function workerTaskApi(nodeId: string, taskId: string): Promise<ApiResponse<WorkerTaskInfo>> {
323+
return await api.get<WorkerTaskInfo>(`/ui/api/worker/${nodeId}/task/${taskId}`)
324+
}
325+
244326
export async function queryApi(): Promise<ApiResponse<QueryInfo[]>> {
245327
return await api.get<QueryInfo[]>('/ui/api/query')
246328
}

core/trino-web-ui/src/main/resources/webapp-preview/src/components/QueryOverview.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
} from '@mui/material'
3030
import { SparkLineChart } from '@mui/x-charts/SparkLineChart'
3131
import { Texts } from '../constant.ts'
32-
import { StackInfo, queryStatusApi, QueryStatusInfo, Session } from '../api/webapp/api.ts'
32+
import { StackInfo, queryStatusApi, QueryStatusInfo, QueryStage, QueryStages, Session } from '../api/webapp/api.ts'
3333
import { ApiResponse } from '../api/base.ts'
3434
import {
3535
addToHistory,
@@ -40,10 +40,12 @@ import {
4040
parseDataSize,
4141
parseDuration,
4242
} from '../utils/utils.ts'
43+
import { QueryStageCard } from './QueryStageCard'
4344
import { CodeBlock } from './CodeBlock.tsx'
4445

4546
interface IQueryStatus {
4647
info: QueryStatusInfo | null
48+
lastSnapshotStages: QueryStages | null
4749

4850
lastScheduledTime: number
4951
lastCpuTime: number
@@ -66,6 +68,7 @@ export const QueryOverview = () => {
6668
const { queryId } = useParams()
6769
const initialQueryStatus: IQueryStatus = {
6870
info: null,
71+
lastSnapshotStages: null,
6972

7073
lastScheduledTime: 0,
7174
lastCpuTime: 0,
@@ -117,6 +120,7 @@ export const QueryOverview = () => {
117120
const newQueryStatusInfo: QueryStatusInfo = apiResponse.data
118121
setQueryStatus((prevQueryStatus) => {
119122
let lastRefresh = prevQueryStatus.lastRefresh
123+
120124
const lastScheduledTime = prevQueryStatus.lastScheduledTime
121125
const lastCpuTime = prevQueryStatus.lastCpuTime
122126
const lastPhysicalInputReadTime = prevQueryStatus.lastPhysicalInputReadTime
@@ -205,6 +209,7 @@ export const QueryOverview = () => {
205209

206210
return {
207211
info: newQueryStatusInfo,
212+
lastSnapshotStages: newQueryStatusInfo.stages,
208213

209214
lastScheduledTime: parseDuration(newQueryStats.totalScheduledTime) || 0,
210215
lastCpuTime: parseDuration(newQueryStats.totalCpuTime) || 0,
@@ -416,6 +421,38 @@ export const QueryOverview = () => {
416421
}
417422
}
418423

424+
const renderStages = (taskRetriesEnabled: boolean) => {
425+
const stages = queryStatus.lastSnapshotStages?.stages
426+
427+
return (
428+
<Grid size={{ xs: 12 }}>
429+
<Box sx={{ pt: 2 }}>
430+
<Typography variant="h6">Stages</Typography>
431+
<Divider />
432+
433+
{stages ? (
434+
stages
435+
.slice()
436+
.sort((a, b) => a.stageId.localeCompare(b.stageId))
437+
.map((stage: QueryStage) => (
438+
<QueryStageCard
439+
key={stage.stageId}
440+
stage={stage}
441+
taskRetriesEnabled={taskRetriesEnabled}
442+
/>
443+
))
444+
) : (
445+
<>
446+
<Box sx={{ width: '100%', mt: 1 }}>
447+
<Alert severity="info">No stage information available.</Alert>
448+
</Box>
449+
</>
450+
)}
451+
</Box>
452+
</Grid>
453+
)
454+
}
455+
419456
const taskRetriesEnabled = queryStatus.info?.retryPolicy == 'TASK'
420457
return (
421458
<>
@@ -839,6 +876,7 @@ export const QueryOverview = () => {
839876
</Box>
840877
</Grid>
841878
{renderPreparedQuery()}
879+
{renderStages(taskRetriesEnabled)}
842880
</Grid>
843881
</Grid>
844882
)}

0 commit comments

Comments
 (0)