How to replace the value of a variable field in logstash pipeline - logstash

For some unavoidable reason, a field "program" in my logstash pipeline contains a value like "date=2023.14.02". I want to rename the value of this field to "kernel". The problem is, the name is variable in nature as a date will be passed to the field every passing day.
I have tried something like this :
if [program]=~/^date.*/ {
filter {
mutate {
rename => {/^date.*/ => "kernel"}
}
}
I tried rename => {"date.*" => "kernel"}, rename => {^date.* => "kernel"} etc.. But it does not work. Is there a correct syntax for the same?

If you want to replace the value of the [program] field with kernel then use mutate { gsub => [ "program", "^date.*", "kernel" ] }.

Related

convert string to array based on pattern in logstash

My original data.
{
message: {
data: "["1,2","3,4","5,6"]"
}
}
Now I want to convert value of data field to an array.
So it should become:
{
message: {
data: ["1,2", "3,4", "5,6"]
}
}
By using
mutate {
gsub => ["data", "[\[\]]", ""]
}
I got rid of square brackets.
After this, I tried splitting based on commas. But that won't work. Since my data has commas as well.
I tried writing a dissect block but that is not useful.
So how should I go ahead with this?
Have you tried the json filter? If the data field always contains valid json data, you use the json filter like this:
json {
source => "data"
target => "data"
}
Using target => "data" will overwrite the data field.

LogStash dissect with key=value, comma

I have a pattern of logs that contain performance&statistical data. I have configured LogStash to dissect this data as csv format in order to save the values to ES.
<1>,www1,3,BISTATS,SCAN,330,712.6,2035,17.3,221.4,656.3
I am using the following LogSTash filter and getting the desired results..
grok {
match => { "Message" => "\A<%{POSINT:priority}>,%{DATA:pan_host},%{DATA:pan_serial_number},%{DATA:pan_type},%{GREEDYDATA:message}\z" }
overwrite => [ "Message" ]
}
csv {
separator => ","
columns => ["pan_scan","pf01","pf02","pf03","kk04","uy05","xd06"]
}
This is currently working well for me as long as the order of the columns doesn't get messed up.
However I want to make this logfile more meaningful and have each column-name in the original log. example-- <1>,www1,30000,BISTATS,SCAN,pf01=330,pf02=712.6,pf03=2035,kk04=17.3,uy05=221.4,xd06=656.3
This way I can keep inserting or appending key/values in the middle of the process without corrupting the data. (Using LogStash5.3)
By using #baudsp recommendations, I was able to formulate the following. I deleted the csv{} block completely and replace it with the kv{} block. The kv{} automatically created all the key values leaving me to only mutate{} the fields into floats and integers.
json {
source => "message"
remove_field => [ "message", "headers" ]
}
date {
match => [ "timestamp", "YYYY-MM-dd'T'HH:mm:ss.SSS'Z'" ]
target => "timestamp"
}
grok {
match => { "Message" => "\A<%{POSINT:priority}>,%{DATA:pan_host},%{DATA:pan_serial_number},%{DATA:pan_type},%{GREEDYDATA:message}\z" }
overwrite => [ "Message" ]
}
kv {
allow_duplicate_values => false
field_split_pattern => ","
}
Using the above block, I was able to insert the K=V, pairs anywhere in the message. Thanks again for all the help. I have added a sample code block for anyone trying to accomplish this task.
Note: I am using NLog for logging, which produces JSON outputs. From the C# code, the format looks like this.
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.ExtendedInfo("<1>,www1,30000,BISTATS,SCAN,pf01=330,pf02=712.6,pf03=2035,kk04=17.3,uy05=221.4,xd06=656.3");

Grok returns array instead of single string

I'm new to grok and I have run into this issue that I just don't know how to solve.
Below is my grok match:
grok {
match => { "source" => "/var/log/nginx/sites/\b\w+\b/\b\w+\b/\b\w+\b/%{DATA:uuid}/" }
}
mutate {
add_field => {
"read_timestamp" => "%{#timestamp}"
"token" => "%{[fields][token]}"
"logzio_codec" => "%{[fields][logzio_codec]}"
"uuid" => "%{uuid}"
"type" => "%{[fields][type]}"
"category" => "%{[fields][category]}"
}
}
for some reason, the uuid is matched and resulted in array of 2 uuid (duplicated values). Instead of uuid_string I get [uuid_string, uuid_string]
I tried on https://grokdebug.herokuapp.com/ and got what I expected so I wonder what is wrong?
So once again I misunderstand how grok works. It seems like once the match is done, all the fields are already added to the output. The additional add_field uuid in the mutate thus causes the field to be added twice and logstash then thinks it's an array.

Logstash to convert epoch timestamp

I'm trying to parse some epoch timestamps to be something more readable.
I looked around for how to parse them into a normal time, and from what I understand all I should have to do is something like this:
mutate
{
remove_field => [ "..."]
}
grok
{
match => { 'message' => '%{NUMBER:time}%{SPACE}%{NUMBER:time2}...' }
}
date
{
match => [ "time","UNIX" ]
}
An example of a message is: 1410811884.84 1406931111.00 ....
The first two values should be UNIX time values.
My grok works, because all of the fields show in Kibana with the expected values, and all the values fields I've removed aren't there so the mutate works too. The date section seems to do nothing.
From what I understand the match => [ "time","UNIX" ] should do what I want (Change the value of time to be a proper date format, and have it show on kibana as a field.) . So apparently I'm not understanding it.
The date{} filter replaces the value of #timestamp with the data provided, so you should see #timestamp with the same value as the [time] field. This is typically useful since there's some delay in the propagation, processing, and storing of the logs, so using the event's own time is preferred.
Since you have more than one date field, you'll want to use the 'target' parameter of the date filter to specify the destination of the parsed date, e.g.:
date {
match => [ "time","UNIX" ]
target => "myTime"
}
This would convert the string field named [time] into a date field named [myTime]. Kibana knows how to display date fields, and you can customize that in the kibana settings.
Since you probably don't need both a string a date version of the same data, you can remove the string version as part of the conversion:
date {
match => [ "time","UNIX" ]
target => "myTime"
remove_field => [ "time" ]
}
Consider also trying with UNIX_MS for milliseconds.
date {
timezone => "UTC"
match => ["timestamp", "UNIX_MS"]
target => "#timestamp"
}

How to add a new dynamic value(which is not there in input) to logstash output?

My input has timestamp in the format of Apr20 14:59:41248 Dataxyz.
Now in my output i need the timestamp in the below format:
**Day Month Monthday Hour:Minute:Second Year DataXYZ **. I was able to remove the timestamp from the input. But I am not quite sure how to add the new timestamp.
I matched the message using grok while receiving the input:
match => ["message","%{WORD:word} %{TIME:time} %{GREEDYDATA:content}"]
I tried using mutate add_field.but was not successful in adding the value of the DAY. add_field => [ "timestamp","%{DAY}"].I got the output as the word ´DAY´ and not the value of DAY. Can someone please throw some light on what is being missed.
You need to grok it out into the individual named fields, and then you can reference those fields in add_field.
So your grok would start like this:
%{MONTH:month}%{MONTHDAY:mday}
And then you can put them back together like this:
mutate {
add_field => {
"newField" => "%{mday} %{month}"
}
}
You can check with my answer, I think this very helpful to you.
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:time} \[%{NUMBER:thread}\] %{LOGLEVEL:loglevel} %{JAVACLASS:class} - %{GREEDYDATA:msg}" }
}
if "Exception" in [msg] {
mutate {
add_field => { "msg_error" => "%{msg}" }
}
}
You can use custom grok patterns to extract/rename fields.
You can extract other fields similarly and rearrange/play arounnd with them in mutate filter. Refer to Custom Patterns for more information.

Resources