Skip to content

Commit

Permalink
[STATS] Update stats architecture (#891)
Browse files Browse the repository at this point in the history
Main goal: allow more complex relations between charts

Main changes overview:
- flexible framework for data retrieval, processing, and storage
- flexible data dependencies with synchronized and efficient updates
- config reorganization and changes (see `migration` in config files folder for more)

Tech debt mitigated:
- `order` parameter in config changed to list; overrideable with env
- compilation without test-utils fix (tests can be run w/o the feature)
- remove duplication of configs (in runtime)
- deprecate toml config
- more accurate metrics collection (exclude mutex waiting)
- fix fill logic when to in request is None
- update some dependencies versions

Collateral changes:
- querying get_chart_data (now `get_line_chart_data`) without `fill_missing_dates` now returns data only within range  according to missing date policy (for FillPrevious the first data point is moved from outside the range, if needed) (previously it could add a point before the range)
  • Loading branch information
bragov4ik authored Jun 26, 2024
1 parent 5018100 commit f8e81fc
Show file tree
Hide file tree
Showing 143 changed files with 10,858 additions and 5,933 deletions.
1 change: 1 addition & 0 deletions libs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"blockscout-service-launcher",
"display-bytes",
"env-collector",
"metrics-tools",
"mismatch",
"reqwest-rate-limiter",
"solidity-metadata",
Expand Down
11 changes: 11 additions & 0 deletions libs/metrics-tools/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "blockscout-metrics-tools"
version = "0.1.0"
description = "Collection of tools helpful for metrics collection"
license = "MIT"
repository = "https://github.com/blockscout/blockscout-rs"
edition = "2021"
keywords = ["metrics", "time"]
categories = ["date-and-time"]

[dependencies]
99 changes: 99 additions & 0 deletions libs/metrics-tools/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use std::time::{Duration, Instant};

/// Timer that combines multiple time intervals into a single measurements.
///
/// The intervals are non-overlapping. Next interval can be started via [`AggregateTimer::start_interval`]
#[derive(Debug)]
pub struct AggregateTimer {
recorded_time_secs: Duration,
}

impl Default for AggregateTimer {
fn default() -> Self {
AggregateTimer::new()
}
}

impl AggregateTimer {
pub fn new() -> Self {
Self {
recorded_time_secs: Duration::from_secs(0),
}
}

pub fn start_interval(&mut self) -> Interval {
Interval {
start_time: Instant::now(),
recorder: self,
discarded: false,
}
}

/// Add to the total
pub fn add_time(&mut self, time: Duration) {
self.recorded_time_secs += time;
}

/// Total time recorded so far
pub fn total_time(&self) -> Duration {
self.recorded_time_secs
}
}

/// Timer tracking next interval.
/// Records passed time when it's dropped.
#[must_use = "Interval cannot record duration if it is not kept in a variable"]
#[derive(Debug)]
pub struct Interval<'a> {
start_time: Instant,
recorder: &'a mut AggregateTimer,
discarded: bool,
}

impl<'a> Interval<'a> {
/// Get current time of the interval without recording.
pub fn elapsed_from_start(&self) -> Duration {
self.start_time.elapsed()
}

/// Do not record this interval.
pub fn discard(mut self) {
self.discarded = true;
}
}

impl<'a> Drop for Interval<'a> {
fn drop(&mut self) {
if !self.discarded {
self.recorder.add_time(self.elapsed_from_start())
}
}
}

#[cfg(test)]
mod tests {
use std::thread::sleep;

use super::*;

#[test]
fn intervals_are_approx_recorded() {
let mut timer = AggregateTimer::new();
let mut total_min_time = Duration::from_secs(0);
{
let time = Duration::from_secs_f64(0.1);
total_min_time += time;
let _interval = timer.start_interval();
sleep(time);
}
{
let time = Duration::from_secs_f64(0.2);
total_min_time += time;
let _interval = timer.start_interval();
sleep(time);
}
// sleep pauses for "at least the specified amount of time"
assert!(timer.total_time() > total_min_time)
// thus the test should be not flaky
}
}
1 change: 0 additions & 1 deletion stats/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ target
Dockerfile
README.md
tests
config.toml
data
Loading

0 comments on commit f8e81fc

Please sign in to comment.