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>(
86        &self,
87        instances: I,
88        use_internal_ip_address: bool,
89    ) -> Vec<(Instance, String)>
90    where
91        I: IntoIterator<Item = Instance>;
92    /// The command to retrieve the metrics from the nodes.
93    fn nodes_metrics_command<I>(
94        &self,
95        instances: I,
96        use_internal_ip_address: bool,
97    ) -> Vec<(Instance, String)>
98    where
99        I: IntoIterator<Item = Instance>,
100    {
101        self.nodes_metrics_path(instances, use_internal_ip_address)
102            .into_iter()
103            .map(|(instance, path)| {
104                let cmd = format!("curl '{path}'");
105                display::action(format!("\n{cmd}"));
106                (instance, cmd)
107            })
108            .collect()
109    }
110
111    /// The command to retrieve the flamegraphs from the nodes.
112    fn nodes_flamegraph_command<I>(&self, instances: I, query: &str) -> Vec<(Instance, String)>
113    where
114        I: IntoIterator<Item = Instance>,
115    {
116        instances
117            .into_iter()
118            .map(|instance| {
119                (instance, {
120                    let cmd = format!("curl 'http://localhost:1337/flamegraph{query}'");
121                    display::action(format!("\n{cmd}"));
122                    cmd.to_string()
123                })
124            })
125            .collect()
126    }
127
128    /// The network path where the clients expose prometheus metrics.
129    fn clients_metrics_path<I>(
130        &self,
131        instances: I,
132        use_internal_ip_address: bool,
133    ) -> Vec<(Instance, String)>
134    where
135        I: IntoIterator<Item = Instance>;
136    /// The command to retrieve the metrics from the clients.
137    fn clients_metrics_command<I>(
138        &self,
139        instances: I,
140        use_internal_ip_address: bool,
141    ) -> Vec<(Instance, String)>
142    where
143        I: IntoIterator<Item = Instance>,
144    {
145        self.clients_metrics_path(instances, use_internal_ip_address)
146            .into_iter()
147            .map(|(instance, path)| (instance, format!("curl -s '{path}'")))
148            .collect()
149    }
150}
151
152#[cfg(test)]
153pub mod test_protocol_metrics {
154    use super::ProtocolMetrics;
155    use crate::client::Instance;
156
157    pub struct TestProtocolMetrics;
158
159    impl ProtocolMetrics for TestProtocolMetrics {
160        const BENCHMARK_DURATION: &'static str = "benchmark_duration";
161        const TOTAL_TRANSACTIONS: &'static str = "latency_s_count";
162        const LATENCY_BUCKETS: &'static str = "latency_s";
163        const LATENCY_SUM: &'static str = "latency_s_sum";
164        const LATENCY_SQUARED_SUM: &'static str = "latency_squared_s";
165
166        fn nodes_metrics_path<I>(
167            &self,
168            instances: I,
169            _use_internal_ip_address: bool,
170        ) -> Vec<(Instance, String)>
171        where
172            I: IntoIterator<Item = Instance>,
173        {
174            instances
175                .into_iter()
176                .enumerate()
177                .map(|(i, instance)| (instance, format!("localhost:{}/metrics", 8000 + i as u16)))
178                .collect()
179        }
180
181        fn clients_metrics_path<I>(
182            &self,
183            instances: I,
184            _use_internal_ip_address: bool,
185        ) -> Vec<(Instance, String)>
186        where
187            I: IntoIterator<Item = Instance>,
188        {
189            instances
190                .into_iter()
191                .enumerate()
192                .map(|(i, instance)| (instance, format!("localhost:{}/metrics", 9000 + i as u16)))
193                .collect()
194        }
195    }
196}