Logstash cannot extract json key - json

I need help regarding logstash filter to extract json key/value to new_field. The following is my logstash conf.
input {
tcp {
port => 5044
}
}
filter {
json {
source => "message"
add_field => {
"data" => "%{[message][data]}"
}
}
}
output {
stdout { codec => rubydebug }
}
I have tried with mutate:
filter {
json {
source => "message"
}
mutate {
add_field => {
"data" => "%{[message][data]}"
}
}
}
I have tried with . instead of []:
filter {
json {
source => "message"
}
mutate {
add_field => {
"data" => "%{message.data}"
}
}
}
I have tried with index number:
filter {
json {
source => "message"
}
mutate {
add_field => {
"data" => "%{[message][0]}"
}
}
}
All with no luck. :(
The following json is sent to port 5044:
{"data": "blablabla"}
The problem is the new field not able to extract value from the key of the json.
"data" => "%{[message][data]}"
The following is my stdout:
{
"#version" => "1",
"host" => "localhost",
"type" => "logstash",
"data" => "%{[message][data]}",
"path" => "/path/from/my/app",
"#timestamp" => 2019-01-11T20:39:10.845Z,
"message" => "{\"data\": \"blablabla\"}"
}
However if I use "data" => "%{[message]}" instead:
filter {
json {
source => "message"
add_field => {
"data" => "%{[message]}"
}
}
}
I will get the whole json from stdout.
{
"#version" => "1",
"host" => "localhost",
"type" => "logstash",
"data" => "{\"data\": \"blablabla\"}",
"path" => "/path/from/my/app",
"#timestamp" => 2019-01-11T20:39:10.845Z,
"message" => "{\"data\": \"blablabla\"}"
}
Can anyone please tell me what I did wrong.
Thank you in advance.
I use docker-elk stack, ELK_VERSION=6.5.4

add_field is used to add custom logic when filter succeeds, many filters have this option. If you want to parse json into a field, you should use target:
filter {
json {
source => "message"
target => "data" // parse into data field
}
}

Related

Removing Json object name using Logtash

I'm trying to parse the following json using logstash
{
"payload": "{\"class\":\"OpenLoyalty\\\\Component\\\\Account\\\\Domain\\\\Event\\\\PointsTransferHasBeenExpired\",\"payload\":{\"accountId\":\"1cbd42b8-1b1f-4a13-a28f-eefeb73a64b0\",\"pointsTransferId\":\"e82c96cf-32a3-43bd-9034-4df343e5f111\"}}"
}
using this filter :
input {
jdbc {
jdbc_connection_string => "jdbc:postgresql://localhost:5432/openloyalty"
jdbc_user => "openloyalty"
jdbc_password => "openloyalty"
jdbc_driver_library => "C:\logstash\postgresql-42.2.12.jar"
jdbc_driver_class => "org.postgresql.Driver"
statement => "SELECT payload from events where events.id=130;"
}
}
filter {
json {
source => "payload"
remove_field => ["class"]
}
}
output {
stdout { codec => json_lines }
}
I get this output:
{
"#version": "1",
"#timestamp": "2020-05-12T11:27:15.097Z",
"payload": {
"accountId": "1cbd42b8-1b1f-4a13-a28f-eefeb73a64b0",
"pointsTransferId": "e82c96cf-32a3-43bd-9034-4df343e5f111"
}
}
however, what I'm looking for is like this:
{
"#version": "1",
"#timestamp": "2020-05-12T11:27:15.097Z",
{
"accountId": "1cbd42b8-1b1f-4a13-a28f-eefeb73a64b0",
"pointsTransferId": "e82c96cf-32a3-43bd-9034-4df343e5f111"
}
}
how can I remove the "payload" name from my Json object?
You can use the mutate filter with the following config after your json filter.
mutate {
rename => {
"[payload][accountId]" => "accountId"
"[payload][pointsTransferId]" => "pointsTransferId"
}
remove_field => ["[payload]"]
}
This will rename your fields and remove the empty payload json object after the rename.

Logstash wrap json object

I would like to wrap a json object sent to Logstash via the http listener plugin so I can send it off to Splunk. I get an object that looks like:
{
"foo" : "text",
"bar" : "text"
}
and I need it to look like:
{ "event" :
{
"foo" : "text",
"bar" : "text"
}
}
I just can not find how to access that top level object.
config:
input {
http {
port => 8080
codec => "json"
}
}
filter {
mutate {
rename => { "WHAT GOES HERE???" => "event" }
}
}
output {
stdout { codec => json }
}
Thanks so much!
You can use rename or add_field.
With rename
mutate {
rename => { "foo" => "[event][foo]" }
rename => { "bar" => "[event][bar]" }
}
With add_field
mutate {
add_field => { "[event][foo]" => "%{[foo]}" }
add_field => { "[event][bar]" => "%{[bar]}" }
}
If you use add_field, the fields foo and bar are kept in the message, you can remove them using remove_field
mutate {
remove_field => [ "foo", "bar" ]
}
Another elegant way is to use json target within a filter:
filter {
json {
source => "message"
target => "event"
}
}
https://www.elastic.co/guide/en/logstash/current/plugins-filters-json.html#plugins-filters-json-target

how to write filter section in logstash for json formatted nested file

I have below log file.
{
"level":"error",
"msg":"err:ERR_AUTH_PORTAL_USER,tenantid:7,reason:out of access period,code:EP05,username:Che,venueid:10,devicemac:##-##-##-##-##-##,apmac:##-##-##-##-##-##,ssid:Jetwig,timestamp:Jan 22 2018 09:05:31 UTC",
"time":"2018-01-22T14:35:31+05:30"
}
I want to filter them according to msg: err:ERR_AUTH_PORTAL_USER using logstash grok filter. How can I do this?
This is what I have tried so far:
input {
file {
type => vampserror
path => "/home/ampsErrorLog/getError/*"
start_position => "beginning"
}
}
filter {
grok {
patterns_dir => ["./patterns"]
match => { "message" => "%{LOGLEVEL:level} %{MESSAGE:msg} %{TIMESTAMP:timestamp}" }
}
}
if "ERR_AUTH_PORTAL_USER" in [msg] {
}
output {
stdout { codec => rubydebug }
}
input {
file{
type=>"json"
path=>"logfile location"
start_position => "beginning"
}
}
filter {
json{
source => "message"
}
}
output {
if[msg][err]=="ERR_AUTH_PORTAL_USER"{
stdout { codec => rubydebug }
mongodb {
collection => "error"
database => "dev"
uri => "mongodb://localhost:27017"
isodate => true
}
}
file{
path => "/tmp/output.txt"
}
}
add this to your conf file
mongodb {
collection => "error"
database => "dev"
uri => "mongodb://localhost:27017"
isodate => true
}
is optional

Logstash Parsing and Calculations with CSV

I am having trouble parsing and calculating performance Navigation Timing data I have in a csv.
I was able to parse the fields but not sure how to approach the calculations (below) properly. Some points to keep in mind:
Data sets are grouped together by the bolded value (it is the ts of when the 21 datapoints were taken
ACMEPage-1486643427973,unloadEventEnd,1486643372422
2.Calculations need to be done with data points within the group
I am assuming some tagging and grouping will need to be done but I don't have a clear vision on how to implement it. Any help would be greatly appreciated.
Thanks,
---------------Calculations-----------------
Total First byte Time = responseStart - navigationStart
Latency = responseStart – fetchStart
DNS / Domain Lookup Time = domainLookupEnd - domainLookupStart
Server connect Time = connectEnd - connectStart
Server Response Time = responseStart - requestStart
Page Load time = loadEventStart - navigationStart
Transfer/Page Download Time = responseEnd - responseStart
DOM Interactive Time = domInteractive - navigationStart
DOM Content Load Time = domContentLoadedEventEnd - navigationStart
DOM Processing to Interactive =domInteractive - domLoading
DOM Interactive to Complete = domComplete - domInteractive
Onload = loadEventEnd - loadEventStart
-------Data in CSV-----------
ACMEPage-1486643427973,unloadEventEnd,1486643372422
ACMEPage-1486643427973,responseEnd,1486643372533
ACMEPage-1486643427973,responseStart,1486643372416
ACMEPage-1486643427973,domInteractive,1486643373030
ACMEPage-1486643427973,domainLookupEnd,1486643372194
ACMEPage-1486643427973,unloadEventStart,1486643372422
ACMEPage-1486643427973,domComplete,1486643373512
ACMEPage-1486643427973,domContentLoadedEventStart,1486643373030
ACMEPage-1486643427973,domainLookupStart,1486643372194
ACMEPage-1486643427973,redirectEnd,0
ACMEPage-1486643427973,redirectStart,0
ACMEPage-1486643427973,connectEnd,1486643372194
ACMEPage-1486643427973,toJSON,{}
ACMEPage-1486643427973,connectStart,1486643372194
ACMEPage-1486643427973,loadEventStart,1486643373512
ACMEPage-1486643427973,navigationStart,1486643372193
ACMEPage-1486643427973,requestStart,1486643372203
ACMEPage-1486643427973,secureConnectionStart,0
ACMEPage-1486643427973,fetchStart,1486643372194
ACMEPage-1486643427973,domContentLoadedEventEnd,1486643373058
ACMEPage-1486643427973,domLoading,1486643372433
ACMEPage-1486643427973,loadEventEnd,1486643373514
----------Output---------------
"path" => "/Users/philipp/Downloads/build2/logDataPoints_com.concur.automation.cge.ui.admin.ADCLookup_1486643340910.csv",
"#timestamp" => 2017-02-09T12:29:57.763Z,
"navigationTimer" => "connectStart",
"#version" => "1",
"host" => "15mbp-09796.local",
"elapsed_time" => "1486643372194",
"pid" => "1486643397763",
"page" => "ADCLookupDataPage",
"message" => "ADCLookupDataPage-1486643397763,connectStart,1486643372194",
"type" => "csv"
}
--------------logstash.conf----------------
input {
file {
type => "csv"
path => "/Users/path/logDataPoints_com.concur.automation.acme.ui.admin.acme_1486643340910.csv"
start_position => beginning
# to read from the beginning of file
sincedb_path => "/dev/null"
}
}
filter {
csv {
columns => ["page_id", "navigationTimer", "elapsed_time"]
}
if (["elapsed_time"] == "{}" ) {
drop{}
}
else {
grok {
match => { "page_id" => "%{WORD:page}-%{INT:pid}"
}
remove_field => [ "page_id" ]
}
}
date {
match => [ "pid", "UNIX_MS" ]
target => "#timestamp"
}
}
output {
elasticsearch { hosts => ["localhost:9200"] }
stdout { codec => rubydebug }
}
I the following to get trend my data:
-I found it easier to pivot the data, rather than going down the column, to have the data go along the rows per each "event" or "document"
-Each field needed to be mapped accordingly as an integer or string
Once the data was in Kibana properly I had problems using the ruby code filter to make simple math calculations so I ended up using the "scripted fields" to make the calculations in Kibana.
input {
file {
type => "csv"
path => "/Users/philipp/perf_csv_pivot2.csv"
start_position => beginning
# to read from the beginning of file
sincedb_path => "/dev/null"
}
}
filter {
csv {
columns => ["page_id","unloadEventEnd","responseEnd","responseStart","domInteractive","domainLookupEnd","unloadEventStart","domComplete","domContentLoadedEventStart","domainLookupstart","redirectEnd","redirectStart","connectEnd","toJSON","connectStart","loadEventStart","navigationStart","requestStart","secureConnectionStart","fetchStart","domContentLoadedEventEnd","domLoading","loadEventEnd"]
}
grok {
match => { "page_id" => "%{WORD:page}-%{INT:page_ts}" }
remove_field => [ "page_id", "message", "path" ]
}
mutate {
convert => { "unloadEventEnd" => "integer" }
convert => { "responseEnd" => "integer" }
convert => { "responseStart" => "integer" }
convert => { "domInteractive" => "integer" }
convert => { "domainLookupEnd" => "integer" }
convert => { "unloadEventStart" => "integer" }
convert => { "domComplete" => "integer" }
convert => { "domContentLoadedEventStart" => "integer" }
convert => { "domainLookupstart" => "integer" }
convert => { "redirectEnd" => "integer" }
convert => { "redirectStart" => "integer" }
convert => { "connectEnd" => "integer" }
convert => { "toJSON" => "string" }
convert => { "connectStart" => "integer" }
convert => { "loadEventStart" => "integer" }
convert => { "navigationStart" => "integer" }
convert => { "requestStart" => "integer" }
convert => { "secureConnectionStart" => "integer" }
convert => { "fetchStart" => "integer" }
convert => { "domContentLoadedEventEnd" => "integer" }
convert => { "domLoading" => "integer" }
convert => { "loadEventEnd" => "integer" }
}
date {
match => [ "page_ts", "UNIX_MS" ]
target => "#timestamp"
remove_field => [ "page_ts", "timestamp", "host", "toJSON" ]
}
}
output {
elasticsearch { hosts => ["localhost:9200"] }
stdout { codec => rubydebug }
}
Hope this can help someone else,

Interpret locations from Keen.io JSON file in logstash filter

I'm trying to parse a JSON file from Keen.io with logstash into elasticsearch. The location and timestamp are stored in parameters like this:
{
"result":
[
{
"keen":
{
"timestamp": "2014-12-02T12:23:51.000Z",
"created_at": "2014-12-01T23:25:31.396Z",
"id": "XXXX",
"location":
{
"coordinates": [-95.8, 36.1]
}
}
}
]
}
My filter currently looks like this:
input {
file {
path => ["test.json"]
start_position => beginning
type => json
}
}
filter {
json {
source => message
remove_field => message
}
}
output {
stdout { codec => rubydebug }
}
How can I parse the "timestamp" and "location" fields so they are used for the #timestamp and #geoip.coordinates in Elasticsearch?
Update:
I've tried variations of this with no luck. The documentation is very basic - am I misunderstanding how to reference the JSON fields? Is there a way of adding debug output to help? I tried How to debug the logstash file plugin and Print a string to stdout using Logstash 1.4? but neither works.
filter {
json {
source => message
remove_field => message
}
if ("[result][0][keen][created_at]") {
date {
add_field => [ "[timestamp]", "[result][0][keen][created_at]" ]
remove_field => "[result][0][keen][created_at]"
}
}
Update 2:
Date is working now, still need to get location working.
filter {
json {
source => message
remove_field => message
add_tag => ["valid_json"]
}
if ("valid_json") {
if ("[result][0][keen][created_at]") {
date {
match => [ "[result][0][keen][created_at]", "ISO8601" ]
}
}
}
}
Keen.io's "created_at" field is stored in ISO 8601 format and so can easily be parsed by the date filter. Lat/long co-ordinates can be set by copying Keen.io's existing co-ordinates into logstash's geoip.coordinates array.
input {
file {
path => ["data.json"]
start_position => beginning
type => json
}
}
filter {
json {
source => message
remove_field => message
add_tag => ["valid_json"]
}
if ("valid_json") {
if ("[result][0][keen][created_at]") {
date {
# Set #timestamp to Keen.io's "created_at" field
match => [ "[result][0][keen][created_at]", "ISO8601" ]
}
}
if ("[result][0][keen][location][coordinates]") {
mutate {
# Copy existing co-orndiates into geoip.coordinates array
add_field => [ "[geoip][coordinates]", "%{[result][0][keen][location][coordinates][0]}" ]
add_field => [ "[geoip][coordinates]", "%{[result][0][keen][location][coordinates][1]}" ]
remove_field => "[result][0][keen][location][coordinates]"
}
}
}
}
output {
stdout { codec => rubydebug }
}