vrl/stdlib/
parse_logfmt.rs1use super::parse_key_value::{ParseKeyValueFn, Whitespace};
2use crate::compiler::prelude::*;
3
4#[derive(Clone, Copy, Debug)]
5pub struct ParseLogFmt;
6
7impl Function for ParseLogFmt {
8 fn identifier(&self) -> &'static str {
9 "parse_logfmt"
10 }
11
12 fn usage(&self) -> &'static str {
13 indoc! {r#"
14 Parses the `value` in [logfmt](https://brandur.org/logfmt).
15
16 * Keys and values can be wrapped using the `"` character.
17 * `"` characters can be escaped by the `\` character.
18 * As per this [logfmt specification](https://pkg.go.dev/github.com/kr/logfmt#section-documentation), the `parse_logfmt` function accepts standalone keys and assigns them a Boolean value of `true`.
19 "#}
20 }
21
22 fn category(&self) -> &'static str {
23 Category::Parse.as_ref()
24 }
25
26 fn internal_failure_reasons(&self) -> &'static [&'static str] {
27 &["`value` is not a properly formatted key-value string"]
28 }
29
30 fn return_kind(&self) -> u16 {
31 kind::OBJECT
32 }
33
34 fn parameters(&self) -> &'static [Parameter] {
35 const PARAMETERS: &[Parameter] = &[Parameter::required(
36 "value",
37 kind::BYTES,
38 "The string to parse.",
39 )];
40 PARAMETERS
41 }
42
43 fn examples(&self) -> &'static [Example] {
44 &[
45 example! {
46 title: "Parse simple logfmt log",
47 source: r#"parse_logfmt!("zork=zook zonk=nork")"#,
48 result: Ok(r#"{"zork": "zook", "zonk": "nork"}"#),
49 },
50 example! {
51 title: "Parse logfmt log",
52 source: indoc! {r#"
53 parse_logfmt!(
54 "@timestamp=\"Sun Jan 10 16:47:39 EST 2021\" level=info msg=\"Stopping all fetchers\" tag#production=stopping_fetchers id=ConsumerFetcherManager-1382721708341 module=kafka.consumer.ConsumerFetcherManager"
55 )
56 "#},
57 result: Ok(indoc! {r#"{
58 "@timestamp": "Sun Jan 10 16:47:39 EST 2021",
59 "level": "info",
60 "msg": "Stopping all fetchers",
61 "tag#production": "stopping_fetchers",
62 "id": "ConsumerFetcherManager-1382721708341",
63 "module": "kafka.consumer.ConsumerFetcherManager"
64 }"#}),
65 },
66 example! {
67 title: "Parse logfmt log with standalone key",
68 source: r#"parse_logfmt!("zork=zook plonk zonk=nork")"#,
69 result: Ok(r#"{"plonk": true, "zork": "zook", "zonk": "nork"}"#),
70 },
71 ]
72 }
73
74 fn compile(
75 &self,
76 _state: &state::TypeState,
77 _ctx: &mut FunctionCompileContext,
78 arguments: ArgumentList,
79 ) -> Compiled {
80 let value = arguments.required("value");
81
82 let key_value_delimiter = Some(expr!("="));
85 let field_delimiter = Some(expr!(" "));
86 let whitespace = Whitespace::Lenient;
87 let standalone_key = Some(expr!(true));
88
89 Ok(ParseKeyValueFn {
90 value,
91 key_value_delimiter,
92 field_delimiter,
93 whitespace,
94 standalone_key,
95 }
96 .as_expr())
97 }
98}