diff --git a/changelog.d/20768-default_gelf_stream_framing.breaking.md b/changelog.d/20768-default_gelf_stream_framing.breaking.md new file mode 100644 index 0000000000000..2e70d6fa03057 --- /dev/null +++ b/changelog.d/20768-default_gelf_stream_framing.breaking.md @@ -0,0 +1,37 @@ +Now the GELF codec with stream-based sources uses null byte (`\0`) by default as messages delimiter instead of newline (`\n`) character. This better matches GELF server behavior. + +### Configuration changes + +In order to maintain the previous behavior, you must set the `framing.method` option to the `character_delimited` method and the `framing.character_delimited.delimiter` option to `\n` when using GELF codec with stream-based sources. + +### Example configuration change for socket source + +#### Previous + +```yaml +sources: + my_source_id: + type: "socket" + address: "0.0.0.0:9000" + mode: "tcp" + decoding: + codec: "gelf" +``` + +#### Current + +```yaml +sources: + my_source_id: + type: "socket" + address: "0.0.0.0:9000" + mode: "tcp" + decoding: + codec: "gelf" + framing: + method: "character_delimited" + character_delimited: + delimiter: "\n" +``` + +authors: jorgehermo9 diff --git a/lib/codecs/src/decoding/framing/character_delimited.rs b/lib/codecs/src/decoding/framing/character_delimited.rs index cebcc95b77524..1a6da25ff5883 100644 --- a/lib/codecs/src/decoding/framing/character_delimited.rs +++ b/lib/codecs/src/decoding/framing/character_delimited.rs @@ -15,6 +15,12 @@ pub struct CharacterDelimitedDecoderConfig { } impl CharacterDelimitedDecoderConfig { + /// Creates a `CharacterDelimitedDecoderConfig` with the specified delimiter and default max length. + pub const fn new(delimiter: u8) -> Self { + Self { + character_delimited: CharacterDelimitedDecoderOptions::new(delimiter, None), + } + } /// Build the `CharacterDelimitedDecoder` from this configuration. pub const fn build(&self) -> CharacterDelimitedDecoder { if let Some(max_length) = self.character_delimited.max_length { @@ -53,7 +59,7 @@ pub struct CharacterDelimitedDecoderOptions { impl CharacterDelimitedDecoderOptions { /// Create a `CharacterDelimitedDecoderOptions` with a delimiter and optional max_length. - pub fn new(delimiter: u8, max_length: Option) -> Self { + pub const fn new(delimiter: u8, max_length: Option) -> Self { Self { delimiter, max_length, diff --git a/lib/codecs/src/decoding/mod.rs b/lib/codecs/src/decoding/mod.rs index 2db0dfcfcb327..bfaeeb2ff126f 100644 --- a/lib/codecs/src/decoding/mod.rs +++ b/lib/codecs/src/decoding/mod.rs @@ -334,7 +334,6 @@ impl DeserializerConfig { DeserializerConfig::Native => FramingConfig::LengthDelimited(Default::default()), DeserializerConfig::Bytes | DeserializerConfig::Json(_) - | DeserializerConfig::Gelf(_) | DeserializerConfig::NativeJson(_) => { FramingConfig::NewlineDelimited(Default::default()) } @@ -342,6 +341,9 @@ impl DeserializerConfig { #[cfg(feature = "syslog")] DeserializerConfig::Syslog(_) => FramingConfig::NewlineDelimited(Default::default()), DeserializerConfig::Vrl(_) => FramingConfig::Bytes, + DeserializerConfig::Gelf(_) => { + FramingConfig::CharacterDelimited(CharacterDelimitedDecoderConfig::new(0)) + } } } @@ -467,3 +469,23 @@ impl format::Deserializer for Deserializer { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn gelf_stream_default_framing_is_null_delimited() { + let deserializer_config = DeserializerConfig::from(GelfDeserializerConfig::default()); + let framing_config = deserializer_config.default_stream_framing(); + matches!( + framing_config, + FramingConfig::CharacterDelimited(CharacterDelimitedDecoderConfig { + character_delimited: CharacterDelimitedDecoderOptions { + delimiter: 0, + max_length: None, + } + }) + ); + } +} diff --git a/lib/codecs/src/encoding/mod.rs b/lib/codecs/src/encoding/mod.rs index 0d766f73e4d17..8b15e76baed64 100644 --- a/lib/codecs/src/encoding/mod.rs +++ b/lib/codecs/src/encoding/mod.rs @@ -362,12 +362,14 @@ impl SerializerConfig { FramingConfig::LengthDelimited(LengthDelimitedEncoderConfig::default()) } SerializerConfig::Csv(_) - | SerializerConfig::Gelf | SerializerConfig::Json(_) | SerializerConfig::Logfmt | SerializerConfig::NativeJson | SerializerConfig::RawMessage | SerializerConfig::Text(_) => FramingConfig::NewlineDelimited, + SerializerConfig::Gelf => { + FramingConfig::CharacterDelimited(CharacterDelimitedEncoderConfig::new(0)) + } } }