@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
88 lines (74 loc) • 2.56 kB
text/typescript
import {GaugeConfiguration} from "prom-client";
import {AvgMinMax as IAvgMinMax, LabelKeys, LabelsGeneric} from "@lodestar/utils";
import {GaugeExtra} from "./gauge.js";
type GetValuesFn = () => number[];
/**
* Special non-standard "Histogram" that captures the avg, min and max of values
*/
export class AvgMinMax<Labels extends LabelsGeneric> implements IAvgMinMax<Labels> {
private readonly sum: GaugeExtra<Labels>;
private readonly avg: GaugeExtra<Labels>;
private readonly min: GaugeExtra<Labels>;
private readonly max: GaugeExtra<Labels>;
private getValuesFn: GetValuesFn | null = null;
constructor(configuration: GaugeConfiguration<LabelKeys<Labels>>) {
this.sum = new GaugeExtra({...configuration, name: `${configuration.name}_sum`});
this.avg = new GaugeExtra({...configuration, name: `${configuration.name}_avg`});
this.min = new GaugeExtra({...configuration, name: `${configuration.name}_min`});
this.max = new GaugeExtra({...configuration, name: `${configuration.name}_max`});
}
addGetValuesFn(getValuesFn: GetValuesFn): void {
if (this.getValuesFn === null) {
this.getValuesFn = getValuesFn;
this.avg.addCollect(this.onCollect);
} else {
throw Error("Already registered a getValuesFn");
}
}
set(values: number[]): void;
set(labels: Labels, values: number[]): void;
set(arg1?: Labels | number[], arg2?: number[]): void {
if (arg2 === undefined) {
const values = arg1 as number[];
const {sum, avg, min, max} = getStats(values);
this.sum.set(sum);
this.avg.set(avg);
this.min.set(min);
this.max.set(max);
} else {
const values = (arg2 !== undefined ? arg2 : arg1) as number[];
const labels = arg1 as Labels;
const {sum, avg, min, max} = getStats(values);
this.sum.set(labels, sum);
this.avg.set(labels, avg);
this.min.set(labels, min);
this.max.set(labels, max);
}
}
private onCollect = (): void => {
if (this.getValuesFn !== null) {
this.set(this.getValuesFn());
}
};
}
type ArrStatistics = {
sum: number;
avg: number;
min: number;
max: number;
};
function getStats(values: number[]): ArrStatistics {
if (values.length < 1) {
return {sum: 0, avg: 0, min: 0, max: 0};
}
let min = values[0];
let max = values[0];
let sum = values[0];
for (let i = 1; i < values.length; i++) {
const val = values[i];
if (val < min) min = val;
if (val > max) max = val;
sum += val;
}
return {sum, avg: sum / values.length, min, max};
}