]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { Component, OnDestroy, OnInit } from '@angular/core'; |
2 | ||
3 | import { I18n } from '@ngx-translate/i18n-polyfill'; | |
4 | import * as _ from 'lodash'; | |
9f95a23c | 5 | import { Subscription } from 'rxjs'; |
11fdf7f2 TL |
6 | |
7 | import { HealthService } from '../../../shared/api/health.service'; | |
9f95a23c | 8 | import { Icons } from '../../../shared/enum/icons.enum'; |
11fdf7f2 | 9 | import { Permissions } from '../../../shared/models/permissions'; |
81eedcae TL |
10 | import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe'; |
11 | import { DimlessPipe } from '../../../shared/pipes/dimless.pipe'; | |
11fdf7f2 TL |
12 | import { AuthStorageService } from '../../../shared/services/auth-storage.service'; |
13 | import { | |
14 | FeatureTogglesMap$, | |
15 | FeatureTogglesService | |
16 | } from '../../../shared/services/feature-toggles.service'; | |
17 | import { RefreshIntervalService } from '../../../shared/services/refresh-interval.service'; | |
18 | import { PgCategoryService } from '../../shared/pg-category.service'; | |
11fdf7f2 TL |
19 | |
20 | @Component({ | |
21 | selector: 'cd-health', | |
22 | templateUrl: './health.component.html', | |
23 | styleUrls: ['./health.component.scss'] | |
24 | }) | |
25 | export class HealthComponent implements OnInit, OnDestroy { | |
26 | healthData: any; | |
27 | interval = new Subscription(); | |
28 | permissions: Permissions; | |
29 | enabledFeature$: FeatureTogglesMap$; | |
9f95a23c | 30 | icons = Icons; |
11fdf7f2 | 31 | |
f91f0fd5 | 32 | clientStatsConfig = { |
81eedcae TL |
33 | colors: [ |
34 | { | |
f91f0fd5 | 35 | backgroundColor: ['--color-cyan', '--color-purple'] |
81eedcae TL |
36 | } |
37 | ] | |
38 | }; | |
f91f0fd5 TL |
39 | |
40 | rawCapacityChartConfig = { | |
81eedcae TL |
41 | colors: [ |
42 | { | |
f91f0fd5 | 43 | backgroundColor: ['--color-blue', '--color-gray'] |
81eedcae TL |
44 | } |
45 | ] | |
46 | }; | |
47 | ||
f91f0fd5 TL |
48 | pgStatusChartConfig = { |
49 | options: { | |
50 | events: [''] | |
51 | } | |
52 | }; | |
53 | ||
11fdf7f2 TL |
54 | constructor( |
55 | private healthService: HealthService, | |
56 | private i18n: I18n, | |
57 | private authStorageService: AuthStorageService, | |
58 | private pgCategoryService: PgCategoryService, | |
59 | private featureToggles: FeatureTogglesService, | |
81eedcae TL |
60 | private refreshIntervalService: RefreshIntervalService, |
61 | private dimlessBinary: DimlessBinaryPipe, | |
62 | private dimless: DimlessPipe | |
11fdf7f2 TL |
63 | ) { |
64 | this.permissions = this.authStorageService.getPermissions(); | |
65 | this.enabledFeature$ = this.featureToggles.get(); | |
66 | } | |
67 | ||
68 | ngOnInit() { | |
69 | this.getHealth(); | |
70 | this.interval = this.refreshIntervalService.intervalData$.subscribe(() => { | |
71 | this.getHealth(); | |
72 | }); | |
73 | } | |
74 | ||
75 | ngOnDestroy() { | |
76 | this.interval.unsubscribe(); | |
77 | } | |
78 | ||
79 | getHealth() { | |
80 | this.healthService.getMinimalHealth().subscribe((data: any) => { | |
81 | this.healthData = data; | |
82 | }); | |
83 | } | |
84 | ||
9f95a23c | 85 | prepareReadWriteRatio(chart: Record<string, any>) { |
11fdf7f2 TL |
86 | const ratioLabels = []; |
87 | const ratioData = []; | |
88 | ||
81eedcae TL |
89 | const total = |
90 | this.healthData.client_perf.write_op_per_sec + this.healthData.client_perf.read_op_per_sec; | |
91 | ||
92 | ratioLabels.push( | |
f91f0fd5 TL |
93 | `${this.i18n(`Reads`)}: ${this.dimless.transform( |
94 | this.healthData.client_perf.read_op_per_sec | |
95 | )} ${this.i18n(`/s`)}` | |
81eedcae | 96 | ); |
adb31ebb | 97 | ratioData.push(this.calcPercentage(this.healthData.client_perf.read_op_per_sec, total)); |
81eedcae | 98 | ratioLabels.push( |
f91f0fd5 TL |
99 | `${this.i18n(`Writes`)}: ${this.dimless.transform( |
100 | this.healthData.client_perf.write_op_per_sec | |
101 | )} ${this.i18n(`/s`)}` | |
81eedcae | 102 | ); |
f91f0fd5 | 103 | ratioData.push(this.calcPercentage(this.healthData.client_perf.write_op_per_sec, total)); |
11fdf7f2 | 104 | |
f91f0fd5 | 105 | chart.labels = ratioLabels; |
11fdf7f2 | 106 | chart.dataset[0].data = ratioData; |
f91f0fd5 TL |
107 | chart.dataset[0].label = `${this.dimless.transform(total)}\n${this.i18n(`IOPS`)}`; |
108 | } | |
109 | ||
110 | prepareClientThroughput(chart: Record<string, any>) { | |
111 | const ratioLabels = []; | |
112 | const ratioData = []; | |
113 | ||
114 | const total = | |
115 | this.healthData.client_perf.read_bytes_sec + this.healthData.client_perf.write_bytes_sec; | |
116 | ||
117 | ratioLabels.push( | |
118 | `${this.i18n(`Reads`)}: ${this.dimlessBinary.transform( | |
119 | this.healthData.client_perf.read_bytes_sec | |
120 | )}${this.i18n(`/s`)}` | |
121 | ); | |
122 | ratioData.push(this.calcPercentage(this.healthData.client_perf.read_bytes_sec, total)); | |
123 | ratioLabels.push( | |
124 | `${this.i18n(`Writes`)}: ${this.dimlessBinary.transform( | |
125 | this.healthData.client_perf.write_bytes_sec | |
126 | )}${this.i18n(`/s`)}` | |
127 | ); | |
128 | ratioData.push(this.calcPercentage(this.healthData.client_perf.write_bytes_sec, total)); | |
129 | ||
11fdf7f2 | 130 | chart.labels = ratioLabels; |
f91f0fd5 TL |
131 | chart.dataset[0].data = ratioData; |
132 | chart.dataset[0].label = `${this.dimlessBinary.transform(total).replace(' ', '\n')}${this.i18n( | |
133 | `/s` | |
134 | )}`; | |
11fdf7f2 TL |
135 | } |
136 | ||
9f95a23c | 137 | prepareRawUsage(chart: Record<string, any>, data: Record<string, any>) { |
81eedcae TL |
138 | const percentAvailable = this.calcPercentage( |
139 | data.df.stats.total_bytes - data.df.stats.total_used_raw_bytes, | |
140 | data.df.stats.total_bytes | |
11fdf7f2 | 141 | ); |
81eedcae TL |
142 | const percentUsed = this.calcPercentage( |
143 | data.df.stats.total_used_raw_bytes, | |
144 | data.df.stats.total_bytes | |
11fdf7f2 TL |
145 | ); |
146 | ||
f91f0fd5 | 147 | chart.dataset[0].data = [percentUsed, percentAvailable]; |
81eedcae | 148 | |
11fdf7f2 | 149 | chart.labels = [ |
f91f0fd5 TL |
150 | `${this.i18n(`Used`)}: ${this.dimlessBinary.transform(data.df.stats.total_used_raw_bytes)}`, |
151 | `${this.i18n(`Avail.`)}: ${this.dimlessBinary.transform( | |
81eedcae | 152 | data.df.stats.total_bytes - data.df.stats.total_used_raw_bytes |
f91f0fd5 | 153 | )}` |
11fdf7f2 | 154 | ]; |
81eedcae | 155 | |
f91f0fd5 | 156 | chart.dataset[0].label = `${percentUsed}%\nof ${this.dimlessBinary.transform( |
81eedcae | 157 | data.df.stats.total_bytes |
f91f0fd5 | 158 | )}`; |
11fdf7f2 TL |
159 | } |
160 | ||
9f95a23c TL |
161 | preparePgStatus(chart: Record<string, any>, data: Record<string, any>) { |
162 | const categoryPgAmount: Record<string, number> = {}; | |
eafe8130 | 163 | let totalPgs = 0; |
11fdf7f2 TL |
164 | |
165 | _.forEach(data.pg_info.statuses, (pgAmount, pgStatesText) => { | |
166 | const categoryType = this.pgCategoryService.getTypeByStates(pgStatesText); | |
167 | ||
168 | if (_.isUndefined(categoryPgAmount[categoryType])) { | |
169 | categoryPgAmount[categoryType] = 0; | |
170 | } | |
171 | categoryPgAmount[categoryType] += pgAmount; | |
eafe8130 | 172 | totalPgs += pgAmount; |
11fdf7f2 TL |
173 | }); |
174 | ||
f91f0fd5 TL |
175 | for (const categoryType of this.pgCategoryService.getAllTypes()) { |
176 | if (_.isUndefined(categoryPgAmount[categoryType])) { | |
177 | categoryPgAmount[categoryType] = 0; | |
178 | } | |
179 | } | |
180 | ||
11fdf7f2 TL |
181 | chart.dataset[0].data = this.pgCategoryService |
182 | .getAllTypes() | |
f91f0fd5 | 183 | .map((categoryType) => this.calcPercentage(categoryPgAmount[categoryType], totalPgs)); |
81eedcae TL |
184 | |
185 | chart.labels = [ | |
f91f0fd5 TL |
186 | `${this.i18n(`Clean`)}: ${this.dimless.transform(categoryPgAmount['clean'])}`, |
187 | `${this.i18n(`Working`)}: ${this.dimless.transform(categoryPgAmount['working'])}`, | |
188 | `${this.i18n(`Warning`)}: ${this.dimless.transform(categoryPgAmount['warning'])}`, | |
189 | `${this.i18n(`Unknown`)}: ${this.dimless.transform(categoryPgAmount['unknown'])}` | |
81eedcae | 190 | ]; |
f91f0fd5 TL |
191 | |
192 | chart.dataset[0].label = `${totalPgs}\n${this.i18n(`PGs`)}`; | |
81eedcae TL |
193 | } |
194 | ||
9f95a23c | 195 | prepareObjects(chart: Record<string, any>, data: Record<string, any>) { |
f91f0fd5 | 196 | const objectCopies = data.pg_info.object_stats.num_object_copies; |
81eedcae | 197 | const healthy = |
f91f0fd5 | 198 | objectCopies - |
81eedcae TL |
199 | data.pg_info.object_stats.num_objects_misplaced - |
200 | data.pg_info.object_stats.num_objects_degraded - | |
201 | data.pg_info.object_stats.num_objects_unfound; | |
f91f0fd5 TL |
202 | const healthyPercentage = this.calcPercentage(healthy, objectCopies); |
203 | const misplacedPercentage = this.calcPercentage( | |
204 | data.pg_info.object_stats.num_objects_misplaced, | |
205 | objectCopies | |
206 | ); | |
207 | const degradedPercentage = this.calcPercentage( | |
208 | data.pg_info.object_stats.num_objects_degraded, | |
209 | objectCopies | |
210 | ); | |
211 | const unfoundPercentage = this.calcPercentage( | |
212 | data.pg_info.object_stats.num_objects_unfound, | |
213 | objectCopies | |
214 | ); | |
81eedcae TL |
215 | |
216 | chart.labels = [ | |
f91f0fd5 TL |
217 | `${this.i18n(`Healthy`)}: ${healthyPercentage}%`, |
218 | `${this.i18n(`Misplaced`)}: ${misplacedPercentage}%`, | |
219 | `${this.i18n(`Degraded`)}: ${degradedPercentage}%`, | |
220 | `${this.i18n(`Unfound`)}: ${unfoundPercentage}%` | |
81eedcae TL |
221 | ]; |
222 | ||
223 | chart.dataset[0].data = [ | |
f91f0fd5 TL |
224 | healthyPercentage, |
225 | misplacedPercentage, | |
226 | degradedPercentage, | |
227 | unfoundPercentage | |
81eedcae TL |
228 | ]; |
229 | ||
f91f0fd5 | 230 | chart.dataset[0].label = `${this.dimless.transform( |
81eedcae | 231 | data.pg_info.object_stats.num_objects |
f91f0fd5 | 232 | )}\n${this.i18n(`objects`)}`; |
11fdf7f2 TL |
233 | } |
234 | ||
235 | isClientReadWriteChartShowable() { | |
236 | const readOps = this.healthData.client_perf.read_op_per_sec || 0; | |
237 | const writeOps = this.healthData.client_perf.write_op_per_sec || 0; | |
238 | ||
239 | return readOps + writeOps > 0; | |
240 | } | |
81eedcae TL |
241 | |
242 | private calcPercentage(dividend: number, divisor: number) { | |
243 | if (!_.isNumber(dividend) || !_.isNumber(divisor) || divisor === 0) { | |
244 | return 0; | |
245 | } | |
246 | ||
247 | return Math.round((dividend / divisor) * 100); | |
248 | } | |
11fdf7f2 | 249 | } |