vitess.io/vitess@v0.16.2/web/vtadmin/src/util/tabletDebugVars.ts (about) 1 /** 2 * Copyright 2021 The Vitess Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * TabletDebugVars is a best-effort typing of the /debug/vars tablet endpoint. 19 * Only fields read by VTAdmin are defined here. 20 * 21 * A good future enhancement is a proto-typed gRPC endpoint in vtadmin.proto, 22 * from which we can generate TypeScript typings vs. having to duplicate them here. 23 * This would also offer us actual runtime type safety by way of protobufjs's 24 * generated validate() functions. For now, everything in here is optional (hence 25 * the Partial<>) and not guaranteed to be defined in every Vitess deployment. 26 */ 27 export type TabletDebugVars = Partial<{ 28 // See https://github.com/vitessio/vitess/blob/main/go/vt/servenv/buildinfo.go 29 BuildGitBranch: string; 30 BuildGitRev: string; 31 BuildHost: string; 32 BuildInformation: { [k: string]: number | string }; 33 BuildNumber: string; 34 BuildTimestamp: string; 35 BuildUser: string; 36 37 QPS: { [k: string]: number[] }; 38 39 // See https://github.com/vitessio/vitess/blob/main/go/vt/vttablet/tabletmanager/vreplication/stats.go 40 VReplicationLag: { [k: string]: number[] }; 41 VReplicationQPS: { [k: string]: number[] }; 42 }>; 43 44 export interface TimeseriesPoint { 45 x: number; 46 y: number; 47 } 48 49 export type TimeseriesMap = { [seriesName: string]: TimeseriesPoint[] }; 50 51 export const getQPSTimeseries = (d: TabletDebugVars | null | undefined, endAt?: number): TimeseriesMap => 52 formatTimeseriesMap(d?.QPS || {}, endAt); 53 54 export const getStreamVReplicationLagTimeseries = ( 55 d: TabletDebugVars | null | undefined, 56 endAt?: number 57 ): TimeseriesMap => formatTimeseriesMap(d?.VReplicationLag || {}, endAt); 58 59 export const getVReplicationQPSTimeseries = (d: TabletDebugVars | null | undefined, endAt?: number): TimeseriesMap => 60 formatTimeseriesMap(d?.VReplicationQPS || {}, endAt); 61 62 /** 63 * REFETCH_INTERVAL defines a default for how often charts, etc. 64 * should refetch /debug/vars. 65 */ 66 export const QPS_REFETCH_INTERVAL = 2500; 67 68 export const RATES_INTERVAL = 5; // 5 seconds 69 export const RATES_MAX_SPAN = 15 * 60; // 15 minutes 70 export const SERIES_LENGTH = RATES_MAX_SPAN / RATES_INTERVAL; 71 72 /** 73 * formatTimeseriesMap formats an array of numbers from a Rates stats counter as 74 * an array of TimeseriesPoints. 75 * 76 * For Rates stats, see https://github.com/vitessio/vitess/blob/main/go/stats/rates.go 77 * 78 * @param rates - An array of numbers, inferred as data points at 5 second intervals. 79 * 80 * @param endAt - Optional. The timestamp for the last (most recent) data point in the series. 81 * The `dataUpdatedAt` property of a query is recommended. Defaults to Date.now() if unspecified. 82 */ 83 export const formatTimeseriesMap = (rates: { [k: string]: number[] }, endAt?: number): TimeseriesMap => { 84 // Rates stats are (unfortunately) not returned with timestamps, so we infer them here. 85 // This behaviour matches that of the vtctld2 UI: 86 // https://github.com/vitessio/vitess/blob/main/go/vt/vttablet/tabletserver/status.go#L178 87 const _endAt = typeof endAt === 'number' ? endAt : Date.now(); 88 89 // The `rates` map returned from the API, keyed by series name, will either: 90 // (a) be empty, or 91 // (b) contain a minimum of two series, one of them named "All". 92 // In the first case, inserting an empty "All" series renders more nicely 93 // on a Highcharts graph since it will include the axes, etc. So, we add it here. 94 const _rates = !!Object.keys(rates).length ? rates : { All: [] }; 95 96 const planTypes = Object.keys(_rates); 97 98 const data: TimeseriesMap = {}; 99 100 // This logic is borrowed from the vtctld2 UI 101 // https://github.com/vitessio/vitess/blob/09e74af/go/vt/vttablet/tabletmanager/vreplication/stats.go#L478-L505 102 for (let i = 0; i < RATES_MAX_SPAN / RATES_INTERVAL; i++) { 103 const x = _endAt - ((i * 60) / RATES_INTERVAL) * 1000; 104 105 for (let j = 0; j < planTypes.length; j++) { 106 // Assume 0.0 QPS for older, non-existent data points. 107 let y = 0; 108 109 if (i < _rates[planTypes[j]].length) { 110 const idx = _rates[planTypes[j]].length - i - 1; 111 y = +_rates[planTypes[j]][idx].toFixed(2); 112 } 113 114 if (!Array.isArray(data[planTypes[j]])) { 115 data[planTypes[j]] = []; 116 } 117 118 data[planTypes[j]].unshift({ x, y }); 119 } 120 } 121 122 return data; 123 };