]>
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'; | |
19 | import { HealthPieColor } from '../health-pie/health-pie-color.enum'; | |
20 | ||
21 | @Component({ | |
22 | selector: 'cd-health', | |
23 | templateUrl: './health.component.html', | |
24 | styleUrls: ['./health.component.scss'] | |
25 | }) | |
26 | export class HealthComponent implements OnInit, OnDestroy { | |
27 | healthData: any; | |
28 | interval = new Subscription(); | |
29 | permissions: Permissions; | |
30 | enabledFeature$: FeatureTogglesMap$; | |
9f95a23c | 31 | icons = Icons; |
11fdf7f2 | 32 | |
81eedcae TL |
33 | rawCapacityChartConfig = { |
34 | options: { | |
35 | title: { display: true, position: 'bottom' } | |
36 | } | |
37 | }; | |
38 | objectsChartConfig = { | |
39 | options: { | |
40 | title: { display: true, position: 'bottom' } | |
41 | }, | |
42 | colors: [ | |
43 | { | |
44 | backgroundColor: [ | |
45 | HealthPieColor.DEFAULT_GREEN, | |
46 | HealthPieColor.DEFAULT_MAGENTA, | |
47 | HealthPieColor.DEFAULT_ORANGE, | |
48 | HealthPieColor.DEFAULT_RED | |
49 | ] | |
50 | } | |
51 | ] | |
52 | }; | |
53 | pgStatusChartConfig = { | |
54 | colors: [ | |
55 | { | |
56 | backgroundColor: [ | |
57 | HealthPieColor.DEFAULT_GREEN, | |
58 | HealthPieColor.DEFAULT_BLUE, | |
59 | HealthPieColor.DEFAULT_ORANGE, | |
60 | HealthPieColor.DEFAULT_RED | |
61 | ] | |
62 | } | |
63 | ] | |
64 | }; | |
65 | ||
11fdf7f2 TL |
66 | constructor( |
67 | private healthService: HealthService, | |
68 | private i18n: I18n, | |
69 | private authStorageService: AuthStorageService, | |
70 | private pgCategoryService: PgCategoryService, | |
71 | private featureToggles: FeatureTogglesService, | |
81eedcae TL |
72 | private refreshIntervalService: RefreshIntervalService, |
73 | private dimlessBinary: DimlessBinaryPipe, | |
74 | private dimless: DimlessPipe | |
11fdf7f2 TL |
75 | ) { |
76 | this.permissions = this.authStorageService.getPermissions(); | |
77 | this.enabledFeature$ = this.featureToggles.get(); | |
78 | } | |
79 | ||
80 | ngOnInit() { | |
81 | this.getHealth(); | |
82 | this.interval = this.refreshIntervalService.intervalData$.subscribe(() => { | |
83 | this.getHealth(); | |
84 | }); | |
85 | } | |
86 | ||
87 | ngOnDestroy() { | |
88 | this.interval.unsubscribe(); | |
89 | } | |
90 | ||
91 | getHealth() { | |
92 | this.healthService.getMinimalHealth().subscribe((data: any) => { | |
93 | this.healthData = data; | |
94 | }); | |
95 | } | |
96 | ||
9f95a23c | 97 | prepareReadWriteRatio(chart: Record<string, any>) { |
11fdf7f2 TL |
98 | const ratioLabels = []; |
99 | const ratioData = []; | |
100 | ||
81eedcae TL |
101 | const total = |
102 | this.healthData.client_perf.write_op_per_sec + this.healthData.client_perf.read_op_per_sec; | |
103 | ||
104 | ratioLabels.push( | |
105 | `${this.i18n('Writes')} (${this.calcPercentage( | |
106 | this.healthData.client_perf.write_op_per_sec, | |
107 | total | |
108 | )}%)` | |
109 | ); | |
11fdf7f2 | 110 | ratioData.push(this.healthData.client_perf.write_op_per_sec); |
81eedcae TL |
111 | ratioLabels.push( |
112 | `${this.i18n('Reads')} (${this.calcPercentage( | |
113 | this.healthData.client_perf.read_op_per_sec, | |
114 | total | |
115 | )}%)` | |
116 | ); | |
11fdf7f2 TL |
117 | ratioData.push(this.healthData.client_perf.read_op_per_sec); |
118 | ||
119 | chart.dataset[0].data = ratioData; | |
120 | chart.labels = ratioLabels; | |
121 | } | |
122 | ||
9f95a23c | 123 | prepareRawUsage(chart: Record<string, any>, data: Record<string, any>) { |
81eedcae TL |
124 | const percentAvailable = this.calcPercentage( |
125 | data.df.stats.total_bytes - data.df.stats.total_used_raw_bytes, | |
126 | data.df.stats.total_bytes | |
11fdf7f2 | 127 | ); |
81eedcae TL |
128 | const percentUsed = this.calcPercentage( |
129 | data.df.stats.total_used_raw_bytes, | |
130 | data.df.stats.total_bytes | |
11fdf7f2 TL |
131 | ); |
132 | ||
133 | chart.dataset[0].data = [data.df.stats.total_used_raw_bytes, data.df.stats.total_avail_bytes]; | |
81eedcae | 134 | |
11fdf7f2 | 135 | chart.labels = [ |
81eedcae TL |
136 | `${this.dimlessBinary.transform(data.df.stats.total_used_raw_bytes)} ${this.i18n( |
137 | 'Used' | |
138 | )} (${percentUsed}%)`, | |
139 | `${this.dimlessBinary.transform( | |
140 | data.df.stats.total_bytes - data.df.stats.total_used_raw_bytes | |
141 | )} ${this.i18n('Avail.')} (${percentAvailable}%)` | |
11fdf7f2 | 142 | ]; |
81eedcae TL |
143 | |
144 | chart.options.title.text = `${this.dimlessBinary.transform( | |
145 | data.df.stats.total_bytes | |
146 | )} ${this.i18n('total')}`; | |
11fdf7f2 TL |
147 | } |
148 | ||
9f95a23c TL |
149 | preparePgStatus(chart: Record<string, any>, data: Record<string, any>) { |
150 | const categoryPgAmount: Record<string, number> = {}; | |
eafe8130 | 151 | let totalPgs = 0; |
11fdf7f2 TL |
152 | |
153 | _.forEach(data.pg_info.statuses, (pgAmount, pgStatesText) => { | |
154 | const categoryType = this.pgCategoryService.getTypeByStates(pgStatesText); | |
155 | ||
156 | if (_.isUndefined(categoryPgAmount[categoryType])) { | |
157 | categoryPgAmount[categoryType] = 0; | |
158 | } | |
159 | categoryPgAmount[categoryType] += pgAmount; | |
eafe8130 | 160 | totalPgs += pgAmount; |
11fdf7f2 TL |
161 | }); |
162 | ||
163 | chart.dataset[0].data = this.pgCategoryService | |
164 | .getAllTypes() | |
165 | .map((categoryType) => categoryPgAmount[categoryType]); | |
81eedcae TL |
166 | |
167 | chart.labels = [ | |
eafe8130 TL |
168 | `${this.i18n('Clean')} (${this.calcPercentage(categoryPgAmount['clean'], totalPgs)}%)`, |
169 | `${this.i18n('Working')} (${this.calcPercentage(categoryPgAmount['working'], totalPgs)}%)`, | |
170 | `${this.i18n('Warning')} (${this.calcPercentage(categoryPgAmount['warning'], totalPgs)}%)`, | |
171 | `${this.i18n('Unknown')} (${this.calcPercentage(categoryPgAmount['unknown'], totalPgs)}%)` | |
81eedcae TL |
172 | ]; |
173 | } | |
174 | ||
9f95a23c | 175 | prepareObjects(chart: Record<string, any>, data: Record<string, any>) { |
81eedcae TL |
176 | const totalReplicas = data.pg_info.object_stats.num_object_copies; |
177 | const healthy = | |
178 | totalReplicas - | |
179 | data.pg_info.object_stats.num_objects_misplaced - | |
180 | data.pg_info.object_stats.num_objects_degraded - | |
181 | data.pg_info.object_stats.num_objects_unfound; | |
182 | ||
183 | chart.labels = [ | |
184 | `${this.i18n('Healthy')} (${this.calcPercentage(healthy, totalReplicas)}%)`, | |
185 | `${this.i18n('Misplaced')} (${this.calcPercentage( | |
186 | data.pg_info.object_stats.num_objects_misplaced, | |
187 | totalReplicas | |
188 | )}%)`, | |
189 | `${this.i18n('Degraded')} (${this.calcPercentage( | |
190 | data.pg_info.object_stats.num_objects_degraded, | |
191 | totalReplicas | |
192 | )}%)`, | |
193 | `${this.i18n('Unfound')} (${this.calcPercentage( | |
194 | data.pg_info.object_stats.num_objects_unfound, | |
195 | totalReplicas | |
196 | )}%)` | |
197 | ]; | |
198 | ||
199 | chart.dataset[0].data = [ | |
200 | healthy, | |
201 | data.pg_info.object_stats.num_objects_misplaced, | |
202 | data.pg_info.object_stats.num_objects_degraded, | |
203 | data.pg_info.object_stats.num_objects_unfound | |
204 | ]; | |
205 | ||
206 | chart.options.title.text = `${this.dimless.transform( | |
207 | data.pg_info.object_stats.num_objects | |
208 | )} ${this.i18n('total')} (${this.dimless.transform(totalReplicas)} ${this.i18n('replicas')})`; | |
209 | ||
210 | chart.options.maintainAspectRatio = window.innerWidth >= 375; | |
11fdf7f2 TL |
211 | } |
212 | ||
213 | isClientReadWriteChartShowable() { | |
214 | const readOps = this.healthData.client_perf.read_op_per_sec || 0; | |
215 | const writeOps = this.healthData.client_perf.write_op_per_sec || 0; | |
216 | ||
217 | return readOps + writeOps > 0; | |
218 | } | |
81eedcae TL |
219 | |
220 | private calcPercentage(dividend: number, divisor: number) { | |
221 | if (!_.isNumber(dividend) || !_.isNumber(divisor) || divisor === 0) { | |
222 | return 0; | |
223 | } | |
224 | ||
225 | return Math.round((dividend / divisor) * 100); | |
226 | } | |
11fdf7f2 | 227 | } |