clap_logflag/
clap.rs

1use clap::Parser;
2
3use crate::{LogDestinationConfig, LoggingConfig};
4
5// We need to remove doc comments here, otherwise clap adds them to the help message
6#[allow(missing_docs)]
7#[derive(Parser, Debug)]
8pub struct LogArgs {
9    /// Log definition consisting of an optional log level filter, and a log destination.
10    /// You can define this argument multiple times for multiple log destinations.
11    ///
12    /// Logging can be disabled with `--log none`.
13    /// If combined with other log definitions, those will take precedence and logging will not be disabled.
14    ///
15    /// The argument can be combined with a level filter to only log messages of a certain level or higher to that destination.
16    ///
17    /// Format: destination | level_filter:destination
18    /// * level_filter = "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE"
19    /// * destination = "stderr" | "syslog" | "file:path" | "none"
20    ///
21    /// Examples:
22    /// * `--log syslog`
23    /// * `--log stderr`
24    /// * `--log file:/path/to/file`
25    /// * `--log INFO:stderr`
26    /// * `--log DEBUG:file:/path/to/file`
27    /// * `--log TRACE:syslog`
28    /// * `--log none`
29    #[arg(long, value_parser=parse_destination_config)]
30    #[clap(verbatim_doc_comment)]
31    pub log: Vec<Option<LogDestinationConfig>>,
32}
33
34fn parse_destination_config(input: &str) -> Result<Option<LogDestinationConfig>, String> {
35    crate::parser::parse_config_definition(input).map_err(|err| err.to_string())
36}
37
38impl LogArgs {
39    /// Build the [LoggingConfig] defined by the command line arguments from [LogArgs].
40    /// If no `--log` argument is given, the default config is returned.
41    pub fn or_default(&self, default: LoggingConfig) -> LoggingConfig {
42        if self.log.is_empty() {
43            // No `--log` argument given, use the default config
44            default
45        } else {
46            // There are `--log` arguments given, but they may be `--log none`.
47            // Let's filter those out. If no non-none are remaining, logging will be disabled.
48            let destinations = self.log.iter().filter_map(|log| log.clone()).collect();
49            LoggingConfig::new(destinations)
50        }
51    }
52}