import { FC } from "react"; import ASTNode, { Aggregation, aggregationType } from "../../../promql/ast"; import { labelNameList } from "../../../promql/format"; import { parsePrometheusFloat } from "../../../lib/formatFloatValue"; import { Card, Text } from "@mantine/core"; const describeAggregationType = ( aggrType: aggregationType, param: ASTNode | null ) => { switch (aggrType) { case "sum": return "sums over the sample values of the input series"; case "min": return "takes the minimum of the sample values of the input series"; case "max": return "takes the maximum of the sample values of the input series"; case "avg": return "calculates the average of the sample values of the input series"; case "stddev": return "calculates the population standard deviation of the sample values of the input series"; case "stdvar": return "calculates the population standard variation of the sample values of the input series"; case "count": return "counts the number of input series"; case "group": return "groups the input series by the supplied grouping labels, while setting the sample value to 1"; case "count_values": if (param === null) { throw new Error( "encountered count_values() node without label parameter" ); } if (param.type !== "stringLiteral") { throw new Error( "encountered count_values() node without string literal label parameter" ); } return ( <> outputs one time series for each unique sample value in the input series (each counting the number of occurrences of that value and indicating the original value in the {labelNameList([param.val])}{" "} label) ); case "bottomk": if (param === null || param.type !== "numberLiteral") { return ( <> returns the bottom{" "} K series by value ); } return ( <> returns the bottom{" "} {param.val} series by value ); case "topk": if (param === null || param.type !== "numberLiteral") { return ( <> returns the top K{" "} series by value ); } return ( <> returns the top{" "} {param.val} series by value ); case "quantile": if (param === null) { throw new Error( "encountered quantile() node without quantile parameter" ); } if (param.type === "numberLiteral") { return `calculates the ${param.val}th quantile (${ parsePrometheusFloat(param.val) * 100 }th percentile) over the sample values of the input series`; } return "calculates a quantile over the sample values of the input series"; case "limitk": if (param === null || param.type !== "numberLiteral") { return ( <> limits the output to{" "} K series ); } return ( <> limits the output to{" "} {param.val} series ); case "limit_ratio": if (param === null || param.type !== "numberLiteral") { return "limits the output to a ratio of the input series"; } return ( <> limits the output to a ratio of{" "} {param.val} ( {parsePrometheusFloat(param.val) * 100}%) of the input series ); default: throw new Error(`invalid aggregation type ${aggrType}`); } }; const describeAggregationGrouping = (grouping: string[], without: boolean) => { if (without) { return ( <>aggregating away the [{labelNameList(grouping)}] label dimensions ); } if (grouping.length === 1) { return <>grouped by their {labelNameList(grouping)} label dimension; } if (grouping.length > 1) { return <>grouped by their [{labelNameList(grouping)}] label dimensions; } return "aggregating away any label dimensions"; }; interface AggregationExplainViewProps { node: Aggregation; } const AggregationExplainView: FC = ({ node }) => { return ( Aggregation This node {describeAggregationType(node.op, node.param)},{" "} {describeAggregationGrouping(node.grouping, node.without)}. ); }; export default AggregationExplainView;