vrl/stdlib/
encode_logfmt.rs1use crate::compiler::prelude::*;
2use std::sync::LazyLock;
3
4use super::encode_key_value::{DEFAULT_FIELDS_ORDERING, EncodeKeyValueFn};
5
6static PARAMETERS: LazyLock<Vec<Parameter>> = LazyLock::new(|| {
7 vec![
8 Parameter::required(
9 "value",
10 kind::OBJECT,
11 "The value to convert to a logfmt string.",
12 ),
13 Parameter::optional("fields_ordering", kind::ARRAY, "The ordering of fields to preserve. Any fields not in this list are listed unordered, after all ordered fields.")
14 .default(&DEFAULT_FIELDS_ORDERING),
15 ]
16});
17
18#[derive(Clone, Copy, Debug)]
19pub struct EncodeLogfmt;
20
21impl Function for EncodeLogfmt {
22 fn identifier(&self) -> &'static str {
23 "encode_logfmt"
24 }
25
26 fn usage(&self) -> &'static str {
27 "Encodes the `value` to [logfmt](https://brandur.org/logfmt)."
28 }
29
30 fn category(&self) -> &'static str {
31 Category::Codec.as_ref()
32 }
33
34 fn internal_failure_reasons(&self) -> &'static [&'static str] {
35 &["`fields_ordering` contains a non-string element."]
36 }
37
38 fn return_kind(&self) -> u16 {
39 kind::BYTES
40 }
41
42 fn notices(&self) -> &'static [&'static str] {
43 &["If `fields_ordering` is specified then the function is fallible else it is infallible."]
44 }
45
46 fn parameters(&self) -> &'static [Parameter] {
47 PARAMETERS.as_slice()
48 }
49
50 fn compile(
51 &self,
52 _state: &state::TypeState,
53 _ctx: &mut FunctionCompileContext,
54 arguments: ArgumentList,
55 ) -> Compiled {
56 let key_value_delimiter = Some(expr!("="));
59 let field_delimiter = Some(expr!(" "));
60 let flatten_boolean = Some(expr!(true));
61
62 let value = arguments.required("value");
63 let fields = arguments.optional("fields_ordering");
64
65 Ok(EncodeKeyValueFn {
66 value,
67 fields,
68 key_value_delimiter,
69 field_delimiter,
70 flatten_boolean,
71 }
72 .as_expr())
73 }
74
75 fn examples(&self) -> &'static [Example] {
76 &[
77 example! {
78 title: "Encode to logfmt (no ordering)",
79 source: r#"encode_logfmt({"ts": "2021-06-05T17:20:00Z", "msg": "This is a message", "lvl": "info"})"#,
80 result: Ok(r#"lvl=info msg="This is a message" ts=2021-06-05T17:20:00Z"#),
81 },
82 example! {
83 title: "Encode to logfmt (fields ordering)",
84 source: r#"encode_logfmt!({"ts": "2021-06-05T17:20:00Z", "msg": "This is a message", "lvl": "info", "log_id": 12345}, ["ts", "lvl", "msg"])"#,
85 result: Ok(r#"ts=2021-06-05T17:20:00Z lvl=info msg="This is a message" log_id=12345"#),
86 },
87 example! {
88 title: "Encode to logfmt (nested fields)",
89 source: r#"encode_logfmt({"agent": {"name": "foo"}, "log": {"file": {"path": "my.log"}}, "event": "log"})"#,
90 result: Ok(r"agent.name=foo event=log log.file.path=my.log"),
91 },
92 example! {
93 title: "Encode to logfmt (nested fields ordering)",
94 source: r#"encode_logfmt!({"agent": {"name": "foo"}, "log": {"file": {"path": "my.log"}}, "event": "log"}, ["event", "log.file.path", "agent.name"])"#,
95 result: Ok(r"event=log log.file.path=my.log agent.name=foo"),
96 },
97 ]
98 }
99}