I have syslog message roughly compatible with the syslog RFC and I’m trying to use pipelines and rules to get better control over parsing these messages. But I’m not a programmer so there are things that are tripping me up.
I have the following to do initial processing of the message:
rule "raw-process-exp"
when
true
then
// Raw processing Tests
let extract = grok(
pattern: "<%{NONNEGINT:syslog_pri}>",
value: to_string($message.message),
only_named_captures: true
);
let syslogpriexanded = expand_syslog_priority(extract.syslog_pri);
set_field("syslog_severity", syslogpriexanded);
set_fields(extract);
set_field("record_type", "EXPERIMENTAL LOG PROCESSING");
end
What gets put in the syslog_severity field is: {"level":3,"facility":17}
I guess that’s what they call a map or a something? I want to actually pull out the “3” and put it in the syslog_severity field. I’ve tried a couple of things but haven’t figured it out yet.
Or maybe there’s a way to use the set_fields function to automatically add a field named “level” and set it to “3” and add a field called “facility” and set it to 17? That would be cool. Haven’t figure that out either.
Is there a super-simple example somewhere on how to use the set_fields function? How do I learn the ins and outs of using these functions?
let syslogpriexanded = expand_syslog_priority(extract.syslog_pri);
Is giving you the map you want of: {"level":3,"facility":17}
so you would set_fields() against that:
set_fields(syslogpriexanded);
which should get the results you wanted.
set_fields() is usually following a grok() and taking the resulting file-to-data mapping and creating a series of fields that grok() matched. You can put the debug() function in any rule and watch the Graylog server logs for the results. Here is an example rule using grok() and debug():
rule "bar-1-start"
when
has_field("bar_event_1") &&
contains(to_string($message.message),"bar session started ")
then
let barLine = grok("%{BAR_1_START}",to_string($message.message), true);
set_fields(barLine);
debug(concat("======= bar_event_1 is: ", to_string($message.bar_event_1) );
debug(concat("======= message is: ", to_string($message.message) );
end
That was one of the first things I tried. I tried it with…
set_fields(extract);
…and it worked great. It seems the grok() function returns a map and the set_fields takes a map. I know this because I ran is_it_map(extract) and it returned TRUE.
But it doesn’t work with syslogpriexpanded(). It doesn’t even compile and just gives the tool-tip message…
Expected type Map for argument fields but found SyslogPriority in call to function set_fields in line 35 pos 4.
Another crazy thing: the output of the expand_syslogpriority() function is not a map. I don’t know what it is. I ran it against:
Everything came up FALSE. What the output of expand_syslogpriority()? Weird. It would be helpful if the documentation indicated the output datatype of expand_syslogpriority(). It doesn’t.
@gsmith Your idea is a good one and we are already doing grok patterns on extractors. But I did notice that we are doing the same grok patterns multiple type across inputs. The pipeline/rule system seems useful for code reusability, so I figured things we be easier to implement there.
We are also finding that we need to do some more advanced post-processing. E.g., change a string to a long integer or reformate a date. We’re trying to bring our syslog processing to the next level!
let syslog_sev_fac = expand_syslog_priority(extract.syslog_pri);
I pull it into variables.
let syslog_sev = to_long(syslog_sev_fac.level);
let syslog_fac = to_long(syslog_sev_fac.facility);
let syslog_severity = syslog_level(syslog_sev);
let syslog_facility = syslog_facility(syslog_fac);