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 #[configurable(metadata(
42 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."
43 ))]
44 pub log_namespace: Option<bool>,
45}
46
47impl Options {
48 /// Gets the value of the globally configured log namespace, or the default if it wasn't set.
49 pub fn log_namespace(self) -> LogNamespace {
50 self.log_namespace
51 .map_or(LogNamespace::Legacy, |use_vector_namespace| {
52 use_vector_namespace.into()
53 })
54 }
55
56 /// Merges two schema options together.
57 pub fn append(&mut self, with: Self, errors: &mut Vec<String>) {
58 if self.log_namespace.is_some()
59 && with.log_namespace.is_some()
60 && self.log_namespace != with.log_namespace
61 {
62 errors.push(
63 format!("conflicting values for 'log_namespace' found. Both {:?} and {:?} used in the same component",
64 self.log_namespace(), with.log_namespace())
65 );
66 }
67 if let Some(log_namespace) = with.log_namespace {
68 self.log_namespace = Some(log_namespace);
69 }
70
71 // If either config enables these flags, it is enabled.
72 self.enabled |= with.enabled;
73 self.validation |= with.validation;
74 }
75}
76
77impl Default for Options {
78 fn default() -> Self {
79 Self {
80 enabled: default_enabled(),
81 validation: default_validation(),
82 log_namespace: None,
83 }
84 }
85}
86
87const fn default_enabled() -> bool {
88 false
89}
90
91const fn default_validation() -> bool {
92 false
93}
94
95#[cfg(test)]
96mod test {
97 use super::*;
98
99 #[test]
100 fn test_append() {
101 for (test, mut a, b, expected) in [
102 (
103 "enable log namespacing",
104 Options {
105 enabled: false,
106 validation: false,
107 log_namespace: None,
108 },
109 Options {
110 enabled: false,
111 validation: false,
112 log_namespace: Some(true),
113 },
114 Some(Options {
115 enabled: false,
116 validation: false,
117 log_namespace: Some(true),
118 }),
119 ),
120 (
121 "log namespace conflict",
122 Options {
123 enabled: false,
124 validation: false,
125 log_namespace: Some(false),
126 },
127 Options {
128 enabled: false,
129 validation: false,
130 log_namespace: Some(true),
131 },
132 None,
133 ),
134 (
135 "enable schemas",
136 Options {
137 enabled: false,
138 validation: false,
139 log_namespace: None,
140 },
141 Options {
142 enabled: true,
143 validation: false,
144 log_namespace: None,
145 },
146 Some(Options {
147 enabled: true,
148 validation: false,
149 log_namespace: None,
150 }),
151 ),
152 (
153 "enable sink requirements",
154 Options {
155 enabled: false,
156 validation: false,
157 log_namespace: None,
158 },
159 Options {
160 enabled: false,
161 validation: true,
162 log_namespace: None,
163 },
164 Some(Options {
165 enabled: false,
166 validation: true,
167 log_namespace: None,
168 }),
169 ),
170 ] {
171 let mut errors = vec![];
172 a.append(b, &mut errors);
173 if errors.is_empty() {
174 assert_eq!(Some(a), expected, "result mismatch: {test}");
175 } else {
176 assert_eq!(
177 errors.is_empty(),
178 expected.is_some(),
179 "error mismatch: {test}"
180 );
181 }
182 }
183 }
184}