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