I want to catch my exception with ELK but my exception is full of ( { [ . , \ / , " ' character. How can I index them in grok?
My log file:
Exception in *** CoreLevel*** occured.
Date&Time: 2018-01-21 09:52:20.744092
Root:
( ['MQROOT' : 0x7f0a902b2d80]
(0x01000000:Name ):Properties = ( ['MQPROPERTYPARSER' : 0x7f0a902bffa0]
(0x03000000:NameValue):MessageFormat = 'jms_text' (CHARACTER) )
(0x03000000:NameValue):MsgId = X'5059414d313339363131303234383030303238' (BLOB))
(0x01000000:Name ):usr = (
(0x03000000:NameValue):MessageName = 'SampleMessageName' (CHARACTER)
(0x03000000:NameValue):MsgVersion = 'V1' (CHARACTER)
)
)
)
*****************************************************************************************
*****************************************************************************************
ExceptionList:
( ['MQROOT' : 0x7f0a9072b350]
(0x01000000:Name):RecoverableException = (
(0x03000000:NameValue):File = '/build/slot1/S800_P/src/DataFlowEngine/PluginInterface/ImbJniNode.cpp' (CHARACTER)
(0x03000000:NameValue):Line = 1260 (INTEGER)
(0x03000000:NameValue):Text = 'Caught exception and rethrowing' (CHARACTER)
(0x01000000:Name ):Insert = (
(0x03000000:NameValue):Type = 14 (INTEGER)
)
(0x03000000:NameValue):Label = '' (CHARACTER)
(0x03000000:NameValue):Catalog = "BIPmsgs" (CHARACTER)
(0x03000000:NameValue):Severity = 3 (INTEGER)
(0x03000000:NameValue):Number = 4395 (INTEGER)
)
)
)
and I except to get this pattern into kibana
Exception in: CoreLevel,
Date&Time: 2018-01-21 09:52:20.744092
message:{
Root:".....",
ExceptionList:"......"
}
and this is my grok block that doesn't work
grok {
patterns_dir => "/etc/logstash/patterns/"
break_on_match => false
keep_empty_captures => true
match => {"message" => ["Exception in (?<msg_f> occured..) Date&Time: %{SYSLOGTIMESTAMP:timestamp}"]}
}
mutate {
gsub => ["message", "\n", ""]
}
I'd really appreciate if anyone could help me.
The date in your log is in ISO8601 format so it can be matched with TIMESTAMP_ISO8601 predefined pattern.
For lines after date & time, you can use (?m) to match multiline in your log with GREEDYDATA.
Following pattern will work,
Exception in \*\*\* %{WORD:Exception_in}.*\s*Date&Time: %{TIMESTAMP_ISO8601}(?m)%{GREEDYDATA}
It will output,
{
"Exception_in": [
[
"CoreLevel"
]
],
"TIMESTAMP_ISO8601": [
[
"2018-01-21 09:52:20.744092"
]
],
"YEAR": [
[
"2018"
]
],
"MONTHNUM": [
[
"01"
]
],
"MONTHDAY": [
[
"21"
]
],
"HOUR": [
[
"09",
null
]
],
"MINUTE": [
[
"52",
null
]
],
"SECOND": [
[
"20.744092"
]
],
"ISO8601_TIMEZONE": [
[
null
]
],
"GREEDYDATA": [
[
" \nRoot: \n ( ['MQROOT' : 0x7f0a902b2d80]\n (0x01000000:Name ):Properties = ( ['MQPROPERTYPARSER' : 0x7f0a902bffa0]\n (0x03000000:NameValue):MessageFormat = 'jms_text' (CHARACTER) )\n (0x03000000:NameValue):MsgId = X'5059414d313339363131303234383030303238' (BLOB))\n (0x01000000:Name ):usr = (\n (0x03000000:NameValue):MessageName = 'SampleMessageName' (CHARACTER)\n (0x03000000:NameValue):MsgVersion = 'V1' (CHARACTER)\n )\n )\n) \n***************************************************************************************** \n***************************************************************************************** \nExceptionList: \n( ['MQROOT' : 0x7f0a9072b350]\n (0x01000000:Name):RecoverableException = (\n (0x03000000:NameValue):File = '/build/slot1/S800_P/src/DataFlowEngine/PluginInterface/ImbJniNode.cpp' (CHARACTER)\n (0x03000000:NameValue):Line = 1260 (INTEGER)\n (0x03000000:NameValue):Text = 'Caught exception and rethrowing' (CHARACTER)\n (0x01000000:Name ):Insert = (\n (0x03000000:NameValue):Type = 14 (INTEGER)\n )\n (0x03000000:NameValue):Label = '' (CHARACTER)\n (0x03000000:NameValue):Catalog = "BIPmsgs" (CHARACTER)\n (0x03000000:NameValue):Severity = 3 (INTEGER)\n (0x03000000:NameValue):Number = 4395 (INTEGER)\n )\n )\n)"
]
]
}
You can test it here
Related
In Python, we can do this.
board = {'us': {'name': 'USA', 'govern': 'good'},
'canada': {'name': 'Canada', 'govern': 'good'},
'uk': {'name': 'UK', 'govern': 'good', 'recruit': 3},
'spain': {'name': 'Spain', 'govern': 'good', 'schengen': True, 'recruit': 2},
'france': {'name': 'France', 'govern': 'good', 'schengen': True, 'recruit': 2},
'italy': {'name': 'italy', 'govern': 'good', 'schengen': True} }
to create a dictionary of name value pairs for easy lookup.
Can I the the same in Stanza language, like:
deftype Countries <: Table<String,Table<String,?>>
; value could be anything. we see Int|String|True|False here
val board : Countries = to-table( "us" => ( "name" => "USA", "govern" => "good" ), ....)
?
The closest data structure to a python dictionary in stanza is Hashtable, from collections. You can do something like :
; to-hashtable<K,V> can be found in collections, too!
val board = to-hashtable<String, HashTable<String, ?>> $ [
"us" => to-hashtable<String, ?> $ [
"name" => "USA"
],
"fr" => to-hashtable<String, ?> $ [
"name" => "France"
]
; .. etc ...
]
println(board["us"])
This will output :
HashTable(
"name" => "USA")
deftype Countries <: Table<...> doesn't create an alias for Table, it declares a new type. In order to use it like a table, you would need to implement the required methods for Table.
But normally we like to add more type information, not less!
defenum Government :
Democracy
Republic
Monarchy
defstruct Country :
name:String,
gov:Government
; ... etc ...
val board = to-hashtable<String,Country> $ [
"us" => Country(name, gov) where :
val name = "USA"
val gov = Republic
"fr" => Country(name, gov) where :
val name = "France"
val gov = Republic
]
I kind of come up with a solution:
defpackage labyrinth :
import core
import collections
deftype Countries <: HashTable<String,?>
defn print-deep ( xs : HashTable<String,?> ) :
for x in xs do :
val k = key(x)
val v = value(x)
print("%_ => " % [k])
match(v):
(v: HashTable<String,?>) : (print("[ "), print-deep(v), println("]"))
(v) : ( print(v), print(", ") )
defn to-hashtable ( t : HashTable<String,?>, kvs : Tuple<KeyValue<?,?>> ) -> False :
for kv in kvs do :
val k = key(kv)
val v = value(kv)
match(k) :
(k : String) :
if v is Tuple<?> :
var d : HashTable<String,?> = HashTable<String,?>()
to-hashtable(d, v)
set(t, k, d)
else :
t[k] = v
defn to-countries ( kvs : Tuple<KeyValue<String,?>> ) -> HashTable<String,?> :
val t : HashTable<String,?> = HashTable<String,?>()
to-hashtable(t, kvs)
t
defn test () -> HashTable<String,?> :
val c : Tuple<KeyValue<String,?>> =
[ "us" => ["name" => "us", "govern" => "good"]
"canada" => [ "name" => "Canada" "govern" => "good" ]
"uk" => [ "name" => "UK" "govern" => "good" "recruit" => 3 ]
"spain" => [ "name" => "Spain" "govern" => "good" "schengen" => true "recruit" => 2 ]
"france" => [ "name" => "France" "govern" => "good" "schengen" => true "recruit" => 2 ]
"italy" => [ "name" => "italy" "govern" => "good" "schengen" => true ]
]
val countries = to-countries(c)
countries
val board = test()
print-deep(board)
I have data file site24x7IPs.json, it looks like below:
{
"LocationDetails": [
{
"IPv6_Address_External": "2803:eb80:4000:d::0/64",
"City": "Buenos Aires",
"Place": "Argentina",
"external_ip": "170.78.75.88"
},
{
"IPv6_Address_External": "",
"City": "Buenos Aires",
"Place": "Argentina",
"external_ip": "170.78.75.87"
},
{
"IPv6_Address_External": "",
"City": "Melbourne",
"Place": "Australia",
"external_ip": "103.91.166.0/24"
},
{
"IPv6_Address_External": "2400:fa80:5:9:d68e:c0c1:fced:a31a",
"City": "Perth",
"Place": "Australia",
"external_ip": "103.77.234.74"
}
]
}
Below is part of my terraform main.tf
locals {
site24x7IPs = jsondecode(file("${path.module}/site24x7IPs.json"))
}
locals {
ipList = [for i in local.site24x7IPs.LocationDetails: i.external_ip if i.Place == "Australia"]
cidrList = [ for j in local.ipList: length(regexall("/", j)) <= 0 : "${j}/32" : j ]
}
My expectation:
cidrList = [ "103.91.166.0/24", "103.77.234.74/32" ]
Error:
Error: Invalid 'for' expression
on main.tf line 7, in locals: 7: cidrList = [ for j in
local.ipList: length(regexall("/", j)) <= 0 : "${j}/32" : j ]
Extra characters after the end of the 'for' expression.
Update:
The correct syntax is:
cidrList = [ for j in local.ipList:
length(regexall("/", j)) <= 0 ? "${j}/32" : j ]
but you are using double :, instead of ? and ':'.
Previous answer
Not sure what exactly are you trying to achieve, it seems to be that you are after something as follows:
cidrList = [ for j in local.ipList:
{"${j}/32" : j } if length(regexall("/", j)) <= 0 ]
which would give:
[
{
"103.77.234.74/32" = "103.77.234.74"
},
]
or
cidrList = [ for j in local.ipList:
"${j}/32" if length(regexall("/", j)) <= 0 ]
which gives:
[
"103.77.234.74/32",
]
I have the issue that I'm not able to execute the following code. The syntax seems to be okay, but when I try to execute it, I get the response, that:
Expression.Error: We cannot convert a value of type Record to type "Text".
Details:
Value=[Record]
Type=[Type]
let
body="{
""page"": ""1"",
""pageSize"": ""100"",
""requestParams"": {
""deviceUids"": [
""xxx-yyy-xxx-yyyy-xxxx"",
""yyy-xxx-yyy-xxxx-yyyy"",
""aaa-bbb-aaa-bbbb-aaaa"",
""ccc-ddd-ccc-dddd-cccc""
],
""entityColumns"": [
{
""entityId"": ""144"",
""joinColumnName"": ""device_uid"",
""columnName"": ""device_random_date""
}
],
""columnNames"": [
""ts"",
""device_uid"",
""1"",
""32"",
""55"",
""203"",
""204""
],
""startUnixTsMs"": ""1583413637000"",
""endUnixTsMs"": ""1583413640000"",
""columnFilters"": [
{
""filterType"": ""eq"",
""columnName"": ""55"",
""value"": ""1234""
}
],
""sortOrder"": [
{
""column"": ""ts"",
""order"": ""DESC""
},
{
""column"": ""55"",
""order"": ""ASC""
}
],
""entityFilters"": [
{
""entityId"": ""144"",
""entityEntryIds"": [
""12345-221-232-1231-123456""
]
}
]
}
}",
Parsed_JSON = Json.Document(body),
BuildQueryString = Uri.BuildQueryString(Parsed_JSON),
Quelle = Json.Document(Web.Contents("http://localhost:8101/device-data-reader-api/read-paginated/xxx-xxx-yyyy-yyyy", [Headers=[#"Content-Type"="application/json"], Content = Text.ToBinary(BuildQueryString)]))
in
Quelle
I tried to remove the quotes of the numbers, but this leads to the same issue, as system complains it cannot convert numbers into text.
I need the body which needs to be handed over with the request in order to do a POST request. What I'm doing wrong?
Since you seem to want to send this as application/json, I think you would change this bit in your code:
Content = Text.ToBinary(BuildQueryString)
to:
Content = Text.ToBinary(body)
and then you'd also get rid of the lines below (since you don't need them):
Parsed_JSON = Json.Document(body),
BuildQueryString = Uri.BuildQueryString(Parsed_JSON),
I don't think you would need Uri.BuildQueryString unless you wanted to send as application/x-www-form-urlencoded (i.e. URL encoded key-value pairs).
Unrelated: If it helps, you can build the structure in M and then use JSON.FromValue to turn the structure into bytes which can be put directly into the POST body. Untested example is below.
let
body = [
page = "1",
pageSize = "100",
requestParams = [
deviceUids = {
"xxx-yyy-xxx-yyyy-xxxx",
"yyy-xxx-yyy-xxxx-yyyy",
"aaa-bbb-aaa-bbbb-aaaa",
"ccc-ddd-ccc-dddd-cccc"
},
entityColumns = {
[
entityId = "144",
joinColumnName = "device_uid",
columnName = "device_random_date"
]
},
columnNames = {
"ts",
"device_uid",
"1",
"32",
"55",
"203",
"204"
},
startUnixTsMs = "1583413637000",
endUnixTsMs = "1583413640000",
columnFilters = {
[
filterType = "eq",
columnName = "55",
value = "1234"
]
},
sortOrder = {
[
column = "ts",
order = "DESC"
],
[
column = "55",
order = "ASC"
]
},
entityFilters = {
[
entityId = "144",
entityEntryIds = {
"12345-221-232-1231-123456"
}
]
}
]
],
Quelle = Json.Document(
Web.Contents(
"http://localhost:8101/device-data-reader-api/read-paginated/xxx-xxx-yyyy-yyyy",
[
Headers = [#"Content-Type" = "application/json"],
Content = Json.FromValue(body)
]
)
)
in
Quelle
It might look a little weird (since M uses [] instead of {}, {} instead of [] and = instead of :), but just mentioning in case it helps.
I have a List of Map with nested Map as well as below :-
def list = [
[
"description": "The issue is open and ready for the assignee to start work on it.",
"id": "1",
"name": "Open",
"statusCategory": [
"colorName": "blue-gray",
"id": 2,
"key": "new",
"name": "To Do",
]
],
[
"description": "This issue is being actively worked on at the moment by the assignee.",
"id": "3",
"name": "In Progress",
"statusCategory": [
"colorName": "yellow",
"id": 4,
"key": "indeterminate",
"name": "In Progress",
]
]
]
I have a task to get List of subMap with nested subMap. I'm doing some thing like as below :-
def getSubMap = { lst ->
lst.findResults { it.subMap(["id", "name", "statusCategory"])}
}
println getSubMap(list)
But its give me output as below :-
[
[
"id":1,
"name":"Open",
"statusCategory":[
"colorName":"blue-gray",
"id":2,
"key":"new",
"name":"To Do"
]
],
[
"id":"3",
"name":"In Progress",
"statusCategory":[
"colorName":"yellow",
"id":"4",
"key":"indeterminate",
"name":"In Progress"
]
]
]
As you can see I'm unable to get subMap of statusCategory key Map. Actually I want to get further subMap for nested Maps something like as below :-
[
[
"id":1,
"name":"Open",
"statusCategory":[
"id":"2",
"name":"To Do"
]
],
[
"id":"3",
"name":"In Progress",
"statusCategory":[
"id":"4",
"name":"In Progress"
]
]
]
To achieve this I'm trying as below :-
def getSubMap = { lst ->
lst.findResults { it.subMap(["id", "name", "statusCategory":["id","name"]])}
}
def modifiedList = getSubMap(list)
But it throws me Excpetion. And If I'm doing as below :-
def getSubMap = { lst ->
lst.findResults { it.subMap(["id", "name", "statusCategory"]).statusCategory.subMap(["id","name"])}
}
println getSubMap(list)
It gives only nested subMap as :-
[["id":"2", "name":"To Do"], ["id":"4", "name":"In Progress"]]
could anyone suggest me how to recurselvely find List of subMap with nested subMap if exist?
If your Map nesting is arbitrary, then you might want to consider something like this:
def nestedSubMap
nestedSubMap = { Map map, List keys ->
map.subMap(keys) + map.findAll { k, v -> v instanceof Map }.collectEntries { k, v -> [(k):nestedSubMap(v, keys)] }
}
Given your input and this closure, the following script:
def result = list.collect { nestedSubMap(it, ["id", "name"]) }
println '['
result.each { print it; println ',' }
println ']'
Produces this output:
[
[id:1, name:Open, statusCategory:[id:2, name:To Do]],
[id:3, name:In Progress, statusCategory:[id:4, name:In Progress]],
]
Given the original list, consider this:
def resultList = list.collect {
def fields = ["id", "name"]
def m = it.subMap(fields)
m["statusCategory"] = it["statusCategory"].subMap(fields)
return m
}
which supports these assertions:
assert 1 == resultList[0]["id"] as int
assert "Open" == resultList[0]["name"]
assert 2 == resultList[0]["statusCategory"]["id"] as int
assert "To Do" == resultList[0]["statusCategory"]["name"]
assert 3 == resultList[1]["id"] as int
assert "In Progress" == resultList[1]["name"]
assert 4 == resultList[1]["statusCategory"]["id"] as int
assert "In Progress" == resultList[1]["statusCategory"]["name"]
Does anyone have any sample Groovy code to convert a JSON document to CSV file? I have tried to search on Google but to no avail.
Example input (from comment):
[ company_id: '1',
web_address: 'vodafone.com/',
phone: '+44 11111',
fax: '',
email: '',
addresses: [
[ type: "office",
street_address: "Vodafone House, The Connection",
zip_code: "RG14 2FN",
geo: [ lat: 51.4145, lng: 1.318385 ] ]
],
number_of_employees: 91272,
naics: [
primary: [
"517210": "Wireless Telecommunications Carriers (except Satellite)" ],
secondary: [
"517110": "Wired Telecommunications Carriers",
"517919": "Internet Service Providers",
"518210": "Web Hosting"
]
]
More info from an edit:
def export(){
def exportCsv = [ [ id:'1', color:'red', planet:'mars', description:'Mars, the "red" planet'],
[ id:'2', color:'green', planet:'neptune', description:'Neptune, the "green" planet'],
[ id:'3', color:'blue', planet:'earth', description:'Earth, the "blue" planet'],
]
def out = new File('/home/mandeep/groovy/workspace/FirstGroovyProject/src/test.csv')
exportCsv.each {
def row = [it.id, it.color, it.planet,it.description]
out.append row.join(',')
out.append '\n'
}
return out
}
Ok, how's this:
import groovy.json.*
// Added extra fields and types for testing
def js = '''{"infile": [{"field1": 11,"field2": 12, "field3": 13},
{"field1": 21, "field4": "dave","field3": 23},
{"field1": 31,"field2": 32, "field3": 33}]}'''
def data = new JsonSlurper().parseText( js )
def columns = data.infile*.keySet().flatten().unique()
// Wrap strings in double quotes, and remove nulls
def encode = { e -> e == null ? '' : e instanceof String ? /"$e"/ : "$e" }
// Print all the column names
println columns.collect { c -> encode( c ) }.join( ',' )
// Then create all the rows
println data.infile.collect { row ->
// A row at a time
columns.collect { colName -> encode( row[ colName ] ) }.join( ',' )
}.join( '\n' )
That prints:
"field3","field2","field1","field4"
13,12,11,
23,,21,"dave"
33,32,31,
Which looks correct to me