hyperi_rustlib/cli/
args.rs1#[derive(Debug, Clone, clap::Args)]
31pub struct CommonArgs {
32 #[arg(short = 'c', long = "config")]
34 pub config: Option<String>,
35
36 #[arg(
38 short = 'l',
39 long = "log-level",
40 env = "LOG_LEVEL",
41 default_value = "info"
42 )]
43 pub log_level: String,
44
45 #[arg(long = "log-format", env = "LOG_FORMAT", default_value = "auto")]
47 pub log_format: String,
48
49 #[arg(
51 long = "metrics-addr",
52 env = "METRICS_ADDR",
53 default_value = "0.0.0.0:9090"
54 )]
55 pub metrics_addr: String,
56
57 #[arg(short = 'v', long, conflicts_with = "quiet")]
59 pub verbose: bool,
60
61 #[arg(short = 'q', long, conflicts_with = "verbose")]
63 pub quiet: bool,
64}
65
66impl CommonArgs {
67 #[must_use]
69 pub fn effective_log_level(&self) -> &str {
70 if self.verbose {
71 "debug"
72 } else if self.quiet {
73 "error"
74 } else {
75 &self.log_level
76 }
77 }
78
79 #[cfg(feature = "logger")]
87 pub fn to_logger_options(&self) -> Result<crate::logger::LoggerOptions, super::CliError> {
88 use std::str::FromStr;
89
90 let level: tracing::Level =
91 self.effective_log_level()
92 .to_uppercase()
93 .parse()
94 .map_err(|_| {
95 super::CliError::InvalidArgument(format!(
96 "invalid log level: {}",
97 self.effective_log_level()
98 ))
99 })?;
100
101 let format = crate::logger::LogFormat::from_str(&self.log_format)
102 .map_err(|e| super::CliError::InvalidArgument(format!("invalid log format: {e}")))?;
103
104 Ok(crate::logger::LoggerOptions {
105 level,
106 format,
107 ..Default::default()
108 })
109 }
110
111 #[cfg(feature = "config")]
119 #[must_use]
120 pub fn to_config_options(&self, env_prefix: &str) -> crate::config::ConfigOptions {
121 crate::config::ConfigOptions {
122 env_prefix: env_prefix.to_string(),
123 config_file: self.config.as_deref().map(std::path::PathBuf::from),
124 ..Default::default()
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_effective_log_level_default() {
135 let args = CommonArgs {
136 config: None,
137 log_level: "info".to_string(),
138 log_format: "auto".to_string(),
139 metrics_addr: "0.0.0.0:9090".to_string(),
140 verbose: false,
141 quiet: false,
142 };
143 assert_eq!(args.effective_log_level(), "info");
144 }
145
146 #[test]
147 fn test_effective_log_level_verbose() {
148 let args = CommonArgs {
149 config: None,
150 log_level: "info".to_string(),
151 log_format: "auto".to_string(),
152 metrics_addr: "0.0.0.0:9090".to_string(),
153 verbose: true,
154 quiet: false,
155 };
156 assert_eq!(args.effective_log_level(), "debug");
157 }
158
159 #[test]
160 fn test_effective_log_level_quiet() {
161 let args = CommonArgs {
162 config: None,
163 log_level: "info".to_string(),
164 log_format: "auto".to_string(),
165 metrics_addr: "0.0.0.0:9090".to_string(),
166 verbose: false,
167 quiet: true,
168 };
169 assert_eq!(args.effective_log_level(), "error");
170 }
171
172 #[cfg(feature = "config")]
173 #[test]
174 fn test_to_config_options_sets_config_file_not_paths() {
175 let args = CommonArgs {
176 config: Some("/etc/svc/config.yaml".to_string()),
177 log_level: "info".to_string(),
178 log_format: "auto".to_string(),
179 metrics_addr: "0.0.0.0:9090".to_string(),
180 verbose: false,
181 quiet: false,
182 };
183 let opts = args.to_config_options("MY_SVC");
184 assert_eq!(opts.env_prefix, "MY_SVC");
185 assert_eq!(
187 opts.config_file,
188 Some(std::path::PathBuf::from("/etc/svc/config.yaml"))
189 );
190 assert!(opts.config_paths.is_empty());
191 }
192
193 #[cfg(feature = "config")]
194 #[test]
195 fn test_to_config_options_no_config_file_when_absent() {
196 let args = CommonArgs {
197 config: None,
198 log_level: "info".to_string(),
199 log_format: "auto".to_string(),
200 metrics_addr: "0.0.0.0:9090".to_string(),
201 verbose: false,
202 quiet: false,
203 };
204 let opts = args.to_config_options("MY_SVC");
205 assert!(opts.config_file.is_none());
206 assert!(opts.config_paths.is_empty());
207 }
208
209 #[test]
210 fn test_effective_log_level_custom() {
211 let args = CommonArgs {
212 config: None,
213 log_level: "warn".to_string(),
214 log_format: "auto".to_string(),
215 metrics_addr: "0.0.0.0:9090".to_string(),
216 verbose: false,
217 quiet: false,
218 };
219 assert_eq!(args.effective_log_level(), "warn");
220 }
221}