use super::env_parsing::{parse_from_env, ValidationBounds};
const DEFAULT_MAX_SUMMARY_SIZE_BYTES: usize = 8 * 1024;
const MIN_MAX_SUMMARY_SIZE_BYTES: usize = 4 * 1024;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[non_exhaustive]
pub enum DiagnosticsVerbosity {
#[default]
Default,
Summary,
Detailed,
}
impl DiagnosticsVerbosity {
pub fn as_str(&self) -> &'static str {
match self {
DiagnosticsVerbosity::Default => "default",
DiagnosticsVerbosity::Summary => "summary",
DiagnosticsVerbosity::Detailed => "detailed",
}
}
}
impl AsRef<str> for DiagnosticsVerbosity {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl std::fmt::Display for DiagnosticsVerbosity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl std::str::FromStr for DiagnosticsVerbosity {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"default" => Ok(DiagnosticsVerbosity::Default),
"summary" | "minimal" => Ok(DiagnosticsVerbosity::Summary),
"detailed" | "verbose" => Ok(DiagnosticsVerbosity::Detailed),
_ => Err(format!(
"Unknown diagnostics verbosity: '{}'. Expected 'default', 'summary', or 'detailed'",
s
)),
}
}
}
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DiagnosticsOptions {
pub(crate) max_summary_size_bytes: usize,
pub(crate) default_verbosity: DiagnosticsVerbosity,
}
impl Default for DiagnosticsOptions {
fn default() -> Self {
DiagnosticsOptionsBuilder::new()
.build()
.expect("Default DiagnosticsOptions should always be valid")
}
}
impl DiagnosticsOptions {
pub fn builder() -> DiagnosticsOptionsBuilder {
DiagnosticsOptionsBuilder::new()
}
pub fn max_summary_size_bytes(&self) -> usize {
self.max_summary_size_bytes
}
pub fn default_verbosity(&self) -> DiagnosticsVerbosity {
self.default_verbosity
}
}
#[non_exhaustive]
#[derive(Clone, Debug, Default)]
pub struct DiagnosticsOptionsBuilder {
max_summary_size_bytes: Option<usize>,
default_verbosity: Option<DiagnosticsVerbosity>,
}
impl DiagnosticsOptionsBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_max_summary_size_bytes(mut self, size: usize) -> Self {
self.max_summary_size_bytes = Some(size);
self
}
pub fn with_default_verbosity(mut self, verbosity: DiagnosticsVerbosity) -> Self {
self.default_verbosity = Some(verbosity);
self
}
pub fn build(self) -> azure_core::Result<DiagnosticsOptions> {
let max_summary_size_bytes = parse_from_env(
self.max_summary_size_bytes,
"AZURE_COSMOS_DIAGNOSTICS_MAX_SUMMARY_SIZE_BYTES",
DEFAULT_MAX_SUMMARY_SIZE_BYTES,
ValidationBounds::min(MIN_MAX_SUMMARY_SIZE_BYTES),
)?;
let default_verbosity = match self.default_verbosity {
Some(v) => v,
None => match std::env::var("AZURE_COSMOS_DIAGNOSTICS_DEFAULT_VERBOSITY") {
Ok(v) => v.parse().map_err(|e: String| {
azure_core::Error::with_message(
azure_core::error::ErrorKind::DataConversion,
format!(
"Failed to parse AZURE_COSMOS_DIAGNOSTICS_DEFAULT_VERBOSITY: {}",
e
),
)
})?,
Err(_) => DiagnosticsVerbosity::Detailed,
},
};
Ok(DiagnosticsOptions {
max_summary_size_bytes,
default_verbosity,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults() {
let options = DiagnosticsOptions::default();
assert_eq!(options.max_summary_size_bytes, 8 * 1024);
assert_eq!(options.default_verbosity, DiagnosticsVerbosity::Detailed);
}
#[test]
fn custom_values() {
let options = DiagnosticsOptionsBuilder::new()
.with_max_summary_size_bytes(16 * 1024)
.with_default_verbosity(DiagnosticsVerbosity::Summary)
.build()
.unwrap();
assert_eq!(options.max_summary_size_bytes, 16 * 1024);
assert_eq!(options.default_verbosity, DiagnosticsVerbosity::Summary);
}
#[test]
fn max_summary_size_too_small() {
let result = DiagnosticsOptionsBuilder::new()
.with_max_summary_size_bytes(2 * 1024) .build();
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("must be at least 4096"));
}
#[test]
fn verbosity_from_str() {
assert_eq!(
"default".parse::<DiagnosticsVerbosity>().unwrap(),
DiagnosticsVerbosity::Default
);
assert_eq!(
"summary".parse::<DiagnosticsVerbosity>().unwrap(),
DiagnosticsVerbosity::Summary
);
assert_eq!(
"minimal".parse::<DiagnosticsVerbosity>().unwrap(),
DiagnosticsVerbosity::Summary
);
assert_eq!(
"detailed".parse::<DiagnosticsVerbosity>().unwrap(),
DiagnosticsVerbosity::Detailed
);
assert_eq!(
"verbose".parse::<DiagnosticsVerbosity>().unwrap(),
DiagnosticsVerbosity::Detailed
);
assert_eq!(
"DETAILED".parse::<DiagnosticsVerbosity>().unwrap(),
DiagnosticsVerbosity::Detailed
);
assert!("invalid".parse::<DiagnosticsVerbosity>().is_err());
}
#[test]
fn verbosity_display() {
assert_eq!(DiagnosticsVerbosity::Default.to_string(), "default");
assert_eq!(DiagnosticsVerbosity::Summary.to_string(), "summary");
assert_eq!(DiagnosticsVerbosity::Detailed.to_string(), "detailed");
}
}