vector/config/
schema.rs

1use vector_lib::{config::LogNamespace, configurable::configurable_component};
2
3pub(crate) use crate::schema::Definition;
4
5/// Schema options.
6///
7/// **Note:** The `enabled` and `validation` options are experimental and should only be enabled if you
8/// understand the limitations. While the infrastructure exists for schema tracking and validation, the
9/// full vision of automatic semantic field mapping and comprehensive schema enforcement was never fully
10/// realized.
11///
12/// If you encounter issues with these features, please [report them here](https://github.com/vectordotdev/vector/issues/new?template=bug.yml).
13#[configurable_component]
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15#[serde(default, deny_unknown_fields)]
16pub struct Options {
17    /// When enabled, Vector tracks the schema (field types and structure) of events as they flow
18    /// from sources through transforms to sinks. This allows Vector to understand what data each
19    /// component receives and produces.
20    #[serde(default = "default_enabled")]
21    pub enabled: bool,
22
23    /// When enabled, Vector validates that events flowing into each sink match the schema
24    /// requirements of that sink. If a sink requires certain fields or types that are missing
25    /// from the incoming events, Vector will report an error during configuration validation.
26    ///
27    /// This helps catch pipeline configuration errors early, before runtime.
28    #[serde(default = "default_validation")]
29    pub validation: bool,
30
31    /// Controls how metadata is stored in log events.
32    ///
33    /// When set to `false` (legacy mode), metadata fields like `host`, `timestamp`, and `source_type`
34    /// are stored as top-level fields alongside your log data.
35    ///
36    /// When set to `true` (Vector namespace mode), metadata is stored in a separate metadata namespace,
37    /// keeping it distinct from your actual log data.
38    ///
39    /// See the [Log Namespacing guide](/guides/level-up/log_namespace/) for detailed information
40    /// about when to use Vector namespace mode and how to migrate from legacy mode.
41    pub log_namespace: Option<bool>,
42}
43
44impl Options {
45    /// Gets the value of the globally configured log namespace, or the default if it wasn't set.
46    pub fn log_namespace(self) -> LogNamespace {
47        self.log_namespace
48            .map_or(LogNamespace::Legacy, |use_vector_namespace| {
49                use_vector_namespace.into()
50            })
51    }
52
53    /// Merges two schema options together.
54    pub fn append(&mut self, with: Self, errors: &mut Vec<String>) {
55        if self.log_namespace.is_some()
56            && with.log_namespace.is_some()
57            && self.log_namespace != with.log_namespace
58        {
59            errors.push(
60                format!("conflicting values for 'log_namespace' found. Both {:?} and {:?} used in the same component",
61                        self.log_namespace(), with.log_namespace())
62            );
63        }
64        if let Some(log_namespace) = with.log_namespace {
65            self.log_namespace = Some(log_namespace);
66        }
67
68        // If either config enables these flags, it is enabled.
69        self.enabled |= with.enabled;
70        self.validation |= with.validation;
71    }
72}
73
74impl Default for Options {
75    fn default() -> Self {
76        Self {
77            enabled: default_enabled(),
78            validation: default_validation(),
79            log_namespace: None,
80        }
81    }
82}
83
84const fn default_enabled() -> bool {
85    false
86}
87
88const fn default_validation() -> bool {
89    false
90}
91
92#[cfg(test)]
93mod test {
94    use super::*;
95
96    #[test]
97    fn test_append() {
98        for (test, mut a, b, expected) in [
99            (
100                "enable log namespacing",
101                Options {
102                    enabled: false,
103                    validation: false,
104                    log_namespace: None,
105                },
106                Options {
107                    enabled: false,
108                    validation: false,
109                    log_namespace: Some(true),
110                },
111                Some(Options {
112                    enabled: false,
113                    validation: false,
114                    log_namespace: Some(true),
115                }),
116            ),
117            (
118                "log namespace conflict",
119                Options {
120                    enabled: false,
121                    validation: false,
122                    log_namespace: Some(false),
123                },
124                Options {
125                    enabled: false,
126                    validation: false,
127                    log_namespace: Some(true),
128                },
129                None,
130            ),
131            (
132                "enable schemas",
133                Options {
134                    enabled: false,
135                    validation: false,
136                    log_namespace: None,
137                },
138                Options {
139                    enabled: true,
140                    validation: false,
141                    log_namespace: None,
142                },
143                Some(Options {
144                    enabled: true,
145                    validation: false,
146                    log_namespace: None,
147                }),
148            ),
149            (
150                "enable sink requirements",
151                Options {
152                    enabled: false,
153                    validation: false,
154                    log_namespace: None,
155                },
156                Options {
157                    enabled: false,
158                    validation: true,
159                    log_namespace: None,
160                },
161                Some(Options {
162                    enabled: false,
163                    validation: true,
164                    log_namespace: None,
165                }),
166            ),
167        ] {
168            let mut errors = vec![];
169            a.append(b, &mut errors);
170            if errors.is_empty() {
171                assert_eq!(Some(a), expected, "result mismatch: {test}");
172            } else {
173                assert_eq!(
174                    errors.is_empty(),
175                    expected.is_some(),
176                    "error mismatch: {test}"
177                );
178            }
179        }
180    }
181}