Separate output values from a single grok query? - logstash

I've been capturing web logs using logstash, and specifically I'm trying to capture web URLs, but also split them up.
If I take an example log entry URL:
"GET https://www.stackoverflow.com:443/some/link/here.html HTTP/1.1"
I use this grok pattern:
\"(?:%{NOTSPACE:http_method}|-)(?:%{SPACE}http://)?(?:%{SPACE}https://)?(%{NOTSPACE:http_site}:)?(?:%{NUMBER:http_site_port:int})?(?:%{GREEDYDATA:http_site_url})? (?:%{WORD:http_type|-}/)?(?:%{NOTSPACE:http_version:float})?(?:%{SPACE})?\"
I get this:
{
"http_method": [
[
"GET"
]
],
"SPACE": [
[
" ",
null,
""
]
],
"http_site": [
[
"www.stackoverflow.com"
]
],
"BASE10NUM": [
[
"443"
]
],
"http_site_url": [
[
"/some/link/here.html"
]
],
"http_type": [
[
"HTTP"
]
]
}
The trouble is, I'm trying to ALSO capture the entire URL:
https://www.stackoverflow.com:443/some/link/here.html
So in total, I'm seeking 4 separate outputs:
http_site_complete https://www.stackoverflow.com:443/some/link/here.html
http_site www.stackoverflow.com
http_site_port 443
http_site_url /some/link/here.html
Is there some way to do this?

First, look at the built-in patterns for dealing with URLs. Putting something like URIHOST in your pattern will be easier to read and maintain that a bunch od WORDs or NOTSPACEs.
Second, once you have lots of little fields, you can always use logstash's filters to manipulate them. You could use:
mutate {
add_field => { "http_site_complete", "%{http_site}:%{http_site_port}%{http_site_url}" }
}
}
Or you could get fancy with your regexp and use a named group:
(?<total>%{WORD:wordOne} %{WORD:wordTwo} %{WORD:wordThree})
which would individually capture three fields and make one more field from the whole string.

Related

How do you find a quoted string with specific word in a log message using grok pattern

I have a log message from my server with the format below:
{"host":"a.b.com","source_type":"ABCD"}
I have this grok pattern so far but it accepts any word in double quotation.
\A%{QUOTEDSTRING}:%{PROG}
how can I change "QUOTEDSTRING" that only check for "host"?
"host" is not at the beginning of the message all the time and it can be found in the middle of message as well.
Thanks for your help.
Since the question specified that "host" can be anywhere between in the log, you can use the following:
\{(\"%{GREEDYDATA:data_before}\",)?(\"host\":\"%{DATA:host_value}\")?(,\"%{GREEDYDATA:data_after}\")?\}
Explanation :
data_before stores the optional data before host type entry is found. You can separate it more as per your need
host : this stores the host value
data_after stores the optional data after host type entry is found. You can seaprate it more as per your need
Example :
{"host":"a.b.com","source_type":"ABCD"}
Output :
{
"data_before": [
[
null
]
],
"host_value": [
[
"a.b.com"
]
],
"data_after": [
[
"source_type":"ABCD"
]
]
}
{"host":"a.b.com"}
Output :
{
"data_before": [
[
null
]
],
"host_value": [
[
"a.b.com"
]
],
"data_after": [
[
null
]
]
}
{"source_type":"ABCD","host":"a.b.com","data_type":"ABCD"}
Output :
{
"data_before": [
[
"source_type":"ABCD"
]
],
"host_value": [
[
"a.b.com"
]
],
"data_after": [
[
"data_type":"ABCD"
]
]
}
Tip : Use the following resources to tune and test your logging patterns :
Grok Debugger
Grok Patterns Full List

Logstash Grok Filter for Opentracing in Quarkus' log

Working on getting our Quarkus log files into elasticsearch. My problem is in trying to process the logs in logstash... How can I get the traceId and spanId using grok filter?
Here's a sample log entry:
21:11:32 INFO traceId=50a4f8740c30b9ca, spanId=50a4f8740c30b9ca, sampled=true [or.se.po.re.EmployeeResource] (vert.x-eventloop-thread-1) getEmployee with [id:2]
Here is my grok:
%{TIME} %{LOGLEVEL} %{WORD:traceId} %{WORD:spanId} %{GREEDYDATA:msg}
Using grok debugger, it seem traceId and spanId are not detected.
AFIK Grok expressions need to be exactly as the original text. So try to add commas, spaces and event all the text you do not want to capture. For instance traceId=
%{TIME} %{LOGLEVEL} traceId=%{WORD:traceId}, spanId=%{WORD:spanId}, %{GREEDYDATA:msg}
This is the output from https://grokdebug.herokuapp.com/ for your log line and my grok expression suggestion.
{
"TIME": [
[
"21:11:32"
]
],
"HOUR": [
[
"21"
]
],
"MINUTE": [
[
"11"
]
],
"SECOND": [
[
"32"
]
],
"LOGLEVEL": [
[
"INFO"
]
],
"traceId": [
[
"50a4f8740c30b9ca"
]
],
"spanId": [
[
"50a4f8740c30b9ca"
]
],
"msg": [
[
"sampled=true [or.se.po.re.EmployeeResource] (vert.x-eventloop-thread-1) getEmployee with [id:2]"
]
]
}
As other users have mentioned, it is important to notice the spaces between the words. For instance, there are two spaces between the logLevel and the traceId. You can use the s+ regular expression to forget about them. But maybe using it too much has a big (and bad) impact on performance.
%{TIME}\s+%{LOGLEVEL}\s+traceId=%{WORD:traceId},\s+spanId=%{WORD:spanId},\s+%{GREEDYDATA:msg}
The issue could be a couple of things:
The spacing between fields might be off (try adding \s? or perhaps \t after %{LOGLEVEL})
The %{WORD} pattern might not be picking up the value because of the inclusion of =
Something like this pattern could work (you might need to modify it some):
^%{TIME:time} %{LOGLEVEL:level}\s?(?:%{WORD:traceid}=%{WORD:traceid}), (?:%{WORD:spanid}=%{WORD:spanid}), (?:%{WORD:sampled}=%{WORD:sampled}) %{GREEDYDATA:msg}$

Concatenate a word to an email using pre-defined grok filter

first of all thank you for reading my question.
i have an email address in a log in following format,
Apr 24 19:38:51 ip-10-0-1-204 sendmail[9489]: w3OJco1s009487: sendid:name#test.co.uk, delay=00:00:01, xdelay=00:00:01, mailer=smtp, pri=120318, relay=webmx.bglen.net. [10.0.3.231], dsn=2.0.0, stat=Sent (Ok: queued as E2DEF60724), w3OJco1s009487: to=<username#domain.us>, delay=00:00:01, xdelay=00:00:01, mailer=smtp, pri=120318, relay=webmx.[redacted].net. [10.0.3.231], dsn=2.0.0, stat=Sent (Ok: queued as E2DEF60724)
and i need to extract the email along with the word sendid
output should look like this,
{
"DATA": [
[
"sendid:name#test.co.uk"
]
]
}
i have tried following but it only extracts email i tested it here, http://grokdebug.herokuapp.com/ ,
sendid:%{DATA},
How can i concatenate the word sendid: to the email without creating a new field or defining a new regex? can someone please help?
i have also tried this but it doesn't work,
sendid:%{"sendid:"} %{DATA},
Your sendid:%{DATA}, won't work because anything that you provide outside grok pattern are matched as surroundings, in your case everything between sendid: and , will be matched, and it will give you,
{
"DATA": [
[
"name#test.co.uk"
]
]
}
You need to create a custom pattern and combine it with pre-defined pattern for your solution, since you cannot use any pre-defined pattern entirely.
Logstash allows you to create custom patterns using Oniguruma regex library for such situations. The syntax is,
(?<field_name>the pattern here)
in your case it will be,
\b(?<data>sendid:%{EMAILADDRESS})\b
OUTPUT:
{
"data": [
[
"sendid:name#test.co.uk"
]
],
"EMAILADDRESS": [
[
"name#test.co.uk"
]
],
"EMAILLOCALPART": [
[
"name"
]
],
"HOSTNAME": [
[
"test.co.uk"
]
]
}

using Grok to skip parts of message or logs

I have just started using grok for logstash and I am trying to parse my log file using grok filter.
My logline is something like below
03-30-2017 13:26:13 [00089] TIMER XXX.TimerLog: entType [organization], queueType [output], memRecno = 446323718, audRecno = 2595542711, elapsed time = 998ms
I want to capture only the initial date/time stamp, entType [organization], and elapsed time = 998ms.
However, it looks like I have to match pattern for every word and number in the line. Is there a way I can skip it ? I tried to look everywhere but couldn't find anything. Kindly help.
As per Charles Duffy's comment.
There are 2 ways of doing this:
The GREEDYDATA way (?:.*):
grok {
match => {"message" => "^%{DATE_US:dte}\s*%{TIME:tme}\s*\[%{GREEDYDATA}elapsed time\s*=\s*%{BASE10NUM}"
}
Or, telling it to ignore a match and look for the next one in the list.
grok {
break_on_match => false
match => { "message" => "^%{DATE_US:dte}\s*%{TIME:tme}\s*\[" }
match => { "message" => "elapsed time\s*=\s*%{BASE10NUM:elapsedTime}"
}
You can then rejoin the date & time into a single field and convert it to a timestamp.
As Charles Duffy suggested, you can simply bypass data you don't need.
You can use .* to do that.
Following will produce the output you want,
%{DATE_US:dateTime}.*entType\s*\[%{WORD:org}\].*elapsed time\s*=\s*%{BASE10NUM}
Explanation:
\s* matches space character.
\[ is bypassing [ character.
%{WORD:org} defines a word boundary and place it in a new field org
Outputs
{
"dateTime": [
[
"03-30-2017"
]
],
"MONTHNUM": [
[
"03"
]
],
"MONTHDAY": [
[
"30"
]
],
"YEAR": [
[
"2017"
]
],
"org": [
[
"organization"
]
],
"BASE10NUM": [
[
"998"
]
]
}
Click for a list of all available grok patterns

Logstash parse date/time

I have the following I'm trying to parse with GROK:
Hello|STATSTIME=20-AUG-15 12.20.03.051000 PM|World
I can parse the first bunch of it with GROK like so:
match => ["message","%{WORD:FW}\|STATSTIME=%{MONTHDAY:MDAY}-%{WORD:MON}-%{INT:YY} %{INT:HH}"]
Anything further than that gives me an error. I can't figure out how to quote the : character, : does not work and %{TIME:time} does not work. I'd like to be able to get the whole thing as a timestamp, but can't get it broken up. Any ideas?
You can use this to debug grok expressions
The time format is as shown here
To parse 12.20.03.051000
%{INT:hour}.%{INT:min}.%{INT:sec}.%{INT:ms}
Output will be something like this
{
"hour": [
[
"12"
]
],
"min": [
[
"20"
]
],
"sec": [
[
"03"
]
],
"ms": [
[
"051000"
]
]
}

Resources