diff --git a/lib/vector-core/src/config/mod.rs b/lib/vector-core/src/config/mod.rs index 8ebc97ee7fb4b..a9f43293221e3 100644 --- a/lib/vector-core/src/config/mod.rs +++ b/lib/vector-core/src/config/mod.rs @@ -30,6 +30,7 @@ pub const MEMORY_BUFFER_DEFAULT_MAX_EVENTS: NonZeroUsize = // This enum should be kept alphabetically sorted as the bitmask value is used when // sorting sources by data type in the GraphQL API. #[bitmask(u8)] +#[bitmask_config(flags_iter)] pub enum DataType { Log, Metric, @@ -38,11 +39,11 @@ pub enum DataType { impl fmt::Display for DataType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut t = Vec::new(); - self.contains(DataType::Log).then(|| t.push("Log")); - self.contains(DataType::Metric).then(|| t.push("Metric")); - self.contains(DataType::Trace).then(|| t.push("Trace")); - f.write_str(&t.join(",")) + f.debug_list() + .entries( + Self::flags().filter_map(|&(name, value)| self.contains(value).then_some(name)), + ) + .finish() } } @@ -191,6 +192,24 @@ impl SourceOutput { } } +fn fmt_helper( + f: &mut fmt::Formatter<'_>, + maybe_port: Option<&String>, + data_type: DataType, +) -> fmt::Result { + match maybe_port { + Some(port) => write!(f, "port: \"{port}\",",), + None => write!(f, "port: None,"), + }?; + write!(f, " types: {data_type}") +} + +impl fmt::Display for SourceOutput { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_helper(f, self.port.as_ref(), self.ty) + } +} + #[derive(Debug, Clone, PartialEq)] pub struct TransformOutput { pub port: Option, @@ -203,6 +222,12 @@ pub struct TransformOutput { pub log_schema_definitions: HashMap, } +impl fmt::Display for TransformOutput { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_helper(f, self.port.as_ref(), self.ty) + } +} + impl TransformOutput { /// Create a `TransformOutput` of the given data type that contains multiple [`schema::Definition`]s. /// Designed for use in transforms. diff --git a/src/config/graph.rs b/src/config/graph.rs index 7c32871a9b4a8..70c59399ec98d 100644 --- a/src/config/graph.rs +++ b/src/config/graph.rs @@ -1,10 +1,10 @@ -use indexmap::{set::IndexSet, IndexMap}; -use std::collections::{HashMap, HashSet, VecDeque}; - use super::{ schema, ComponentKey, DataType, OutputId, SinkOuter, SourceOuter, SourceOutput, TransformOuter, TransformOutput, }; +use indexmap::{set::IndexSet, IndexMap}; +use std::collections::{HashMap, HashSet, VecDeque}; +use std::fmt; #[derive(Debug, Clone)] pub enum Node { @@ -20,6 +20,33 @@ pub enum Node { }, } +impl fmt::Display for Node { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Node::Source { outputs } => { + write!(f, "component_kind: source\n outputs:")?; + for output in outputs { + write!(f, "\n {}", output)?; + } + Ok(()) + } + Node::Transform { in_ty, outputs } => { + write!( + f, + "component_kind: source\n input_types: {in_ty}\n outputs:" + )?; + for output in outputs { + write!(f, "\n {}", output)?; + } + Ok(()) + } + Node::Sink { ty } => { + write!(f, "component_kind: sink\n types: {ty}") + } + } + } +} + #[derive(Debug, Clone)] struct Edge { from: OutputId, @@ -139,9 +166,16 @@ impl Graph { Some(Node::Sink { .. }) => "sink", _ => panic!("only transforms and sinks have inputs"), }; + info!( + "Available components:\n{}", + self.nodes + .iter() + .map(|(key, node)| format!("\"{}\":\n {}", key, node)) + .collect::>() + .join("\n") + ); Err(format!( - "Input \"{}\" for {} \"{}\" doesn't match any components.", - from, output_type, to + "Input \"{from}\" for {output_type} \"{to}\" doesn't match any components.", )) } } @@ -510,7 +544,7 @@ mod test { assert_eq!( Err(vec![ - "Data type mismatch between in (Log) and out (Metric)".into() + "Data type mismatch between in ([\"Log\"]) and out ([\"Metric\"])".into() ]), graph.typecheck() );