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}