Skip to main content

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    /// This feature is in beta and behavior may change.
34    ///
35    /// When set to `false` (legacy mode), metadata fields like `host`, `timestamp`, and `source_type`
36    /// are stored as top-level fields alongside your log data.
37    ///
38    /// When set to `true` (Vector namespace mode), metadata is stored in a separate metadata namespace,
39    /// keeping it distinct from your actual log data.
40    ///
41    /// See the [Log Namespacing guide](/guides/level-up/log_namespace/) for detailed information
42    /// about when to use Vector namespace mode and how to migrate from legacy mode.
43    #[configurable(metadata(
44        status = "beta",
45        docs::warnings = "Enabling log namespacing currently does not work when disk buffers are used. Avoid combining `schema.log_namespace = true` with disk buffers until [#18574](https://github.com/vectordotdev/vector/issues/18574) is resolved."
46    ))]
47    pub log_namespace: Option<bool>,
48}
49
50impl Options {
51    /// Gets the value of the globally configured log namespace, or the default if it wasn't set.
52    pub fn log_namespace(self) -> LogNamespace {
53        self.log_namespace
54            .map_or(LogNamespace::Legacy, |use_vector_namespace| {
55                use_vector_namespace.into()
56            })
57    }
58
59    /// Merges two schema options together.
60    pub fn append(&mut self, with: Self, errors: &mut Vec<String>) {
61        if self.log_namespace.is_some()
62            && with.log_namespace.is_some()
63            && self.log_namespace != with.log_namespace
64        {
65            errors.push(
66                format!("conflicting values for 'log_namespace' found. Both {:?} and {:?} used in the same component",
67                        self.log_namespace(), with.log_namespace())
68            );
69        }
70        if let Some(log_namespace) = with.log_namespace {
71            self.log_namespace = Some(log_namespace);
72        }
73
74        // If either config enables these flags, it is enabled.
75        self.enabled |= with.enabled;
76        self.validation |= with.validation;
77    }
78}
79
80impl Default for Options {
81    fn default() -> Self {
82        Self {
83            enabled: default_enabled(),
84            validation: default_validation(),
85            log_namespace: None,
86        }
87    }
88}
89
90const fn default_enabled() -> bool {
91    false
92}
93
94const fn default_validation() -> bool {
95    false
96}
97
98#[cfg(test)]
99mod test {
100    use super::*;
101
102    #[test]
103    fn test_append() {
104        for (test, mut a, b, expected) in [
105            (
106                "enable log namespacing",
107                Options {
108                    enabled: false,
109                    validation: false,
110                    log_namespace: None,
111                },
112                Options {
113                    enabled: false,
114                    validation: false,
115                    log_namespace: Some(true),
116                },
117                Some(Options {
118                    enabled: false,
119                    validation: false,
120                    log_namespace: Some(true),
121                }),
122            ),
123            (
124                "log namespace conflict",
125                Options {
126                    enabled: false,
127                    validation: false,
128                    log_namespace: Some(false),
129                },
130                Options {
131                    enabled: false,
132                    validation: false,
133                    log_namespace: Some(true),
134                },
135                None,
136            ),
137            (
138                "enable schemas",
139                Options {
140                    enabled: false,
141                    validation: false,
142                    log_namespace: None,
143                },
144                Options {
145                    enabled: true,
146                    validation: false,
147                    log_namespace: None,
148                },
149                Some(Options {
150                    enabled: true,
151                    validation: false,
152                    log_namespace: None,
153                }),
154            ),
155            (
156                "enable sink requirements",
157                Options {
158                    enabled: false,
159                    validation: false,
160                    log_namespace: None,
161                },
162                Options {
163                    enabled: false,
164                    validation: true,
165                    log_namespace: None,
166                },
167                Some(Options {
168                    enabled: false,
169                    validation: true,
170                    log_namespace: None,
171                }),
172            ),
173        ] {
174            let mut errors = vec![];
175            a.append(b, &mut errors);
176            if errors.is_empty() {
177                assert_eq!(Some(a), expected, "result mismatch: {test}");
178            } else {
179                assert_eq!(
180                    errors.is_empty(),
181                    expected.is_some(),
182                    "error mismatch: {test}"
183                );
184            }
185        }
186    }
187}