github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/util/appStats.ts (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 // This file significantly duplicates the algorithms available in 12 // pkg/roachpb/app_stats.go, in particular the functions on NumericStats 13 // to compute variance and add together NumericStats. 14 15 import _ from "lodash"; 16 import * as protos from "src/js/protos"; 17 import { FixLong } from "src/util/fixLong"; 18 import ISensitiveInfo = protos.cockroach.sql.ISensitiveInfo; 19 20 export type StatementStatistics = protos.cockroach.sql.IStatementStatistics; 21 export type CollectedStatementStatistics = protos.cockroach.server.serverpb.StatementsResponse.ICollectedStatementStatistics; 22 23 export interface NumericStat { 24 mean?: number; 25 squared_diffs?: number; 26 } 27 28 export function variance(stat: NumericStat, count: number) { 29 return stat.squared_diffs / (count - 1); 30 } 31 32 export function stdDev(stat: NumericStat, count: number) { 33 return Math.sqrt(variance(stat, count)) || 0; 34 } 35 36 export function stdDevLong(stat: NumericStat, count: number | Long) { 37 return stdDev(stat, FixLong(count).toInt()); 38 } 39 40 export function addNumericStats(a: NumericStat, b: NumericStat, countA: number, countB: number) { 41 const total = countA + countB; 42 const delta = b.mean - a.mean; 43 44 return { 45 mean: ((a.mean * countA) + (b.mean * countB)) / total, 46 squared_diffs: (a.squared_diffs + b.squared_diffs) + delta * delta * countA * countB / total, 47 }; 48 } 49 50 export function addStatementStats(a: StatementStatistics, b: StatementStatistics) { 51 const countA = FixLong(a.count).toInt(); 52 const countB = FixLong(b.count).toInt(); 53 return { 54 count: a.count.add(b.count), 55 first_attempt_count: a.first_attempt_count.add(b.first_attempt_count), 56 max_retries: a.max_retries.greaterThan(b.max_retries) ? a.max_retries : b.max_retries, 57 num_rows: addNumericStats(a.num_rows, b.num_rows, countA, countB), 58 parse_lat: addNumericStats(a.parse_lat, b.parse_lat, countA, countB), 59 plan_lat: addNumericStats(a.plan_lat, b.plan_lat, countA, countB), 60 run_lat: addNumericStats(a.run_lat, b.run_lat, countA, countB), 61 service_lat: addNumericStats(a.service_lat, b.service_lat, countA, countB), 62 overhead_lat: addNumericStats(a.overhead_lat, b.overhead_lat, countA, countB), 63 sensitive_info: coalesceSensitiveInfo(a.sensitive_info, b.sensitive_info), 64 }; 65 } 66 67 export function coalesceSensitiveInfo(a: ISensitiveInfo, b: ISensitiveInfo) { 68 return { 69 last_err: a.last_err || b.last_err, 70 most_recent_plan_description: a.most_recent_plan_description || b.most_recent_plan_description, 71 }; 72 } 73 74 export function aggregateStatementStats(statementStats: CollectedStatementStatistics[]) { 75 const statementsMap: { [statement: string]: CollectedStatementStatistics[] } = {}; 76 statementStats.forEach( 77 (statement: CollectedStatementStatistics) => { 78 const matches = statementsMap[statement.key.key_data.query] || (statementsMap[statement.key.key_data.query] = []); 79 matches.push(statement); 80 }); 81 82 return _.values(statementsMap).map(statements => 83 _.reduce(statements, (a: CollectedStatementStatistics, b: CollectedStatementStatistics) => ({ 84 key: a.key, 85 stats: addStatementStats(a.stats, b.stats), 86 })), 87 ); 88 } 89 90 export interface ExecutionStatistics { 91 statement: string; 92 app: string; 93 distSQL: boolean; 94 opt: boolean; 95 implicit_txn: boolean; 96 failed: boolean; 97 node_id: number; 98 stats: StatementStatistics; 99 } 100 101 export function flattenStatementStats(statementStats: CollectedStatementStatistics[]): ExecutionStatistics[] { 102 return statementStats.map(stmt => ({ 103 statement: stmt.key.key_data.query, 104 app: stmt.key.key_data.app, 105 distSQL: stmt.key.key_data.distSQL, 106 opt: stmt.key.key_data.opt, 107 implicit_txn: stmt.key.key_data.implicit_txn, 108 failed: stmt.key.key_data.failed, 109 node_id: stmt.key.node_id, 110 stats: stmt.stats, 111 })); 112 } 113 114 export function combineStatementStats(statementStats: StatementStatistics[]): StatementStatistics { 115 return _.reduce(statementStats, addStatementStats); 116 }