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  }