iota_aws_orchestrator/protocol/
mod.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::path::PathBuf;
6
7use crate::{
8    benchmark::{BenchmarkParameters, BenchmarkType},
9    client::Instance,
10    display,
11};
12
13pub mod iota;
14
15/// The minimum interface that the protocol should implement to allow benchmarks
16/// from the orchestrator.
17pub trait ProtocolCommands<T: BenchmarkType> {
18    /// The list of dependencies to install (e.g., through apt-get).
19    fn protocol_dependencies(&self) -> Vec<&'static str>;
20
21    /// The directories of all databases (that should be erased before each
22    /// run).
23    fn db_directories(&self) -> Vec<PathBuf>;
24
25    /// The command to generate the genesis and all configuration files. This
26    /// command is run on each remote machine.
27    fn genesis_command<'a, I>(&self, instances: I, parameters: &BenchmarkParameters<T>) -> String
28    where
29        I: Iterator<Item = &'a Instance>;
30
31    /// The command to run a node. The function returns a vector of commands
32    /// along with the associated instance on which to run the command.
33    fn node_command<I>(
34        &self,
35        instances: I,
36        parameters: &BenchmarkParameters<T>,
37    ) -> Vec<(Instance, String)>
38    where
39        I: IntoIterator<Item = Instance>;
40
41    /// The command to run a fullnode. The function returns a vector of commands
42    /// along with the associated instance on which to run the command.
43    fn fullnode_command<I>(
44        &self,
45        instances: I,
46        parameters: &BenchmarkParameters<T>,
47    ) -> Vec<(Instance, String)>
48    where
49        I: IntoIterator<Item = Instance>;
50
51    fn monitor_command<I>(&self, instances: I) -> Vec<(Instance, String)>
52    where
53        I: IntoIterator<Item = Instance>;
54
55    /// The command to run a client. The function returns a vector of commands
56    /// along with the associated instance on which to run the command.
57    fn client_command<I>(
58        &self,
59        instances: I,
60        parameters: &BenchmarkParameters<T>,
61    ) -> Vec<(Instance, String)>
62    where
63        I: IntoIterator<Item = Instance>;
64}
65
66/// The names of the minimum metrics exposed by the load generators that are
67/// required to compute performance.
68pub trait ProtocolMetrics {
69    /// The name of the metric reporting the total duration of the benchmark (in
70    /// seconds).
71    const BENCHMARK_DURATION: &'static str;
72    /// The name of the metric reporting the total number of finalized
73    /// transactions
74    const TOTAL_TRANSACTIONS: &'static str;
75    /// The name of the metric reporting the latency buckets.
76    const LATENCY_BUCKETS: &'static str;
77    /// The name of the metric reporting the sum of the end-to-end latency of
78    /// all finalized transactions.
79    const LATENCY_SUM: &'static str;
80    /// The name of the metric reporting the square of the sum of the end-to-end
81    /// latency of all finalized transactions.
82    const LATENCY_SQUARED_SUM: &'static str;
83
84    /// The network path where the nodes expose prometheus metrics.
85    fn nodes_metrics_path<I, T>(
86        &self,
87        instances: I,
88        parameters: &BenchmarkParameters<T>,
89    ) -> Vec<(Instance, String)>
90    where
91        I: IntoIterator<Item = Instance>,
92        T: BenchmarkType;
93    /// The command to retrieve the metrics from the nodes.
94    fn nodes_metrics_command<I, T>(
95        &self,
96        instances: I,
97        parameters: &BenchmarkParameters<T>,
98    ) -> Vec<(Instance, String)>
99    where
100        I: IntoIterator<Item = Instance>,
101        T: BenchmarkType,
102    {
103        self.nodes_metrics_path(instances, parameters)
104            .into_iter()
105            .map(|(instance, path)| {
106                let cmd = format!("curl '{path}'");
107                display::action(format!("\n{cmd}"));
108                (instance, cmd)
109            })
110            .collect()
111    }
112
113    /// The command to retrieve the flamegraphs from the nodes.
114    fn nodes_flamegraph_command<I, T>(
115        &self,
116        instances: I,
117        _parameters: &BenchmarkParameters<T>,
118        query: &str,
119    ) -> Vec<(Instance, String)>
120    where
121        I: IntoIterator<Item = Instance>,
122        T: BenchmarkType,
123    {
124        instances
125            .into_iter()
126            .map(|instance| {
127                (instance, {
128                    let cmd = format!("curl 'http://localhost:1337/flamegraph{query}'");
129                    display::action(format!("\n{cmd}"));
130                    cmd.to_string()
131                })
132            })
133            .collect()
134    }
135
136    /// The network path where the clients expose prometheus metrics.
137    fn clients_metrics_path<I, T>(
138        &self,
139        instances: I,
140        parameters: &BenchmarkParameters<T>,
141    ) -> Vec<(Instance, String)>
142    where
143        I: IntoIterator<Item = Instance>,
144        T: BenchmarkType;
145    /// The command to retrieve the metrics from the clients.
146    fn clients_metrics_command<I, T>(
147        &self,
148        instances: I,
149        parameters: &BenchmarkParameters<T>,
150    ) -> Vec<(Instance, String)>
151    where
152        I: IntoIterator<Item = Instance>,
153        T: BenchmarkType,
154    {
155        self.clients_metrics_path(instances, parameters)
156            .into_iter()
157            .map(|(instance, path)| (instance, format!("curl '{path}'")))
158            .collect()
159    }
160}
161
162#[cfg(test)]
163pub mod test_protocol_metrics {
164    use super::ProtocolMetrics;
165    use crate::{
166        benchmark::{BenchmarkParameters, BenchmarkType},
167        client::Instance,
168    };
169
170    pub struct TestProtocolMetrics;
171
172    impl ProtocolMetrics for TestProtocolMetrics {
173        const BENCHMARK_DURATION: &'static str = "benchmark_duration";
174        const TOTAL_TRANSACTIONS: &'static str = "latency_s_count";
175        const LATENCY_BUCKETS: &'static str = "latency_s";
176        const LATENCY_SUM: &'static str = "latency_s_sum";
177        const LATENCY_SQUARED_SUM: &'static str = "latency_squared_s";
178
179        fn nodes_metrics_path<I, T>(
180            &self,
181            instances: I,
182            _parameters: &BenchmarkParameters<T>,
183        ) -> Vec<(Instance, String)>
184        where
185            I: IntoIterator<Item = Instance>,
186            T: BenchmarkType,
187        {
188            instances
189                .into_iter()
190                .enumerate()
191                .map(|(i, instance)| (instance, format!("localhost:{}/metrics", 8000 + i as u16)))
192                .collect()
193        }
194
195        fn clients_metrics_path<I, T>(
196            &self,
197            instances: I,
198            _parameters: &BenchmarkParameters<T>,
199        ) -> Vec<(Instance, String)>
200        where
201            I: IntoIterator<Item = Instance>,
202            T: BenchmarkType,
203        {
204            instances
205                .into_iter()
206                .enumerate()
207                .map(|(i, instance)| (instance, format!("localhost:{}/metrics", 9000 + i as u16)))
208                .collect()
209        }
210    }
211}