// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see .
//! Statistical functions and helpers.
use std::{
iter::FromIterator,
ops::{Add, Deref, Div, Sub},
time::Instant,
};
#[macro_use]
extern crate log;
pub extern crate prometheus;
/// Implements a prometheus metrics collector
pub trait PrometheusMetrics {
fn prometheus_metrics(&self, registry: &mut prometheus::Registry);
}
/// Adds a new prometheus counter with the specified value
pub fn prometheus_counter(reg: &mut prometheus::Registry, name: &str, help: &str, value: i64) {
let c = prometheus::IntCounter::new(name, help).expect("name and help must be non-empty");
c.inc_by(value);
reg.register(Box::new(c))
.expect("prometheus identifiers must be unique");
}
/// Adds a new prometheus gauge with the specified gauge
pub fn prometheus_gauge(reg: &mut prometheus::Registry, name: &str, help: &str, value: i64) {
let g = prometheus::IntGauge::new(name, help).expect("name and help must be non-empty");
g.set(value);
reg.register(Box::new(g))
.expect("prometheus identifiers must be are unique");
}
/// Adds a new prometheus counter with the time spent in running the specified function
pub fn prometheus_optime T, T>(r: &mut prometheus::Registry, name: &str, f: &F) -> T {
let start = Instant::now();
let t = f();
let elapsed = start.elapsed();
prometheus_gauge(
r,
&format!("optime_{}", name),
&format!("Time to perform {}", name),
elapsed.as_millis() as i64,
);
t
}
/// Sorted corpus of data.
#[derive(Debug, Clone, PartialEq)]
pub struct Corpus(Vec);
impl From> for Corpus {
fn from(mut data: Vec) -> Self {
data.sort();
Corpus(data)
}
}
impl FromIterator for Corpus {
fn from_iter>(iterable: I) -> Self {
iterable.into_iter().collect::>().into()
}
}
impl Deref for Corpus {
type Target = [T];
fn deref(&self) -> &[T] {
&self.0[..]
}
}
impl Corpus {
/// Get given percentile (approximated).
pub fn percentile(&self, val: usize) -> Option<&T> {
let len = self.0.len();
let x = val * len / 100;
let x = ::std::cmp::min(x, len);
if x == 0 {
return None;
}
self.0.get(x - 1)
}
/// Get the median element, if it exists.
pub fn median(&self) -> Option<&T> {
self.0.get(self.0.len() / 2)
}
/// Whether the corpus is empty.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Number of elements in the corpus.
pub fn len(&self) -> usize {
self.0.len()
}
}
impl Corpus
where
T: Add