Kibana - how to export search results - json

We've recently moved our centralized logging from Splunk to an ELK solution, and we have a need to export search results - is there a way to do this in Kibana 4.1? If there is, it's not exactly obvious...
Thanks!

This is very old post. But I think still someone searching for a good answer.
You can easily export your searches from Kibana Discover.
Click Save first, then click Share
Click CSV Reports
Then click Generate CSV
After a few moments, you'll get download option bottom right side.

This works with Kibana v 7.2.0 - export query results into a local JSON file. Here I assume that you have Chrome, similar approach may work with Firefox.
Chrome - open Developer Tools / Network
Kibana - execute your query
Chrome - right click on the network call and choose Copy / Copy as cURL
command line - execute [cURL from step 3] > query_result.json . The query response data is now stored in query_result.json
Edit: To drill down into the source nodes in the resulting JSON file using jq:
jq '.responses | .[] | .hits | .hits | .[]._source ' query_result.json

If you want to export the logs (not just the timestamp and counts), you have a couple of options (tylerjl answered this question very well on the Kibana forums):
If you're looking to actually export logs from Elasticsearch, you
probably want to save them somewhere, so viewing them in the browser
probably isn't the best way to view hundreds or thousands of logs.
There are a couple of options here:
In the "Discover" tab, you can click on the arrow tab near the bottom to see the raw request and response. You could click "Request"
and use that as a query to ES with curl (or something similar) to
query ES for the logs you want.
You could use logstash or stream2es206 to dump out the contents of a index (with possible query parameters to get the
specific documents you want.)

#Sean's answer is right, but lacks specifics.
Here is a quick-and-dirty script that can grab all the logs from ElasticSearch via httpie, parse and write them out via jq, and use a scroll cursor to iterate the query so that more than the first 500 entries can be captured (unlike other solutions on this page).
This script is implemented with httpie (the http command) and fish shell, but could readily be adapted to more standard tools like bash and curl.
The query is set as per #Sean's answer:
In the "Discover" tab, you can click on the arrow tab near the bottom
to see the raw request and response. You could click "Request" and
use that as a query to ES with curl (or something similar) to query ES
for the logs you want.
set output logs.txt
set query '<paste value from Discover tab here>'
set es_url http://your-es-server:port
set index 'filebeat-*'
function process_page
# You can do anything with each page of results here
# but writing to a TSV file isn't a bad example -- note
# the jq expression here extracts a kubernetes pod name and
# the message field, but can be modified to suit
echo $argv | \
jq -r '.hits.hits[]._source | [.kubernetes.pod.name, .message] | #tsv' \
>> $output
end
function summarize_string
echo (echo $argv | string sub -l 10)"..."(echo $argv | string sub -s -10 -l 10)
end
set response (echo $query | http POST $es_url/$index/_search\?scroll=1m)
set scroll_id (echo $response | jq -r ._scroll_id)
set hits_count (echo $response | jq -r '.hits.hits | length')
set hits_so_far $hits_count
echo "Got initial response with $hits_count hits and scroll ID "(summarize_string $scroll_id)
process_page $response
while test "$hits_count" != "0"
set response (echo "{ \"scroll\": \"1m\", \"scroll_id\": \"$scroll_id\" }" | http POST $es_url/_search/scroll)
set scroll_id (echo $response | jq -r ._scroll_id)
set hits_count (echo $response | jq -r '.hits.hits | length')
set hits_so_far (math $hits_so_far + $hits_count)
echo "Got response with $hits_count hits (hits so far: $hits_so_far) and scroll ID "(summarize_string $scroll_id)
process_page $response
end
echo Done!
The end result is all of the logs matching the query in Kibana, in the output file specified at the top of the script, transformed as per the code in the process_page function.

If you have troubles making your own request with curl or you don't need automatic program to extract logs from Kibana, just click 'Response' and get what you need.
After having troubles like 'xsrf token missing' when using curl,
I found this way is more easier and simple!
Like others said, Request button appears after clicking the arrow tab near the bottom.

Only the Timestamp and the count of messages at that time are exported, not the log information:
Raw:
1441240200000,1214
1441251000000,1217
1441261800000,1342
1441272600000,1452
1441283400000,1396
1441294200000,1332
1441305000000,1332
1441315800000,1334
1441326600000,1337
1441337400000,1215
1441348200000,12523
1441359000000,61897
Formatted:
"September 3rd 2015, 06:00:00.000","1,214"
"September 3rd 2015, 09:00:00.000","1,217"
"September 3rd 2015, 12:00:00.000","1,342"
"September 3rd 2015, 15:00:00.000","1,452"
"September 3rd 2015, 18:00:00.000","1,396"
"September 3rd 2015, 21:00:00.000","1,332"
"September 4th 2015, 00:00:00.000","1,332"
"September 4th 2015, 03:00:00.000","1,334"
"September 4th 2015, 06:00:00.000","1,337"
"September 4th 2015, 09:00:00.000","1,215"
"September 4th 2015, 12:00:00.000","12,523"
"September 4th 2015, 15:00:00.000","61,897"

Sure, you can export from Kibana's Discover (Kibana 4.x+).
1. On the discover page click the "up arrow" here:
Now, on the bottom of the page, you'll have two options to export search results
At logz.io (the company I work for), we'll be releasing scheduled reports based on specific searches.

Related

Zabbix api value is different from Graph value

i have zabbix 5. I've been trying to write a shell script to get item trend for a range of time. the shell script works correctly but the value it return doesn't match what is showing on graph.
for example:
I have an item with itemid "10234" which return "percentage of used CPU".
i want to get the zabbix trend for this item from "2021/09/20 09:00:00" till "2021/09/21 09:00:00".
Unix time for this rang is: 1632112200 , 1632198600
I run this command to get the values:
curl -L -k -i -X POST -H 'Content-Type:application/json' -d '{"jsonrpc":"2.0","method":"trend.get","id":1,"aut h":"1a543455bd48e6ddc222219acccb52e9","params" : {"output": ["clock","value_avg","value_min","value_max","num", "itemid"],"itemids":["10234"],"time_from": "1632112200","time_till": "1632198600", "limit": "1"}}' https://172.30.134.03:423//api_jsonrpc.php
output:
{"clock":"1632114000","value_avg":"14.968717529411 764","value_min":"12.683622999999997","value_max": "17.635707999999994"}
but in Graph it shows:
why this happens and how to fix it?
In most cases, the graphs apply approximations. If you zoom in, you should see the same data you get from the API. The most zoom you can apply is 1 minute, while the API will get you the exact point in time value.

jq skip the initial invalid string before every json objects and print the selected column

We are formatting our logs into structured logs(json) so that it's easy to ingest and process logs by ELK.
but with that every time we need to go to Kibana to see the logs whereas on the app console (Cloudfoundry console) the logs are not human readable.
The logs printed as series of below string:
cf logs <app_name> :
" 2020-07-02T11:15:09.21+0530 [APP/PROC/WEB/1] OUT { \"written_at\":\"2020-07-02T05:45:09.210Z\",\"written_ts\":626217332175001,\"tenant_id\":\"-\",\"
component_type\":\"application\",\"component_id\":\"29094be5-e8d6-4467-a230-11cbbb65a25b\",\"space_name\":\"prov_eu10_adev001\",\"component_name\":\"it-
co\",\"component_instance\":\"1\",\"organization_id\":\"3c93940f-0520-423e-a035-780c1c9be4f9\",\"correlation_id\":\"-\",\"organization_name\":\"cpi_adev
001_eu10_org\",\"space_id\":\"75efa1d1-1d35-4c7a-9ba7-df152151990d\",\"container_id\":\"10.0.137.112\",\"type\":\"log\",\"logger\":\"com.company.it.util.loc
k.db.DbLock\",\"thread\":\"app_snapshot_callbackMEDIUM54\",\"level\":\"INFO\",\"categories\":[],\"msg\":\"(unlock) Attempting to release lock snapshot-
app-mash-0\" }"
We would like to parse the above tail logs into a human-readable format where we are only interested in time and msg.
so the expected output is:
2020-07-02T11:15:09.21+0530 (unlock) Attempting to release lock snapshot-app-mash-0
cf logs <app_name> | jq 'filter?'
It would seem that the input is a valid JSON string, and therefore that invoking jq with the -r option and a filter such as the following should do the trick:
capture("^ *(?<date>[^ ]+) [^ ]+ [^ ]+ (?<json>.*)")
| "\(.date) \(.json|fromjson|.msg)"
Of course you may need to modify the regex argument of capture to match the actual lines in the log file.

I am using identical syntax in jq to change JSON values, yet one case works while other turns bash interactive, how can I fix this?

I am trying to update a simple JSON file (consists of one object with several key/value pairs) and I am using the same command yet getting different results (sometimes even having the whole json wiped with the 2nd command). The command I am trying is:
cat ~/Desktop/config.json | jq '.Option = "klay 10"' | tee ~/Desktop/config.json
This command perfectly replaces the value of the minerOptions key with "klay 10", my intended output.
Then, I try to run the same process on the newly updated file (just value is changed for that one key) and only get interactive terminal with no result. ps unfortunately isn't helpful in showing what's going on. This is what I do after getting that first command to perfectly change the value of the key:
cat ~/Desktop/config.json | jq ‘.othOptions = "-epool etc-eu1.nanopool.org:14324 -ewal 0xc63c1e59c54ca935bd491ac68fe9a7f1139bdbc0 -mode 1"' | tee ~/Desktop/config.json
which I would have expected would replace the othOptions key value with the assigned result, just as the last did. I tried directly sending the stdout to the file, but no result there either. I even tried piping one more time and creating a temp file and then moving it to change to original, all of these, as opposed to the same identical command, just return > and absolutely zero output; when I quit the process, it is the same value as before, not the new one.
What am I missing here that is causing the same command with just different inputs (the key in second comes right after first and has identical structure, it's not creating an object or anything, just key-val pair like first. I thought it could be tee but any other implementation like a passing of stdout to file produces the same constant > waiting for a command, no user.
I genuinely looked everywhere I could online for why this could be happening before resorting to SE, it's giving me such a headache for what I thought should be simple.
As #GordonDavisson pointed out, using tee to overwrite the input file is a (well-known - see e.g. the jq FAQ) recipe for disaster. If you absolutely positively want to overwrite the file unconditionally, then you might want to consider using sponge, as in
jq ... config.json | sponge config.json
or more safely:
cp -p config.json config.json.bak && jq ... config.json | sponge config.json
For further details about this and other options, search for ‘sponge’ in the FAQ.

Parsing json output for hive

I need to automatically move new cases (TheHive-Project) to LimeSurvey every 5 minutes. I have figured out the basis of the API script to add responses to LimeSurvey. However, I can't figure out how to add only new cases, and how to parse the Hive case data for the information I want to add.
So far I've been using curl to get a list of cases from hive. The following is the command and the output.
curl -su user:pass http://myhiveIPaddress:9000/api/case
[{"createdBy":"charlie","owner":"charlie","createdAt":1498749369897,"startDate":1498749300000,"title":"test","caseId":1,"user":"charlie","status":"Open","description":"testtest","tlp":2,"tags":[],"flag":false,"severity":1,"metrics":{"Time for Alert to Handler Pickup":2,"Time from open to close":4,"Time from compromise to discovery":6},"updatedBy":"charlie","updatedAt":1498751817577,"id":"AVz0bH7yqaVU6WeZlx3w","_type":"case"},{"createdBy":"charlie","owner":"charlie","title":"testtest","caseId":3,"description":"ddd","user":"charlie","status":"Open","createdAt":1499446483328,"startDate":1499446440000,"severity":2,"tlp":2,"tags":[],"flag":false,"id":"AV0d-Z0DqHSVxnJ8z_HI","_type":"case"},{"createdBy":"charlie","owner":"charlie","createdAt":1499268177619,"title":"test test","user":"charlie","status":"Open","caseId":2,"startDate":1499268120000,"tlp":2,"tags":[],"flag":false,"description":"s","severity":1,"metrics":{"Time from open to close":2,"Time for Alert to Handler Pickup":3,"Time from compromise to discovery":null},"updatedBy":"charlie","updatedAt":1499268203235,"id":"AV0TWOIinKQtYP_yBYgG","_type":"case"}]
Each field is separated by the delimiter },{.
In regards to parsing out specific information from each case, I previously tried to just use the cut command. This mostly worked until I reached "metrics"; it doesn't always work for metrics because they will not always be listed in the same order.
I have asked my boss for help, and he told me this command might get me going in the right direction to adding only new hive cases to the survey, but I'm still very lost and want to avoid asking too much again.
curl -su user:pass http://myhiveIPaddress:9000/api/case | sed 's/},{/\n/g' | sed 's/\[{//g' | sed 's/}]//g' | awk -F '"caseId":' {'print $2'} | cut -f 1 -d , | sort -n | while read line; do echo '"caseId":'$line; done
Basically, I'm in way over my head and feel like I have no idea what I'm doing. If I need to clarify anything, or if it would help for me to post what I have so far in my API script, please let me know.
Update
Here is the potential logic for the script I'd like to write.
get list of hive cases (curl ...)
read each field, delimited by },{
while read each field, check /tmp/addedHiveCases to see if caseId of field already exists
--> if it does not exist in file, add case to limesurvey and add caseId to /tmp/addedHiveCases
--> if it does exist, skip to next field
why are you thinking that the fields are separated by a "},{" delimiter?
The response of the /api/case API is a valid JSON format, that lists the cases.
Can you use a Python script to play with the API? If yes, I can help you write the script you need.

Is there a `jq` command line tool or wrapper which lets you interactively explore `jq` similar to `jmespath.terminal`

jq is a lightweight and flexible command-line JSON processor.
https://stedolan.github.io/jq/
Is there a jq command line tool or wrapper which lets you pipe output into it and interactively explore jq, with the JSON input in one pane and your interactively updating result in another pane, similar to jmespath.terminal ?
I'm looking for something similar to the JMESPath Terminal jpterm
"JMESPath exploration tool in the terminal"
https://github.com/jmespath/jmespath.terminal
I found this project jqsh but it's not maintained and it appears to produce a lot of errors when I use it.
https://github.com/bmatsuo/jqsh
I've used https://jqplay.org/ and it's a great web based jq learning tool. However, I want to be able to, in the shell, pipe the json output of a command into an interactive jq which allows me to explore and experiment with jq commands.
Thanks in advance!
I've been using jiq and I'm pretty happy with it.
https://github.com/fiatjaf/jiq
It's jid with jq.
You can drill down interactively by using jq filtering queries.
jiq uses jq internally, and it requires you to have jq in your PATH.
Using the aws cli
aws ec2 describe-regions --region-names us-east-1 us-west-1 | jiq
jiq output
[Filter]> .Regions
{
"Regions": [
{
"Endpoint": "ec2.us-east-1.amazonaws.com",
"RegionName": "us-east-1"
},
{
"Endpoint": "ec2.us-west-1.amazonaws.com",
"RegionName": "us-west-1"
}
]
}
https://github.com/simeji/jid
n.b. I'm not clear how strictly it follows jq syntax and feature set
You may have to roll-your-own.
Of course, jq itself is interactive in the sense that if you invoke it without specifying any JSON input, it will process STDIN interactively.
If you want to feed the same data to multiple programs, you could easily write your own wrapper. Over at github, there's a bash script named jqplay that has a few bells and whistles. For example, if the input command begins with | then the most recent result is used as input.
Example 1
./jqplay -c spark.json
Enter a jq filter (possibly beginning with "|"), or blank line to terminate:
.[0]
{"name":"Paddington","lovesPandas":null,"knows":{"friends":["holden","Sparky"]}}
.[1]
{"name":"Holden"}
| .name
"Holden"
| .[0:1]
"H"
| length
1
.[1].name
"Holden"
Bye.
Example 2
./jqplay -n
Enter a jq filter (possibly beginning and/or ending with "|"), or blank line to terminate:
?
An initial | signifies the filter should be applied to the previous jq
output.
A terminating | causes the next line that does not trigger a special
action to be appended to the current line.
Special action triggers:
:exit # exit this script, also triggered by a blank line
:help # print this help
:input PATHNAME ...
:options OPTIONS
:save PN # save the most recent output in the named file provided
it does not exist
:save! PN # save the most recent output in the named file
:save # save to the file most recently specified by a :save command
:show # print the OPTIONS and PATHNAMEs currently in effect
:! PN # equivalent to the sequence of commands
:save! PN
:input PN
? # print this help
# # ignore this line
1+2
3
:exit
Bye.
If you're using Emacs (or willing to) then JQ-mode allows you to run JQ filters interactively on the current JSON document buffer:
https://github.com/ljos/jq-mode
There is a new one: https://github.com/PaulJuliusMartinez/jless
JLess is a command-line JSON viewer designed for reading, exploring, and searching through JSON data.
JLess will pretty print your JSON and apply syntax highlighting.
Expand and collapse Objects and Arrays to grasp the high- and low-level structure of a JSON document. JLess has a large suite of vim-inspired commands that make exploring data a breeze.
JLess supports full text regular-expression based search. Quickly find the data you're looking for in long String values, or jump between values for the same Object key.