Skip to content

Commit e429968

Browse files
committed
Create WorkersDetail component
1 parent 7e7b13f commit e429968

3 files changed

Lines changed: 176 additions & 157 deletions

File tree

src/components/PlanNodeDetail.vue

Lines changed: 4 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,11 @@ import { computed, inject, onBeforeMount, reactive, ref, watch } from "vue"
33
import type { Ref } from "vue"
44
import { directive as vTippy } from "vue-tippy"
55
import type { IPlan, Node, ViewOptions } from "@/interfaces"
6-
import { HelpService } from "@/services/help-service"
6+
import { HelpService, shouldShowProp } from "@/services/help-service"
77
import { formatNodeProp } from "@/filters"
8-
import {
9-
EstimateDirection,
10-
NodeProp,
11-
nodePropTypes,
12-
PropType,
13-
WorkerProp,
14-
} from "@/enums"
8+
import { EstimateDirection, NodeProp } from "@/enums"
159
import useNode from "@/node"
10+
import WorkersDetail from "@/components/WorkersDetail.vue"
1611
import { PlanKey, ViewOptionsKey } from "@/symbols"
1712
import _ from "lodash"
1813
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"
@@ -39,7 +34,6 @@ const nodeProps = ref<
3934
const activeTab = ref<string>("general")
4035
4136
const helpService = new HelpService()
42-
const getHelpMessage = helpService.getHelpMessage
4337
const getNodeTypeDescription = helpService.getNodeTypeDescription
4438
4539
const {
@@ -54,74 +48,8 @@ const {
5448
rowsRemovedClass,
5549
rowsRemovedPercentString,
5650
rowsRemovedProp,
57-
workersLaunchedCount,
5851
} = useNode(plan, node, viewOptions)
5952
60-
// Returns the list of properties that have already been displayed either in
61-
// the main panel or in other detailed tabs.
62-
const notMiscProperties: string[] = [
63-
NodeProp.NODE_TYPE,
64-
NodeProp.CTE_NAME,
65-
NodeProp.EXCLUSIVE_DURATION,
66-
NodeProp.EXCLUSIVE_COST,
67-
NodeProp.TOTAL_COST,
68-
NodeProp.PLAN_ROWS,
69-
NodeProp.ACTUAL_ROWS,
70-
NodeProp.ACTUAL_LOOPS,
71-
NodeProp.OUTPUT,
72-
NodeProp.WORKERS,
73-
NodeProp.WORKERS_PLANNED,
74-
NodeProp.WORKERS_LAUNCHED,
75-
NodeProp.EXCLUSIVE_SHARED_HIT_BLOCKS,
76-
NodeProp.EXCLUSIVE_SHARED_READ_BLOCKS,
77-
NodeProp.EXCLUSIVE_SHARED_DIRTIED_BLOCKS,
78-
NodeProp.EXCLUSIVE_SHARED_WRITTEN_BLOCKS,
79-
NodeProp.EXCLUSIVE_TEMP_READ_BLOCKS,
80-
NodeProp.EXCLUSIVE_TEMP_WRITTEN_BLOCKS,
81-
NodeProp.EXCLUSIVE_LOCAL_HIT_BLOCKS,
82-
NodeProp.EXCLUSIVE_LOCAL_READ_BLOCKS,
83-
NodeProp.EXCLUSIVE_LOCAL_DIRTIED_BLOCKS,
84-
NodeProp.EXCLUSIVE_LOCAL_WRITTEN_BLOCKS,
85-
NodeProp.SHARED_HIT_BLOCKS,
86-
NodeProp.SHARED_READ_BLOCKS,
87-
NodeProp.SHARED_DIRTIED_BLOCKS,
88-
NodeProp.SHARED_WRITTEN_BLOCKS,
89-
NodeProp.TEMP_READ_BLOCKS,
90-
NodeProp.TEMP_WRITTEN_BLOCKS,
91-
NodeProp.LOCAL_HIT_BLOCKS,
92-
NodeProp.LOCAL_READ_BLOCKS,
93-
NodeProp.LOCAL_DIRTIED_BLOCKS,
94-
NodeProp.LOCAL_WRITTEN_BLOCKS,
95-
NodeProp.PLANNER_ESTIMATE_FACTOR,
96-
NodeProp.PLANNER_ESTIMATE_DIRECTION,
97-
NodeProp.SUBPLAN_NAME,
98-
NodeProp.GROUP_KEY,
99-
NodeProp.HASH_CONDITION,
100-
NodeProp.JOIN_TYPE,
101-
NodeProp.INDEX_NAME,
102-
NodeProp.HASH_CONDITION,
103-
NodeProp.EXCLUSIVE_IO_READ_TIME,
104-
NodeProp.EXCLUSIVE_IO_WRITE_TIME,
105-
NodeProp.AVERAGE_IO_READ_TIME,
106-
NodeProp.AVERAGE_IO_WRITE_TIME,
107-
NodeProp.IO_READ_TIME, // Exclusive value already shown in IO tab
108-
NodeProp.IO_WRITE_TIME, // Exclusive value already shown in IO tab
109-
NodeProp.HEAP_FETCHES,
110-
NodeProp.WAL_RECORDS,
111-
NodeProp.WAL_BYTES,
112-
NodeProp.WAL_FPI,
113-
NodeProp.NODE_ID,
114-
NodeProp.ROWS_REMOVED_BY_FILTER,
115-
NodeProp.ROWS_REMOVED_BY_JOIN_FILTER,
116-
NodeProp.ACTUAL_ROWS_REVISED,
117-
NodeProp.PLAN_ROWS_REVISED,
118-
NodeProp.ROWS_REMOVED_BY_FILTER_REVISED,
119-
NodeProp.ROWS_REMOVED_BY_JOIN_FILTER_REVISED,
120-
"size", // Manually added to use FlexTree
121-
NodeProp.RELATION_NAME,
122-
NodeProp.ALIAS,
123-
]
124-
12553
onBeforeMount(() => {
12654
calculateProps()
12755
})
@@ -145,15 +73,6 @@ function calculateProps() {
14573
.value()
14674
}
14775
148-
function shouldShowProp(key: string, value: unknown): boolean {
149-
return (
150-
(!!value ||
151-
nodePropTypes[key] === PropType.increment ||
152-
key === NodeProp.ACTUAL_ROWS) &&
153-
notMiscProperties.indexOf(key) === -1
154-
)
155-
}
156-
15776
const shouldShowIoBuffers = computed((): boolean => {
15877
const properties: Array<keyof typeof NodeProp> = [
15978
"EXCLUSIVE_SHARED_HIT_BLOCKS",
@@ -509,79 +428,7 @@ watch(activeTab, () => {
509428
"
510429
>
511430
<!-- workers tab -->
512-
<div>
513-
<b>Workers planned: </b>
514-
<span class="px-1">{{
515-
node[NodeProp.WORKERS_PLANNED] ||
516-
node[NodeProp.WORKERS_PLANNED_BY_GATHER]
517-
}}</span>
518-
<em
519-
v-if="
520-
!node[NodeProp.WORKERS_PLANNED] &&
521-
!node[NodeProp.WORKERS] &&
522-
(!plan.isVerbose || !plan.isAnalyze)
523-
"
524-
class="text-warning"
525-
>
526-
<font-awesome-icon
527-
icon="exclamation-triangle"
528-
class="cursor-help"
529-
v-tippy="getHelpMessage('fuzzy needs verbose')"
530-
></font-awesome-icon>
531-
</em>
532-
</div>
533-
<div>
534-
<b>Workers launched: </b>
535-
<span class="px-1">{{ workersLaunchedCount }}</span>
536-
</div>
537-
<div
538-
v-if="!workersLaunchedCount && node[NodeProp.WORKERS_PLANNED_BY_GATHER]"
539-
class="text-muted"
540-
>
541-
<em>
542-
Detailed information is not available.
543-
<font-awesome-icon
544-
icon="exclamation-triangle"
545-
class="cursor-help"
546-
v-tippy="getHelpMessage('workers detailed info missing')"
547-
></font-awesome-icon>
548-
</em>
549-
</div>
550-
551-
<div
552-
v-if="_.isArray(node[NodeProp.WORKERS])"
553-
class="overflow-auto"
554-
style="max-height: 300px"
555-
@wheel.stop
556-
>
557-
<template
558-
v-for="(worker, index) in node[NodeProp.WORKERS]"
559-
:key="index"
560-
>
561-
<div class="card mt-2">
562-
<div class="card-header">
563-
<b>Worker {{ worker[WorkerProp.WORKER_NUMBER] }}</b>
564-
</div>
565-
<ul class="list-group list-group-flush">
566-
<template v-for="(value, key) in worker" :key="key">
567-
<li
568-
class="list-group-item d-flex flex-row"
569-
v-if="shouldShowProp(key as string, value)"
570-
>
571-
<div class="col-6">
572-
{{ key }}
573-
</div>
574-
<div
575-
class="col-6"
576-
v-html="formatNodeProp(key as string, value)"
577-
></div>
578-
</li>
579-
</template>
580-
</ul>
581-
</div>
582-
</template>
583-
</div>
584-
<!-- workers tab -->
431+
<workers-detail :node="node" />
585432
</div>
586433
<div class="tab-pane" :class="{ 'show active': activeTab === 'misc' }">
587434
<!-- misc tab -->

src/components/WorkersDetail.vue

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<script lang="ts" setup>
2+
import { inject, reactive } from "vue"
3+
import _ from "lodash"
4+
import type { Ref } from "vue"
5+
import type { IPlan, Node, ViewOptions } from "@/interfaces"
6+
import { NodeProp, WorkerProp } from "@/enums"
7+
import { PlanKey, ViewOptionsKey } from "@/symbols"
8+
import { HelpService, shouldShowProp } from "@/services/help-service"
9+
import useNode from "@/node"
10+
import { formatNodeProp } from "@/filters"
11+
import { directive as vTippy } from "vue-tippy"
12+
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"
13+
14+
interface Props {
15+
node: Node
16+
}
17+
const props = defineProps<Props>()
18+
const node = reactive<Node>(props.node)
19+
const plan = inject(PlanKey) as Ref<IPlan>
20+
const viewOptions = inject(ViewOptionsKey) as ViewOptions
21+
22+
const helpService = new HelpService()
23+
const getHelpMessage = helpService.getHelpMessage
24+
25+
const { workersLaunchedCount } = useNode(plan, node, viewOptions)
26+
</script>
27+
<template>
28+
<!-- workers tab -->
29+
<div>
30+
<b>Workers planned: </b>
31+
<span class="px-1">{{
32+
node[NodeProp.WORKERS_PLANNED] || node[NodeProp.WORKERS_PLANNED_BY_GATHER]
33+
}}</span>
34+
<em
35+
v-if="
36+
!node[NodeProp.WORKERS_PLANNED] &&
37+
!node[NodeProp.WORKERS] &&
38+
(!plan.isVerbose || !plan.isAnalyze)
39+
"
40+
class="text-warning"
41+
>
42+
<font-awesome-icon
43+
icon="exclamation-triangle"
44+
class="cursor-help"
45+
v-tippy="getHelpMessage('fuzzy needs verbose')"
46+
></font-awesome-icon>
47+
</em>
48+
</div>
49+
<div>
50+
<b>Workers launched: </b>
51+
<span class="px-1">{{ workersLaunchedCount }}</span>
52+
</div>
53+
<div
54+
v-if="!workersLaunchedCount && node[NodeProp.WORKERS_PLANNED_BY_GATHER]"
55+
class="text-muted"
56+
>
57+
<em>
58+
Detailed information is not available.
59+
<font-awesome-icon
60+
icon="exclamation-triangle"
61+
class="cursor-help"
62+
v-tippy="getHelpMessage('workers detailed info missing')"
63+
></font-awesome-icon>
64+
</em>
65+
</div>
66+
67+
<div
68+
v-if="_.isArray(node[NodeProp.WORKERS])"
69+
class="overflow-auto"
70+
style="max-height: 300px"
71+
@wheel.stop
72+
>
73+
<template v-for="(worker, index) in node[NodeProp.WORKERS]" :key="index">
74+
<div class="card mt-2">
75+
<div class="card-header">
76+
<b>Worker {{ worker[WorkerProp.WORKER_NUMBER] }}</b>
77+
</div>
78+
<ul class="list-group list-group-flush">
79+
<template v-for="(value, key) in worker" :key="key">
80+
<li
81+
class="list-group-item d-flex flex-row"
82+
v-if="shouldShowProp(key as string, value)"
83+
>
84+
<div class="col-6">
85+
{{ key }}
86+
</div>
87+
<div
88+
class="col-6"
89+
v-html="formatNodeProp(key as string, value)"
90+
></div>
91+
</li>
92+
</template>
93+
</ul>
94+
</div>
95+
</template>
96+
</div>
97+
</template>

src/services/help-service.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import _ from "lodash"
22
import type { IPlan, Node } from "@/interfaces"
33
import { NodeProp } from "@/enums"
4+
import { nodePropTypes, PropType } from "@/enums"
45

56
export class HelpService {
67
public nodeId = 0
@@ -292,3 +293,77 @@ export function findNodeBySubplanName(
292293
}
293294
return o
294295
}
296+
297+
// Returns the list of properties that have already been displayed either in
298+
// the main panel or in other detailed tabs.
299+
const notMiscProperties: string[] = [
300+
NodeProp.NODE_TYPE,
301+
NodeProp.CTE_NAME,
302+
NodeProp.EXCLUSIVE_DURATION,
303+
NodeProp.EXCLUSIVE_COST,
304+
NodeProp.TOTAL_COST,
305+
NodeProp.PLAN_ROWS,
306+
NodeProp.ACTUAL_ROWS,
307+
NodeProp.ACTUAL_LOOPS,
308+
NodeProp.OUTPUT,
309+
NodeProp.WORKERS,
310+
NodeProp.WORKERS_PLANNED,
311+
NodeProp.WORKERS_LAUNCHED,
312+
NodeProp.EXCLUSIVE_SHARED_HIT_BLOCKS,
313+
NodeProp.EXCLUSIVE_SHARED_READ_BLOCKS,
314+
NodeProp.EXCLUSIVE_SHARED_DIRTIED_BLOCKS,
315+
NodeProp.EXCLUSIVE_SHARED_WRITTEN_BLOCKS,
316+
NodeProp.EXCLUSIVE_TEMP_READ_BLOCKS,
317+
NodeProp.EXCLUSIVE_TEMP_WRITTEN_BLOCKS,
318+
NodeProp.EXCLUSIVE_LOCAL_HIT_BLOCKS,
319+
NodeProp.EXCLUSIVE_LOCAL_READ_BLOCKS,
320+
NodeProp.EXCLUSIVE_LOCAL_DIRTIED_BLOCKS,
321+
NodeProp.EXCLUSIVE_LOCAL_WRITTEN_BLOCKS,
322+
NodeProp.SHARED_HIT_BLOCKS,
323+
NodeProp.SHARED_READ_BLOCKS,
324+
NodeProp.SHARED_DIRTIED_BLOCKS,
325+
NodeProp.SHARED_WRITTEN_BLOCKS,
326+
NodeProp.TEMP_READ_BLOCKS,
327+
NodeProp.TEMP_WRITTEN_BLOCKS,
328+
NodeProp.LOCAL_HIT_BLOCKS,
329+
NodeProp.LOCAL_READ_BLOCKS,
330+
NodeProp.LOCAL_DIRTIED_BLOCKS,
331+
NodeProp.LOCAL_WRITTEN_BLOCKS,
332+
NodeProp.PLANNER_ESTIMATE_FACTOR,
333+
NodeProp.PLANNER_ESTIMATE_DIRECTION,
334+
NodeProp.SUBPLAN_NAME,
335+
NodeProp.GROUP_KEY,
336+
NodeProp.HASH_CONDITION,
337+
NodeProp.JOIN_TYPE,
338+
NodeProp.INDEX_NAME,
339+
NodeProp.HASH_CONDITION,
340+
NodeProp.EXCLUSIVE_IO_READ_TIME,
341+
NodeProp.EXCLUSIVE_IO_WRITE_TIME,
342+
NodeProp.AVERAGE_IO_READ_TIME,
343+
NodeProp.AVERAGE_IO_WRITE_TIME,
344+
NodeProp.IO_READ_TIME, // Exclusive value already shown in IO tab
345+
NodeProp.IO_WRITE_TIME, // Exclusive value already shown in IO tab
346+
NodeProp.HEAP_FETCHES,
347+
NodeProp.WAL_RECORDS,
348+
NodeProp.WAL_BYTES,
349+
NodeProp.WAL_FPI,
350+
NodeProp.NODE_ID,
351+
NodeProp.ROWS_REMOVED_BY_FILTER,
352+
NodeProp.ROWS_REMOVED_BY_JOIN_FILTER,
353+
NodeProp.ACTUAL_ROWS_REVISED,
354+
NodeProp.PLAN_ROWS_REVISED,
355+
NodeProp.ROWS_REMOVED_BY_FILTER_REVISED,
356+
NodeProp.ROWS_REMOVED_BY_JOIN_FILTER_REVISED,
357+
"size", // Manually added to use FlexTree
358+
NodeProp.RELATION_NAME,
359+
NodeProp.ALIAS,
360+
]
361+
362+
export function shouldShowProp(key: string, value: unknown): boolean {
363+
return (
364+
(!!value ||
365+
nodePropTypes[key] === PropType.increment ||
366+
key === NodeProp.ACTUAL_ROWS) &&
367+
notMiscProperties.indexOf(key) === -1
368+
)
369+
}

0 commit comments

Comments
 (0)