-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathconfig.rs
124 lines (106 loc) · 5.04 KB
/
config.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Application configuration.
use crate::util::serde_duration_millis;
use chrono::Duration;
use eyre::{eyre, Context, Result};
use serde::{Deserialize, Serialize};
use std::env;
use std::path::PathBuf;
/// The environment variable key for the [AppConfig.iterations] setting.
pub const ENV_KEY_ITERATIONS: &str = "FHIR_BENCH_ITERATIONS";
/// The environment variable key for the [AppConfig.operation_timeout] setting (in milliseconds).
pub const ENV_KEY_OPERATION_TIMEOUT: &str = "FHIR_BENCH_OPERATION_TIMEOUT_MS";
/// The environment variable key for the [AppConfig.concurrency_levels] setting.
pub const ENV_KEY_CONCURRENCY_LEVELS: &str = "FHIR_BENCH_CONCURRENCY_LEVELS";
/// The environment variable key for the [AppConfig.population_size] setting.
pub const ENV_KEY_POPULATION_SIZE: &str = "FHIR_BENCH_POPULATION_SIZE";
/// Represents the application's configuration.
#[derive(Clone, Deserialize, Serialize)]
pub struct AppConfig {
/// The maximum number of iterations to exercise each operation for, during a benchmark run.
pub iterations: u32,
/// The maximum amount of time to let any individual operation being benchmarked run for.
#[serde(with = "serde_duration_millis")]
pub operation_timeout: Duration,
/// The concurrency level(s) to test at. Each operation will be tested with an attempt to model each
/// specified number of concurrent users.
pub concurrency_levels: Vec<u32>,
/// The maximum synthetic patient population size to benchmark with.
pub population_size: u32,
}
impl AppConfig {
pub fn new() -> Result<AppConfig> {
// If present, load environment variables from a `.env` file in the working directory.
dotenv::dotenv().ok();
// Parse iterations.
let iterations: std::result::Result<String, std::env::VarError> =
env::var(ENV_KEY_ITERATIONS).or_else(|_| Ok(String::from("1000")));
let iterations: u32 = iterations
.context(format!("Unable to read {}.", ENV_KEY_ITERATIONS))?
.parse()
.context(format!("Unable to parse {}.", ENV_KEY_ITERATIONS))?;
// Parse operation_timeout.
let operation_timeout: std::result::Result<String, std::env::VarError> =
env::var(ENV_KEY_OPERATION_TIMEOUT).or_else(|_| Ok(String::from("10000")));
let operation_timeout: u32 = operation_timeout
.context(format!("Unable to read {}.", ENV_KEY_OPERATION_TIMEOUT))?
.parse()
.context(format!("Unable to parse {}.", ENV_KEY_OPERATION_TIMEOUT))?;
let operation_timeout = Duration::milliseconds(operation_timeout as i64);
// Parse concurrency_levels.
let concurrency_levels: std::result::Result<String, std::env::VarError> =
env::var(ENV_KEY_CONCURRENCY_LEVELS).or_else(|_| Ok(String::from("1,10")));
let concurrency_levels: std::result::Result<Vec<u32>, _> = concurrency_levels
.context(format!("Unable to read {}.", ENV_KEY_CONCURRENCY_LEVELS))?
.split(',')
.map(str::parse::<u32>)
.collect();
let concurrency_levels = concurrency_levels
.context(format!("Unable to parse {}.", ENV_KEY_CONCURRENCY_LEVELS))?;
// Parse population_size.
let population_size: std::result::Result<String, std::env::VarError> =
env::var(ENV_KEY_POPULATION_SIZE).or_else(|_| Ok(String::from("100")));
let population_size: u32 = population_size
.context(format!("Unable to read {}.", ENV_KEY_POPULATION_SIZE))?
.parse()
.context(format!("Unable to parse {}.", ENV_KEY_POPULATION_SIZE))?;
Ok(AppConfig {
iterations,
operation_timeout,
concurrency_levels,
population_size,
})
}
/// Returns the root directory for the benchmarks project; the Git repo's top-level directory.
pub fn benchmark_dir(&self) -> Result<PathBuf> {
benchmark_dir()
}
}
/// Returns the root directory for the benchmarks project; the Git repo's top-level directory.
pub fn benchmark_dir() -> Result<PathBuf> {
// For now, this is hard-coded to check a couple of likely scenarios:
//
// 1. Someone is running from the `fhir-bench-orchestrator` module, like might happen if they are
// running a specific test from their IDE.
// 2. Someone is running from the Git project's root directory, like they might from a terminal.
let current_dir = std::env::current_dir().context("unable to retrieve current directory")?;
if current_dir
.file_name()
.map(|n| n.to_string_lossy().to_string())
== Some("fhir-bench-orchestrator".to_string())
{
Ok(current_dir
.parent()
.expect("Unable to get module parent directory.")
.into())
} else if current_dir
.read_dir()?
.any(|e| e.is_ok() && e.as_ref().unwrap().file_name() == ".git")
{
Ok(current_dir)
} else {
Err(eyre!(
"Unable to find benchmark directory from current directory: '{:?}'",
current_dir
))
}
}