vector_core/event/lua/
event.rs1use mlua::prelude::*;
2
3use super::{
4 super::{Event, LogEvent, Metric},
5 metric::LuaMetric,
6};
7
8pub struct LuaEvent {
9 pub event: Event,
10 pub metric_multi_value_tags: bool,
11}
12
13impl IntoLua for LuaEvent {
14 #![allow(clippy::wrong_self_convention)] fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
16 let table = lua.create_table()?;
17 match self.event {
18 Event::Log(log) => table.raw_set("log", log.into_lua(lua)?)?,
19 Event::Metric(metric) => table.raw_set(
20 "metric",
21 LuaMetric {
22 metric,
23 multi_value_tags: self.metric_multi_value_tags,
24 }
25 .into_lua(lua)?,
26 )?,
27 Event::Trace(_) => {
28 return Err(LuaError::ToLuaConversionError {
29 from: String::from("Event"),
30 to: "table",
31 message: Some("Trace are not supported".to_string()),
32 });
33 }
34 }
35 Ok(LuaValue::Table(table))
36 }
37}
38
39impl FromLua for Event {
40 fn from_lua(value: LuaValue, lua: &Lua) -> LuaResult<Self> {
41 let LuaValue::Table(table) = &value else {
42 return Err(LuaError::FromLuaConversionError {
43 from: value.type_name(),
44 to: String::from("Event"),
45 message: Some("Event should be a Lua table".to_string()),
46 });
47 };
48 match (table.raw_get("log")?, table.raw_get("metric")?) {
49 (LuaValue::Table(log), LuaValue::Nil) => {
50 Ok(Event::Log(LogEvent::from_lua(LuaValue::Table(log), lua)?))
51 }
52 (LuaValue::Nil, LuaValue::Table(metric)) => Ok(Event::Metric(Metric::from_lua(
53 LuaValue::Table(metric),
54 lua,
55 )?)),
56 _ => Err(LuaError::FromLuaConversionError {
57 from: value.type_name(),
58 to: String::from("Event"),
59 message: Some(
60 "Event should contain either \"log\" or \"metric\" key at the top level"
61 .to_string(),
62 ),
63 }),
64 }
65 }
66}
67
68#[cfg(test)]
69mod test {
70 use super::*;
71 use crate::event::{
72 Metric, Value,
73 metric::{MetricKind, MetricValue},
74 };
75
76 fn assert_event(event: Event, assertions: Vec<&'static str>) {
77 let lua = Lua::new();
78 lua.globals()
79 .set(
80 "event",
81 LuaEvent {
82 event,
83 metric_multi_value_tags: false,
84 },
85 )
86 .unwrap();
87 for assertion in assertions {
88 assert!(
89 lua.load(assertion).eval::<bool>().expect(assertion),
90 "{}",
91 assertion
92 );
93 }
94 }
95
96 #[test]
97 fn into_lua_log() {
98 use vrl::event_path;
99 let mut event = LogEvent::default();
100 event.insert(event_path!("field"), "value");
101
102 let assertions = vec![
103 "type(event) == 'table'",
104 "event.metric == nil",
105 "type(event.log) == 'table'",
106 "event.log.field == 'value'",
107 ];
108
109 assert_event(event.into(), assertions);
110 }
111
112 #[test]
113 fn into_lua_metric() {
114 let event = Event::Metric(Metric::new(
115 "example counter",
116 MetricKind::Absolute,
117 MetricValue::Counter {
118 value: 0.577_215_66,
119 },
120 ));
121
122 let assertions = vec![
123 "type(event) == 'table'",
124 "event.log == nil",
125 "type(event.metric) == 'table'",
126 "event.metric.name == 'example counter'",
127 "event.metric.counter.value == 0.57721566",
128 ];
129
130 assert_event(event, assertions);
131 }
132
133 #[test]
134 fn from_lua_log() {
135 let lua_event = r#"
136 {
137 log = {
138 field = "example",
139 nested = {
140 field = "another example"
141 }
142 }
143 }"#;
144
145 let event = Lua::new().load(lua_event).eval::<Event>().unwrap();
146 let log = event.as_log();
147 assert_eq!(log["field"], Value::Bytes("example".into()));
148 assert_eq!(log["nested.field"], Value::Bytes("another example".into()));
149 }
150
151 #[test]
152 fn from_lua_metric() {
153 let lua_event = r#"
154 {
155 metric = {
156 name = "example counter",
157 counter = {
158 value = 0.57721566
159 }
160 }
161 }"#;
162 let expected = Event::Metric(Metric::new(
163 "example counter",
164 MetricKind::Absolute,
165 MetricValue::Counter {
166 value: 0.577_215_66,
167 },
168 ));
169
170 let event = Lua::new().load(lua_event).eval::<Event>().unwrap();
171 vector_common::assert_event_data_eq!(event, expected);
172 }
173
174 #[test]
175 #[allow(clippy::should_panic_without_expect)]
177 #[should_panic]
178 fn from_lua_missing_log_and_metric() {
179 let lua_event = r"{
180 some_field: {}
181 }";
182 Lua::new().load(lua_event).eval::<Event>().unwrap();
183 }
184}