]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts
import 15.2.0 Octopus source
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cephfs / cephfs-chart / cephfs-chart.component.ts
CommitLineData
11fdf7f2
TL
1import { Component, ElementRef, Input, OnChanges, OnInit, ViewChild } from '@angular/core';
2
eafe8130 3import { ChartDataSets, ChartOptions, ChartPoint, ChartType } from 'chart.js';
11fdf7f2
TL
4import * as _ from 'lodash';
5import * as moment from 'moment';
6
7import { ChartTooltip } from '../../../shared/models/chart-tooltip';
8
9@Component({
10 selector: 'cd-cephfs-chart',
11 templateUrl: './cephfs-chart.component.html',
12 styleUrls: ['./cephfs-chart.component.scss']
13})
14export class CephfsChartComponent implements OnChanges, OnInit {
9f95a23c 15 @ViewChild('chartCanvas', { static: true })
11fdf7f2 16 chartCanvas: ElementRef;
9f95a23c 17 @ViewChild('chartTooltip', { static: true })
11fdf7f2
TL
18 chartTooltip: ElementRef;
19
20 @Input()
21 mdsCounter: any;
22
494da23a 23 lhsCounter = 'mds_mem.ino';
11fdf7f2
TL
24 rhsCounter = 'mds_server.handle_client_request';
25
eafe8130
TL
26 chart: {
27 datasets: ChartDataSets[];
28 options: ChartOptions;
29 chartType: ChartType;
30 } = {
31 datasets: [
32 {
33 label: this.lhsCounter,
34 yAxisID: 'LHS',
35 data: [],
36 lineTension: 0.1
37 },
38 {
39 label: this.rhsCounter,
40 yAxisID: 'RHS',
41 data: [],
42 lineTension: 0.1
43 }
44 ],
45 options: {
46 title: {
47 text: '',
48 display: true
49 },
50 responsive: true,
51 maintainAspectRatio: false,
52 legend: {
53 position: 'top'
54 },
55 scales: {
56 xAxes: [
57 {
58 position: 'top',
59 type: 'time',
60 time: {
61 displayFormats: {
62 quarter: 'MMM YYYY'
63 }
64 },
65 ticks: {
66 maxRotation: 0
67 }
68 }
69 ],
70 yAxes: [
71 {
72 id: 'LHS',
73 type: 'linear',
74 position: 'left'
75 },
76 {
77 id: 'RHS',
78 type: 'linear',
79 position: 'right'
80 }
81 ]
82 },
83 tooltips: {
84 enabled: false,
85 mode: 'index',
86 intersect: false,
87 position: 'nearest',
88 callbacks: {
89 // Pick the Unix timestamp of the first tooltip item.
90 title: (tooltipItems, data): string => {
91 let ts = 0;
92 if (tooltipItems.length > 0) {
93 const item = tooltipItems[0];
94 const point = data.datasets[item.datasetIndex].data[item.index] as ChartPoint;
95 ts = point.x as number;
96 }
97 return ts.toString();
98 }
99 }
100 }
101 },
102 chartType: 'line'
103 };
11fdf7f2
TL
104
105 constructor() {}
106
107 ngOnInit() {
108 if (_.isUndefined(this.mdsCounter)) {
109 return;
110 }
eafe8130
TL
111 this.setChartTooltip();
112 this.updateChart();
113 }
11fdf7f2 114
eafe8130
TL
115 ngOnChanges() {
116 if (_.isUndefined(this.mdsCounter)) {
117 return;
118 }
119 this.updateChart();
120 }
11fdf7f2 121
eafe8130 122 private setChartTooltip() {
11fdf7f2
TL
123 const chartTooltip = new ChartTooltip(
124 this.chartCanvas,
125 this.chartTooltip,
9f95a23c
TL
126 (tooltip: any) => tooltip.caretX + 'px',
127 (tooltip: any) => tooltip.caretY - tooltip.height - 23 + 'px'
11fdf7f2 128 );
eafe8130 129 chartTooltip.getTitle = (ts) => moment(ts, 'x').format('LTS');
11fdf7f2 130 chartTooltip.checkOffset = true;
eafe8130
TL
131 const chartOptions: ChartOptions = {
132 title: {
133 text: this.mdsCounter.name
11fdf7f2 134 },
eafe8130
TL
135 tooltips: {
136 custom: (tooltip) => chartTooltip.customTooltips(tooltip)
137 }
11fdf7f2 138 };
eafe8130 139 _.merge(this.chart, { options: chartOptions });
11fdf7f2
TL
140 }
141
eafe8130
TL
142 private updateChart() {
143 const chartDataSets: ChartDataSets[] = [
144 {
145 data: this.convertTimeSeries(this.mdsCounter[this.lhsCounter])
146 },
147 {
148 data: this.deltaTimeSeries(this.mdsCounter[this.rhsCounter])
149 }
150 ];
151 _.merge(this.chart, {
152 datasets: chartDataSets
153 });
154 this.chart.datasets = [...this.chart.datasets]; // Force angular to update
11fdf7f2
TL
155 }
156
eafe8130
TL
157 /**
158 * Convert ceph-mgr's time series format (list of 2-tuples
159 * with seconds-since-epoch timestamps) into what chart.js
160 * can handle (list of objects with millisecs-since-epoch
161 * timestamps)
162 */
9f95a23c
TL
163 private convertTimeSeries(sourceSeries: any) {
164 const data: any[] = [];
11fdf7f2
TL
165 _.each(sourceSeries, (dp) => {
166 data.push({
167 x: dp[0] * 1000,
168 y: dp[1]
169 });
170 });
171
eafe8130
TL
172 /**
173 * MDS performance counters chart is expecting the same number of items
174 * from each data series. Since in deltaTimeSeries we are ignoring the first
175 * element, we will do the same here.
176 */
177 data.shift();
178
11fdf7f2
TL
179 return data;
180 }
181
9f95a23c 182 private deltaTimeSeries(sourceSeries: any) {
11fdf7f2
TL
183 let i;
184 let prev = sourceSeries[0];
185 const result = [];
186 for (i = 1; i < sourceSeries.length; i++) {
187 const cur = sourceSeries[i];
11fdf7f2
TL
188
189 result.push({
190 x: cur[0] * 1000,
9f95a23c 191 y: cur[1] - prev[1]
11fdf7f2
TL
192 });
193
194 prev = cur;
195 }
196 return result;
197 }
198}