clap_logflag/clap.rs
1use clap::Parser;
2
3use crate::{LogDestinationConfig, LoggingConfig};
4
5#[derive(Parser, Debug)]
6pub struct LogArgs {
7 // TODO Formatting of this is weird in `--help` output
8 /// Log definition consisting of an optional log level, and a log destination.
9 /// You can define this argument multiple times for multiple log destinations.
10 ///
11 /// Logging can be disabled with `--log none`.
12 /// If combined with other log definitions, those will take precedence and logging will not be disabled.
13 ///
14 /// Format: \[level:\]destination
15 ///
16 /// level = "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE"
17 ///
18 /// destination = "stderr" | "syslog" | "file:path" | "none"
19 ///
20 /// Examples:
21 /// * "--log syslog"
22 /// * "--log stderr"
23 /// * "--log file:/path/to/file"
24 /// * "--log INFO:stderr"
25 /// * "--log DEBUG:file:/path/to/file"
26 /// * "--log TRACE:syslog"
27 /// * "--log none"
28 #[arg(long, value_parser=parse_destination_config)]
29 pub log: Vec<Option<LogDestinationConfig>>,
30}
31
32fn parse_destination_config(input: &str) -> Result<Option<LogDestinationConfig>, String> {
33 crate::parser::parse_config_definition(input).map_err(|err| err.to_string())
34}
35
36impl LogArgs {
37 pub fn or_default(&self, default: LoggingConfig) -> LoggingConfig {
38 if self.log.is_empty() {
39 // No `--log` argument given, use the default config
40 default
41 } else {
42 // There are `--log` arguments given, but they may be `--log none`.
43 // Let's filter those out
44 let destinations: Vec<LogDestinationConfig> =
45 self.log.iter().filter_map(|log| log.clone()).collect();
46 if destinations.is_empty() {
47 // All `--log` arguments were `--log none`, disable logging
48 LoggingConfig::LoggingDisabled
49 } else {
50 // There was at least one `--log` argument that wasn't `--log none`, enable logging
51 LoggingConfig::LoggingEnabled { destinations }
52 }
53 }
54 }
55}