| 1 | <template> |
| 2 | <div class="metrics-list"> |
| 3 | <n-card |
| 4 | v-for="group of sanitizedMetrics" |
| 5 | :key="group.groupName" |
| 6 | :title="group.groupName" |
| 7 | size="small" |
| 8 | segmented |
| 9 | class="metrics-group" |
| 10 | content-style="padding:0" |
| 11 | > |
| 12 | <div class="list"> |
| 13 | <div |
| 14 | v-for="metric of group.throughputMetrics" |
| 15 | :key="metric.metric" |
| 16 | class="metric-wrap flex items-center gap-4" |
| 17 | > |
| 18 | <div class="metric basis-2/3"> |
| 19 | {{ metric.metric }} |
| 20 | </div> |
| 21 | <div class="value basis-1/3"> |
| 22 | <n-progress type="line" status="success" :percentage="metric.percentage"> |
| 23 | <span class="font-mono"> |
| 24 | {{ metric.value }} |
| 25 | </span> |
| 26 | </n-progress> |
| 27 | </div> |
| 28 | </div> |
| 29 | </div> |
| 30 | </n-card> |
| 31 | </div> |
| 32 | </template> |
| 33 | |
| 34 | <script setup lang="ts"> |
| 35 | // TODO-FE: refactor |
| 36 | import type { ThroughputMetric } from "@/types/graylog/metrics.d" |
| 37 | import _groupBy from "lodash/groupBy" |
| 38 | import _map from "lodash/map" |
| 39 | import _trim from "lodash/trim" |
| 40 | import { NCard, NProgress } from "naive-ui" |
| 41 | import { computed, toRefs } from "vue" |
| 42 | |
| 43 | interface Metrics { |
| 44 | groupName: string |
| 45 | throughputMetrics: (ThroughputMetric & { name: string; percentage: number })[] |
| 46 | } |
| 47 | |
| 48 | const props = defineProps<{ |
| 49 | throughputMetrics: ThroughputMetric[] |
| 50 | }>() |
| 51 | const { throughputMetrics } = toRefs(props) |
| 52 | |
| 53 | const sanitizedMetrics = computed<Metrics[]>(() => { |
| 54 | return sanitizeMetrics(throughputMetrics.value) |
| 55 | }) |
| 56 | |
| 57 | function sanitizeMetrics(metrics: ThroughputMetric[]): Metrics[] { |
| 58 | const keywords = ["input", "output", "process"] |
| 59 | |
| 60 | const tempData = metrics.map(o => { |
| 61 | const obj = { ...o } as ThroughputMetric & { name: string; percentage: number } |
| 62 | obj.name = obj.metric |
| 63 | for (const key of keywords) { |
| 64 | obj.name = _trim(obj.name.replace(key, "").replace("..", "."), ".") |
| 65 | } |
| 66 | return obj |
| 67 | }) |
| 68 | |
| 69 | const groups = _groupBy(tempData, "name") |
| 70 | |
| 71 | return _map(groups, group => { |
| 72 | const max = Math.max(...group.map(g => g.value)) || 1 |
| 73 | |
| 74 | for (const m of group) { |
| 75 | m.percentage = (m.value / max) * 100 |
| 76 | } |
| 77 | |
| 78 | const groupObj: Metrics = { |
| 79 | groupName: group[0]?.name ?? "", |
| 80 | throughputMetrics: group |
| 81 | } |
| 82 | return groupObj |
| 83 | }) |
| 84 | } |
| 85 | </script> |
| 86 | |
| 87 | <style lang="scss" scoped> |
| 88 | .metrics-list { |
| 89 | .metrics-group { |
| 90 | margin-bottom: calc(var(--spacing) * 6); |
| 91 | overflow: hidden; |
| 92 | |
| 93 | .list { |
| 94 | background-color: var(--bg-secondary-color); |
| 95 | .metric-wrap { |
| 96 | padding-inline: calc(var(--spacing) * 4); |
| 97 | padding-block: calc(var(--spacing) * 3); |
| 98 | |
| 99 | .metric { |
| 100 | line-height: 1.1; |
| 101 | } |
| 102 | |
| 103 | &:not(:last-child) { |
| 104 | border-bottom: 1px solid var(--border-color); |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | </style> |