Skip to content
This repository has been archived by the owner on Mar 21, 2023. It is now read-only.

add optional prefix/suffix to set_fields functions #75

Merged
merged 1 commit into from Aug 8, 2016
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
Expand Up @@ -24,6 +24,8 @@
import org.graylog.plugins.pipelineprocessor.ast.functions.ParameterDescriptor;
import org.graylog2.plugin.Message;

import java.util.Optional;

import static com.google.common.collect.ImmutableList.of;
import static org.graylog.plugins.pipelineprocessor.ast.functions.ParameterDescriptor.object;
import static org.graylog.plugins.pipelineprocessor.ast.functions.ParameterDescriptor.string;
Expand All @@ -32,26 +34,37 @@
public class SetField extends AbstractFunction<Void> {

public static final String NAME = "set_field";
public static final String FIELD = "field";
public static final String VALUE = "value";

private final ParameterDescriptor<String, String> fieldParam;
private final ParameterDescriptor<Object, Object> valueParam;
private final ParameterDescriptor<String, String> prefixParam;
private final ParameterDescriptor<String, String> suffixParam;
private final ParameterDescriptor<Message, Message> messageParam;

public SetField() {
fieldParam = string(FIELD).build();
valueParam = object(VALUE).build();
fieldParam = string("field").build();
valueParam = object("value").build();
prefixParam = string("prefix").optional().build();
suffixParam = string("suffix").optional().build();
messageParam = type("message", Message.class).optional().build();
}

@Override
public Void evaluate(FunctionArgs args, EvaluationContext context) {
final String field = fieldParam.required(args, context);
String field = fieldParam.required(args, context);
final Object value = valueParam.required(args, context);

if (!Strings.isNullOrEmpty(field)) {
final Message message = messageParam.optional(args, context).orElse(context.currentMessage());
final Optional<String> prefix = prefixParam.optional(args, context);
final Optional<String> suffix = suffixParam.optional(args, context);

if (prefix.isPresent()) {
field = prefix.get() + field;
}
if (suffix.isPresent()) {
field = field + suffix.get();
}
message.addField(field, value);
}
return null;
Expand All @@ -64,6 +77,8 @@ public FunctionDescriptor<Void> descriptor() {
.returnType(Void.class)
.params(of(fieldParam,
valueParam,
prefixParam,
suffixParam,
messageParam))
.build();
}
Expand Down
Expand Up @@ -24,19 +24,25 @@
import org.graylog2.plugin.Message;

import java.util.Map;
import java.util.Optional;

import static com.google.common.collect.ImmutableList.of;
import static org.graylog.plugins.pipelineprocessor.ast.functions.ParameterDescriptor.string;
import static org.graylog.plugins.pipelineprocessor.ast.functions.ParameterDescriptor.type;

public class SetFields extends AbstractFunction<Void> {

public static final String NAME = "set_fields";
public static final String FIELDS = "fields";

private final ParameterDescriptor<Map, Map> fieldsParam;
private final ParameterDescriptor<String, String> prefixParam;
private final ParameterDescriptor<String, String> suffixParam;
private final ParameterDescriptor<Message, Message> messageParam;

public SetFields() {
fieldsParam = ParameterDescriptor.type(FIELDS, Map.class).build();
fieldsParam = type("fields", Map.class).build();
prefixParam = string("prefix").optional().build();
suffixParam = string("suffix").optional().build();
messageParam = type("message", Message.class).optional().build();
}

Expand All @@ -45,7 +51,20 @@ public Void evaluate(FunctionArgs args, EvaluationContext context) {
//noinspection unchecked
final Map<String, Object> fields = fieldsParam.required(args, context);
final Message message = messageParam.optional(args, context).orElse(context.currentMessage());
message.addFields(fields);
final Optional<String> prefix = prefixParam.optional(args, context);
final Optional<String> suffix = suffixParam.optional(args, context);

if (fields != null) {
fields.forEach((field, value) -> {
if (prefix.isPresent()) {
field = prefix.get() + field;
}
if (suffix.isPresent()) {
field = field + suffix.get();
}
message.addField(field, value);
});
}
return null;
}

Expand All @@ -54,7 +73,7 @@ public FunctionDescriptor<Void> descriptor() {
return FunctionDescriptor.<Void>builder()
.name(NAME)
.returnType(Void.class)
.params(of(fieldsParam, messageParam))
.params(of(fieldsParam, prefixParam, suffixParam, messageParam))
.build();
}

Expand Down
Expand Up @@ -503,4 +503,25 @@ public void conversions() {
assertThat(message.getField("ip_4")).isEqualTo(new IpAddress(InetAddresses.forString("::1")));

}

@Test
public void fieldPrefixSuffix() {
final Rule rule = parser.parseRule(ruleForTest(), false);

final Message message = evaluateRule(rule);

assertThat(message).isNotNull();

assertThat(message.getField("field")).isEqualTo("1");
assertThat(message.getField("prae_field_sueff")).isEqualTo("2");
assertThat(message.getField("field_sueff")).isEqualTo("3");
assertThat(message.getField("prae_field")).isEqualTo("4");
assertThat(message.getField("pre_field1_suff")).isEqualTo("5");
assertThat(message.getField("pre_field2_suff")).isEqualTo("6");
assertThat(message.getField("pre_field1")).isEqualTo("7");
assertThat(message.getField("pre_field2")).isEqualTo("8");
assertThat(message.getField("field1_suff")).isEqualTo("9");
assertThat(message.getField("field2_suff")).isEqualTo("10");

}
}
@@ -0,0 +1,40 @@
rule "prefixsuffix"
when true
then
// plain set field
set_field("field", "1");
// both prefix and suffix, doesn't touch the above
set_field("field", "2", "prae_", "_sueff");

// combinations of optional prefix, suffix
set_field(field: "field", value: "3", suffix: "_sueff");
set_field(field: "field", value: "4", prefix: "prae_");

// set multiple fields with the same prefix
set_fields(
fields: {
field1: "5",
field2: "6"
},
prefix: "pre_",
suffix: "_suff"
);

// set multiple fields with the same prefix, suffix optional
set_fields(
fields: {
field1: "7",
field2: "8"
},
prefix: "pre_"
);
// set multiple fields with the same suffix, prefix optional
set_fields(
fields: {
field1: "9",
field2: "10"
},
suffix: "_suff"
);
end

Expand Up @@ -3,10 +3,10 @@ when true
then
let x = create_message("new", "synthetic", now());

set_field("removed_again", "foo", x);
set_field("only_in", "new message", x);
set_fields({ multi: "new message" }, x);
set_field("has_source", has_field("source", x), x);
set_field(field: "removed_again", value: "foo", message: x);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the named values required now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are only if we want to set the optional message parameter. Leaving that out you can also omit the parameter names
Prefix and Suffix are "in between" the positional params, the parser does not yet try to match the parameter types.

set_field(field: "only_in", value: "new message", message: x);
set_fields(fields: { multi: "new message" }, message: x);
set_field(field: "has_source", value: has_field("source", x), message: x);
route_to_stream(name: "some stream", message: x);
remove_field("removed_again", x);
end