Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement(lua transform)!: respect Lua types when converting back to events #1886

Merged
1 commit merged into from Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 64 additions & 13 deletions src/transforms/lua.rs
@@ -1,6 +1,6 @@
use super::Transform;
use crate::{
event::Event,
event::{Event, Value},
topology::config::{DataType, TransformConfig, TransformContext, TransformDescription},
};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -109,11 +109,32 @@ impl rlua::UserData for Event {
fn add_methods<'lua, M: rlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method_mut(
rlua::MetaMethod::NewIndex,
|_ctx, this, (key, value): (String, Option<rlua::String<'lua>>)| {
if let Some(string) = value {
this.as_mut_log().insert(key, string.as_bytes());
} else {
this.as_mut_log().remove(&key.into());
|_ctx, this, (key, value): (String, Option<rlua::Value<'lua>>)| {
match value {
Some(rlua::Value::String(string)) => {
this.as_mut_log().insert(key, string.as_bytes());
}
Some(rlua::Value::Integer(integer)) => {
this.as_mut_log().insert(key, Value::Integer(integer));
}
Some(rlua::Value::Number(number)) => {
this.as_mut_log().insert(key, Value::Float(number));
}
Some(rlua::Value::Boolean(boolean)) => {
this.as_mut_log().insert(key, Value::Boolean(boolean));
}
Some(rlua::Value::Nil) | None => {
this.as_mut_log().remove(&key.into());
}
_ => {
info!(
message =
"Could not set field to Lua value of invalid type, dropping field",
field = key.as_str(),
rate_limit_secs = 30
);
this.as_mut_log().remove(&key.into());
}
}

Ok(())
Expand Down Expand Up @@ -163,7 +184,10 @@ fn format_error(error: &rlua::Error) -> String {
#[cfg(test)]
mod tests {
use super::{format_error, Lua};
use crate::{event::Event, transforms::Transform};
use crate::{
event::{Event, Value},
transforms::Transform,
};

#[test]
fn lua_add_field() {
Expand Down Expand Up @@ -255,7 +279,7 @@ mod tests {
}

#[test]
fn lua_numeric_value() {
fn lua_integer_value() {
let mut transform = Lua::new(
r#"
event["number"] = 3
Expand All @@ -265,22 +289,49 @@ mod tests {
.unwrap();

let event = transform.transform(Event::new_empty_log()).unwrap();
assert_eq!(event.as_log()[&"number".into()], "3".into());
assert_eq!(event.as_log()[&"number".into()], Value::Integer(3));
}

#[test]
fn lua_numeric_value() {
let mut transform = Lua::new(
r#"
event["number"] = 3.14159
"#,
vec![],
)
.unwrap();

let event = transform.transform(Event::new_empty_log()).unwrap();
assert_eq!(event.as_log()[&"number".into()], Value::Float(3.14159));
}

#[test]
fn lua_boolean_value() {
let mut transform = Lua::new(
r#"
event["bool"] = true
"#,
vec![],
)
.unwrap();

let event = transform.transform(Event::new_empty_log()).unwrap();
assert_eq!(event.as_log()[&"bool".into()], Value::Boolean(true));
}

#[test]
fn lua_non_coercible_value() {
let transform = Lua::new(
let mut transform = Lua::new(
r#"
event["junk"] = {"asdf"}
"#,
vec![],
)
.unwrap();

let err = transform.process(Event::new_empty_log()).unwrap_err();
let err = format_error(&err);
assert!(err.contains("error converting Lua table to String"), err);
let event = transform.transform(Event::new_empty_log()).unwrap();
assert_eq!(event.as_log().get(&"junk".into()), None);
}

#[test]
Expand Down
8 changes: 8 additions & 0 deletions website/docs/reference/transforms/lua.md
Expand Up @@ -237,6 +237,14 @@ paths that will searched when using the [Lua `require`
function][urls.lua_require].



### Types

Event fields can be set to scalar values (booleans, numbers, or strings),
and the resulting event will keep the correct types. If an event field is
set to an invalid value, a message will be logged and the field will be dropped.


[docs.configuration#environment-variables]: /docs/setup/configuration/#environment-variables
[docs.data-model.log#schema]: /docs/about/data-model/log/#schema
[docs.data-model.log]: /docs/about/data-model/log/
Expand Down
6 changes: 6 additions & 0 deletions website/docs/reference/transforms/lua.md.erb
Expand Up @@ -98,6 +98,12 @@ variable representing the event:
Note, a Lua `table` is an associative array. You can read more about
[Lua types][urls.lua_types] in the [Lua docs][urls.lua_docs].

### Types

Event fields can be set to scalar values (booleans, numbers, or strings),
and the resulting event will keep the correct types. If an event field is
set to an invalid value, a message will be logged and the field will be dropped.

### Nested Fields

As described in the [Data Model document][docs.data_model], Vector flatten
Expand Down