Skip to main content

provide_telemetry/
consent.rs

1// SPDX-FileCopyrightText: Copyright (C) 2026 provide.io llc
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-Comment: Part of provide-telemetry.
4//
5
6use std::sync::{Mutex, OnceLock};
7
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
9pub enum ConsentLevel {
10    #[default]
11    Full,
12    Functional,
13    Minimal,
14    None,
15}
16
17static CONSENT_LEVEL: OnceLock<Mutex<ConsentLevel>> = OnceLock::new();
18
19#[cfg_attr(test, mutants::skip)] // Equivalent mutants only rewrite ConsentLevel::Full as Default::default().
20fn default_consent_level_mutex() -> Mutex<ConsentLevel> {
21    Mutex::new(ConsentLevel::Full)
22}
23
24fn consent_level() -> &'static Mutex<ConsentLevel> {
25    CONSENT_LEVEL.get_or_init(default_consent_level_mutex)
26}
27
28pub fn set_consent_level(level: ConsentLevel) {
29    *crate::_lock::lock(consent_level()) = level;
30}
31
32pub fn get_consent_level() -> ConsentLevel {
33    *crate::_lock::lock(consent_level())
34}
35
36fn log_level_order(level: Option<&str>) -> usize {
37    match level.unwrap_or_default().to_ascii_uppercase().as_str() {
38        "TRACE" => 0,
39        "DEBUG" => 1,
40        "INFO" => 2,
41        "WARNING" | "WARN" => 3,
42        "ERROR" => 4,
43        "CRITICAL" => 5,
44        _ => 0,
45    }
46}
47
48pub fn should_allow(signal: &str, log_level: Option<&str>) -> bool {
49    match get_consent_level() {
50        ConsentLevel::Full => true,
51        ConsentLevel::None => false,
52        ConsentLevel::Functional => match signal {
53            "logs" => log_level_order(log_level) >= 3,
54            "context" => false,
55            _ => true,
56        },
57        ConsentLevel::Minimal => match signal {
58            "logs" => log_level_order(log_level) >= 4,
59            _ => false,
60        },
61    }
62}
63
64pub fn reset_consent_for_tests() {
65    set_consent_level(ConsentLevel::Full);
66}
67
68#[cfg(test)]
69#[path = "consent_tests.rs"]
70mod tests;