Is it possible to join 2 lines of logs from 2 separate log files using Logstash - elasticsearch

I have a 2 separate IIS log files (advanced and simple)
They need to be joined, because the advanced log is missing information that the simple one has written, but they have the same timestamp.
input { file {
path => "C:/Logs/*.log"
start_position => "beginning"}
}
filter {
grok {
break_on_match => "true"
match => ["message", '%{TIMESTAMP_ISO8601:log_timestamp} \"%{DATA:s_computername}\"']
match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{NOTSPACE:uriQuery} "]
}
output {
elasticsearch {
hosts => "localhost:9200"
}
}
}
simplified version. I want elasticsearch to have a entry containing log_timestamp, s_computername, and uriQuery.
Using the multiline codec, it is possible to merge them if the lines were next to each other. As they're in separate files, I have not yet found a way to do this. Is it possible to merge the two using the same timestamp as a unique identifier?

Related

Parsing log data throught grok filter (logstash)

I'm pretty new to ELK, and I'm trying to parse my logs throught logstash. Logs are sent by filebeat.
Logs looks like:
2019.12.02 16:21:54.330536 [ 1 ] {} <Information> Application: starting up
2020.03.21 13:14:54.941405 [ 28 ] {xxx23xx-xxx23xx-4f0e-a3c6-rge3gu1} <Debug> executeQuery: (from [::ffff:192.0.0.0]:9999) blahblahblah
2020.03.21 13:14:54.941469 [ 28 ] {xxx23xx-xxx23xx-4f0e-a3c6-rge3gu0} <Error> executeQuery: Code: 62, e.displayText() = DB::Exception: Syntax error: failed at position 1
My default logstash configuration is:
input {
beats {
port => 5044
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "%{[#metadata][beat]}-%{[#metadata][version]}-%{+YYYY.MM.dd}"
}
}
In my log example, I extract fields like this:
timestamp
code
pipelineId
logLevel
program
message.
But I have several problems with my grok pattern. First, the timestamp on the log is quite different than a classic timestamp. How can I get it recognized ?
I also have problems when {} can be empty or not. Can you give me some advices on what should be the correct grok pattern please ?
Also, in Kibana, I have A LOT of informations, such as hostname, os details, agent details, source etc. I've read that these fields are ES metadata so it's not possible to remove them. I found that it's
a lot of informations throught, is there any way to "hide" these ?
Grok pattern
On the screenshot below you can see the pattern I constructed for your example log (in Grok Debugger):
Is this the result you're looking for?
Logstash config
# logstash.conf
…
filter {
grok {
patterns_dir => ["./patterns"]
match => {
"message" => "%{CUSTOM_DATE:timestamp}\s\[\s%{BASE10NUM:code}\s\]\s\{%{GREEDYDATA:pipeline_id}\}\s\<%{GREEDYDATA:log_level}\>\s%{GREEDYDATA:program_message}"
}
}
}
…
Custom pattern
As you can see, I told grok to look for my custom patterns in the patterns directory which I put in the same location as my logstash.conf file. In this directory I created the custom.txt file with the following content:
# patterns/custom.txt
CUSTOM_DATE (?>\d\d){1,2}\.(?:0?[1-9]|1[0-2])\.(?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9])\s(?!<[0-9])(?:2[0123]|[01]?[0-9]):(?:[0-5][0-9])(?::(?:(?:[0-5][0-9]|60)(?:[:.,][0-9]+)?))(?![0-9])
I didn't write this long pattern on my own. I started with this line:
CUSTOM_DATE %{YEAR}\.%{MONTHNUM}\.%{MONTHDAY}\s%{TIME}
Then, I replaced every predefined pattern with a corresponding regular expression (one by one, directly in the Grok Debugger). You can use the %{YEAR}\.%{MONTHNUM}\.%{MONTHDAY}\s%{TIME} in your application, but the Grok Debugger interface will print every part separately.
Do you want to remove empty fields?
I don't know what you want to do in case the pipeline_id field is empty. If you want to remove it completely you can try adding the following lines to your config:
# logstash.conf
…
filter {
grok {
…
}
if [pipeline_id] == "" {
mutate {
remove_field => ["pipeline_id"]
}
}
}
…
Useful resources
Available patterns that I used in my pattern
What to do when part of one field got caught in a different pattern

Elasticsearch is slow to update mapping

Elasticsearch has become extremely slow when receiving input from Logstash, particularly when using file input. I have had to wait for 10+ minutes to get results. Oddly enough, standard input is mapped very quickly, which leads me to believe that my config file may be too complex, but it really isn't.
My config file uses file input, my filter is grok with 4 fields, and my output is to Elasticsearch. The file I am inputting is a .txt with 5 lines in it.
Any suggestions? Elasticsearch and Logstash newbie here.
input {
file {
type => "type"
path => "insert_path"
start_position = > "beginning'
}
}
filter {
grok { match => {"message" => "%{IP:client} %{WORD:primary} %{WORD:secondary} %{NUMBER:speed}" }
}
output {
elasticsearch {
hosts => ["localhost:9200"]
}
}
Thought: Is it a sincedb_path issue? I often try to reparse files without changing the filename.

Is it possible to index only the matched log lines of grok in Logstash?

I'm having a log file, which actually has INFOs' and ERRORs. So I tried to match only the needful INFOs by using the grok filter. So this is how my log lines look like. Few of them from the file.
And this is how my grok look like in my logstash conf:
grok {
patterns_dir => ["D:/elk_stack_for_ideabiz/elk_from_chamith/ELK_stack/logstash-5.1.1/bin/patterns"]
match => {
"message" => [
"^TID\: \[0\] \[AM\] \[%{LOGTIMESTAMPTWO:logtimestamp}]%{REQUIREDDATAFORAPP:app_message}",
"^TID\: \[0\] \[AM\] \[%{LOGTIMESTAMPTWO:logtimestamp}]%{REQUIREDDATAFORRESPONSESTATUS:response_message}"
]
}
}
The pattern seems to be working fine. I could provide the pattern if required.
I've got two questions. One is I wanted only the grok matched lines to be sent to the index, and prevent Logstash from indexing the non-matched ones and the second is to prevent Logstash from showing the message in every single ES record.
I tried using the overwrite as such under the match but still no luck:
overwrite => [ "message" ]
All in all what I need to see in my indice are the messages (app_message, response_message from the above match), which should match the above two conditions. Where as now, all the lines are getting indexed.
Is it possible do something like this? Or does Logstash index all of them by default?
Where am I going wrong? Any help could be appreciated.
Indexing only the lines you want is pretty straightforward.
By default, if grok fails to match anything it will add the tag _grokparsefailure.
Now what you want to do is check for that tag and then use the drop filter.
if "_grokparsefailure" in [tags] {
drop { }
}
sysadmin1138 mentioned that you can select between different grok filters by adding tag_on_failure => ['_INFOFailure' ]
For your sencond question you can simply remove the field. Every filter has a remove_field option but I use the mutate filter to indicate that I am manipulating the message.
mutate {
remove_field => ["message"]
}

Create index in kibana without using kibana

I'm very new to the elasticsearch-kibana-logstash and can't seem to find solution for this one.
I'm trying to create index that I will see in kibana without having to use the POST command in Dev Tools section.
I have set test.conf-
input {
file {
path => "/home/user/logs/server.log"
type => "test-type"
start_position => "beginning"
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "new-index"
}
}
and then
bin/logstash -f test.conf from logstash directory
what i get is that I can't find the new-index in kibana (index patterns section), when I use elasticsearch - http://localhost:9200/new-index/ it presents an error and when I go to http://localhost:9600/ (the port it's showing) it doesn't seem to have any errors
Thanks a lot for the help!!
It's obvious that you won't be able to find the index which you've created using logstash in Kibana, unless you're manually creating it there within the Managemen section of Kibana.
Make sure, that you have the same name of the indice which you created using logstash. Have a look at the doc, which conveys:
When you define an index pattern, indices that match that pattern must
exist in Elasticsearch. Those indices must contain data.
which pretty much says that the indice should exist for you to create the index in Kibana. Hope it helps!
I have actually succeeded to create index even without first creating it in Kibana
I used the following config file -
input {
file {
path => "/home/hadar/tmp/logs/server.log"
type => "test-type"
id => "NEWTRY"
start_position => "beginning"
}
}
filter {
grok {
match => { "message" => "%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day} %{HOUR:hour}:%{MINUTE:minute}:%{SECOND:second} - %{LOGLEVEL:level} - %{WORD:scriptName}.%{WORD:scriptEND} - " }
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "new-index"
codec => line { format => "%{year}-%{month}-%{day} %{hour}:%{minute}:%{second} - %{level} - %{scriptName}.%{scriptEND} - \"%{message}\"" }
}
}
I made sure that the index wasn't already in Kibana (I tried with other indexes names too just to be sure...) and eventually I did see the index with the log's info in both Kibana (I added it in the index pattern section) and Elasticsearch when I went to http://localhost:9200/new-index
The only thing I should have done was to erase the .sincedb_XXX files which are created under data/plugins/inputs/file/ after every Logstash run
OR
the other solution (for tests environment only) is to add sincedb_path=>"/dev/null" to the input file plugin which indicates to not create the .sincedb_XXX file
You can create directly index in elastic search using https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html
and these indices can be used in Kibana.

How to assign a variable in logstash config?

I'm trying to fetch the host name from the events that logstash processes, and if the events matches to the criteria I want the host name to be sent to another file. But meanwhile the event should be sent to elasticsearch output.
The idea what am having is to assign the host name to a variable, and send the variable value to a file, if the "if" condition is satisfied.
Will this be possible with logstash?
Regards,
Gaurav
Yes, what you want is posible in Logstash. The Logstash site has documentation for the config format, and all the available plugins which can be found at http://logstash.net/docs/1.4.0/. You will probably want to use the grok filter to extract the host name, and the file output to write the data.
Here is an example confg, which does what you want:
input {
#some input
}
filters {
grok {
match => ["message", "%{HOSTNAME:host} rest of message line" ]
add_tag => ["has_hostname"]
}
}
output {
elasticsearch {}
if "has_hostname" in [tags] {
file {
message_format => "%{host}"
path => "path/to/file"
}
}
}
The grok pattern will need to be altered to match your data, the logstash docs include a link the default pattern set that you can use.

Resources