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