Can we extract numeric values from string through script in kibana? - elasticsearch

I need to extract numeric values from string and store in new field..Can we do this through scripted field?
Ex: 1 hello 3 test
I need to extract 1 and 3.

You can do this through logstash if you are using elasticsearch.
Run a logstash process with a config like
input {
elasticsearch {
hosts => "your_host"
index => "your_index"
query => "{ "query": { "match_all": {} } }"
}
}
filter {
grok {
match => { "your_string_field" => "%{NUMBER:num1} %{GREEDYDATA:middle_stuff} %{NUMBER:num2} %{GREEDYDATA:other_stuff}" }
}
mutate {
remove_field => ["middle_stuff", "other_stuff"]
}
}
output{
elasticsearch {
host => "yourhost"
index => "your index"
document_id => %{id}
}
}
This would essentially overwrite each document in your index with two more fields, num1 and num2 that correspond to the numbers that you are looking for. This is just a quick and dirty approach that would take up more memory, but would allow you to do all of the break up at one time instead of at visualization time.
I am sure there is a way to do this with scripting, look into groovy regex matching where you return a specific group.
Also no guarantee my config representation is correct as I don't have time to test it at the moment.
Have a good day!

Related

Generate multiple types with multiple csv

I am trying to generate various types in the same index based on various csv. As I donĀ“t know the amount of csv, making an input for each one would be non-viable.
So does anyone know how to generate types with the names of the files and in those, introduce the csv respectively?
input {
file {
path => "/home/user/Documents/data/*.csv"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
csv {
separator => ","
skip_header => "true"
autodetect_column_names => true
autogenerate_column_names => true
}
}
output {
elasticsearch {
hosts => "http://localhost:9200"
index => "final_index"
}
stdout {}
}
Thank you so much
Having multiple document structures in the same index has been removed in Elasticsearch indices since version 6, if a document is not looking the same way as the index is templated it will not be able to send the data to it, what you can do is make sure that all fields are known and you have one general template containing all possible fields.
Is there a reason why you want all of it in one index?
If it is for querying purposes or Kibana, do know you can wildcard when searching and have patterns for Kibana.
Update after your comment:
Use a filter to extract the filename using grok
filter {
grok {
match => ["path","%{GREEDYDATA}/%{GREEDYDATA:filename}\.csv"]
}
}
And use the filename in your output like this:
elasticsearch {
hosts => "http://localhost:9200"
index => "final_index-%{[filename]}"
}

Logstash parses logfiles to wrong index

I have an elasticsearch instance, which parses my logfiles according to my regex pattern, which takes the date from the logfile. Then the date should be used as the index pattern for elasticsearch purposes. This is where it gets wrong. My logstash-pipeline-config-file looks as follows:
input {
beats {
port => "5044"
}
}
filter {
grok {
match => { "message" => "%{LOGGERLEVEL:log}%{PIPE:k}%{TIMESTAMP_ISO8601:datetime}%{GREEDYDATA:data}"}
}
date {
match => ["datetime", "ISO8601"]
timezone => "Europe/Helsinki"
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
}
}
LOGGERLEVEL and PIPE are user defined regexes. This version parses the logs as it should but it indexes the first two hours of the day to the date before. If I change the config-file as follows, elasticsearch will ignore the first two hours altogether:
input {
beats {
port => "5044"
}
}
filter {
grok {
match => { "message" => "%{LOGGERLEVEL:log}%{PIPE:k}%{TIMESTAMP_ISO8601:datetime}%{GREEDYDATA:data}"}
}
date {
match => ["datetime", "ISO8601"]
timezone => "Europe/London"
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
}
}
How should I configurate my pipeline that one day would be indexed as a whole and under the same index that is the date found from the logfile?
Solved the problem. Using kibana, go to management -> advanced settings and change the dateFormat:tz to the desired format. In my case I have to use the second configuration and select Europe/London from kibana-settings.

Parse integer and show in timeline in Kibana

Here is the Kibana UI and I want to parse some Integer in the message. The number in the end of message is the process time for one method and I what to visualize the average process time by hour in Kibana. Is that possible?
I tried some conf in logstash:
filter{
json{
source => "message"
}
grok {
match => {
"message" => "^Finish validate %{NUMBER:cto_validate_time}$"
}
}
grok {
match => {
"message" => "^Finish customize %{NUMBER:cto_customize_time}$"
}
}
}
It works. But when I create the timechart I can not get the new field.
Since you don't care about performance issues, you may create a scripted field named process_time in your index pattern with the following painless code. What it does is simply take the last numerical value from your message field.
def m = /.*\s(\d+)$/.matcher(doc['message.keyword'].value);
if ( m.matches() ) {
return m.group(1)
} else {
return 0
}
Then you can build a chart to show the average process time by hour. Go to the Visualize tab and create a new vertical bar chart. On the Y-Axis you'll create an Average aggregation on the process_time field and on the X-Axis you'll use a Date histogram aggregation on your timestamp field. A sample is shown below:
Note: You also need to add the following line in your elasticsearch.yml file and restart ES:
script.painless.regex.enabled: true
UPDATE
If you want to do it via Logstash you can add the following grok filter
filter{
grok {
match => {
"message" => "^Finish customize in controller %{NUMBER:cto_customize_time}$"
}
}
mutate {
convert => { "cto_customize_time" => "integer" }
}
}

Logstash: error for querying elasticsearch

Hello everyone,
Through logstash, I want to query elasticsearch in order to get fields from previous events and do some computation with fields of my current event and add new fields. Here is what I did:
input file:
{"device":"device1","count":5}
{"device":"device2","count":11}
{"device":"device1","count":8}
{"device":"device3","count":100}
{"device":"device3","count":95}
{"device":"device3","count":155}
{"device":"device2","count":15}
{"device":"device1","count":55}
My expected output:
{"device":"device1","count":5,"previousCount=0","delta":0}
{"device":"device2","count":11,"previousCount=0","delta":0}
{"device":"device1","count":8,"previousCount=5","delta":3}
{"device":"device3","count":100,"previousCount=0","delta":0}
{"device":"device3","count":95,"previousCount=100","delta":-5}
{"device":"device3","count":155,"previousCount=95","delta":60}
{"device":"device2","count":15,"previousCount=11","delta":4}
{"device":"device1","count":55,"previousCount=8","delta":47}
Logstash filter part:
filter {
elasticsearch {
hosts => ["localhost:9200/device"]
query => 'device:"%{[device]}"'
sort => "#timestamp:desc"
fields => ['count','previousCount']
}
if [previousCount]{
ruby {
code => "event[delta] = event[count] - event[previousCount]"
}
}
else{
mutate {
add_field => { "previousCount" => "0" }
add_field => { "delta" => "0" }
}
}
}
My problem:
For every line of my input file I got the following error : Failed to query elasticsearch for previous event ..
It seems that every line completely treated is not put in elasticsearch before logstash starts to treat the next line.
I don't know if my conclusion is correct and, if yes, why it happens.
So, do you know how I could solve this problem please ?!
Thank you for your attention and your help.
S

How to overwrite field value in Kibana?

I am using Logstash to feed data into Elasticsearch and then analyzing that data with Kibana. I have a field that contains numeric identifiers. These are not easy to read. How can I have Kibana overwrite or show a more human-readable value?
More specifically, I have a 'ip.proto' field. When this field contains a 6, it should be shown as 'TCP'. When this field contains a 7, it should be shown as 'UDP'.
I am not sure which tool in the ELK stack I need to modify to make this happen.
Thanks
You can use conditionals and the mutate filter:
filter {
if [ip][proto] == "6" {
mutate {
replace => ["[ip][proto]", "TCP"]
}
} else if [ip][proto] == "7" {
mutate {
replace => ["[ip][proto]", "UDP"]
}
}
}
This quickly gets clumsy, and the translate filter is more elegant (and probably faster). Untested example:
filter {
translate {
field => "[ip][proto]"
dictionary => {
"6" => "TCP"
"7" => "UDP"
}
}
}

Resources