Grafana: How to use the selected range of time in a query? - python

I'm using Grafana with JSON API data source and I'd like to build a query that depends on the selected period of time selected in the upper right corner of the screen.
Is there any variable (or something like that), which I can send the selected time range form Grafana and receive it in my backend?
In other words, If I select 24hs in Grafana I'd like to use that in my query and return only data in this period.
I tried to get request from Grafana, which should contain the time range. However I got error: Failed to decode JSON object: Expecting value: line 1 column 1 (char 0).
It's possible that I misunderstood something and it doesn't work that way.
This is my /query endpoint:
#app.route('/query', methods=['POST', 'GET'])
def query():
req = request.get_json() <- failed
range = req['request']['range']
json_data = get_from_database(range)
return json_data
Are there any other options, like sending the time range ( with these variables {__from}&to=${__to}) in URL?

You can use the global variables $__from and $__to. As explained in the docs, ${__from} will give you Unix millisecond epoch, but there are also other format options.
How to use variables in the JSON API plugin is explained in the docs. So you can either use them as params what will result in a URL like this /query?range_start=${__from}&range_end=${__to} or use them directly in your path like this /query/${__from}/${__to}.
For retrieving them using python: you will find a lot on that topic on SO. Basically, I think you don't need .get_json() (will not work if the request is not application/json). If you send them as params, use request.args.get('range_start') to get the value (short explanation).

Related

Hardcoding query params in python requests URL gives different result to key value pair in params

I am trying to use query parameters in an API. If I hardcode the query parameters, I get the expected results of top 2:
requests.get('https://someurl/Counties?$top=2')
But if I try
q = {"top":"2"}
requests.get('https://someurl/Counties', params=q)
I get the default response, with all items and not just the two first. When I try the same approach on a different API, both approaches work. The api uses Odata, if that matters. But I can't get my head around how these two should yield different results in the request that is posted.
I was just missing a dollar sign in front of top.
q = {"$top":"2"}

transform JSON file to be usable

Long story short, i get the query from spotify api which is JSON that has data about newest albums. How do i get the specific info from that like let's say every band name or every album title. I've tried a lot of ways to get that info that i found on the internet and nothing seems to work for me and after couple of hours im kinda frustrated
JSON data is on jsfiddle
here is the request
endpoint = "https://api.spotify.com/v1/browse/new-releases"
lookup_url = f"{endpoint}"
r = requests.get(lookup_url, headers=headers)
print(r.json())
you can find the
When you make this request like the comments have mentioned you get a dictionary which you can then access the keys and values. For example if you want to get the album_type you could do the following:
print(data["albums"]["items"][0]["album_type"])
Since items contains a list you would need to get the first values 0 and then access the album_type.
Output:
single
Here is a link to the code I used with your json.
I suggest you look into how to deal with json data in python, this is a good place to start.
I copied the data from the jsfiddle link.
Now try the following code:
import ast
pyobj=ast.literal_eval(str_cop_from_src)
later you can try with keys
pyobj["albums"]["items"][0]["album_type"]
pyobj will be a python dictionary will all data.

Looking for samples to multiple API calls in python

I am new and learning python. As part of my learning, i am trying to do Api integration. I am getting the result but it's limited to 100. But the totalresults is around 7000 records. Is there a way I can call multiple times to bring the entire result in CSV format. I am adding my code below and not sure how to proceed further.
import requests
import pandas as pd
resp = requests.get ('apipath' & '?company=XXXX', auth=(XXXXX', 'XXXXXX'))
dataframe = resp.json()
dataset = pd.DataFrame(dataframe["items"]).to_csv('dict_file.csv', header=True)
Please help.
You'll need to check the API Documentation but generally there will be a parameter "maxResults (or similar) that you can add to the url to retrieve more than the default number of results.
Your request (by modify the query string in the url) would look something like this:
resp = requests.get ('apipath' & '?company=XXXX&maxResults=1000', auth=(XXXXX', 'XXXXXX'))

Need to get or convert data from a site to be valid JSON

I am working on a script that will get data from a Website (Cisco Patches site) and based on the data received, I need to post it to another site (ServiceNow Event Management). The POST needs to be REST/JSON with specific keys for this to work.
I have enough code to GET the data and I have the code to POST working.
I am having a hard time with converting the data I get from GET to map it into valid JSON key value pairs to POST.
I am using the following code to get a list of new patches from Cisco website. I am getting the correct data but the format if the data is not how I can use it to post to another tool in JSON format (using different keys but values from the returned information.
This works -
def getjson(ciscourl):
response = urllib.request.urlopen(ciscourl)
ciscodata = response.read().decode("utf-8")
return json.loads(ciscodata)
The data I get back looks like below (this query resulted in 2 patches):
[{"identifier":"cisco-sa-20180521-cpusidechannel","title":"CPU Side-Channel Information Disclosure Vulnerabilities: May 2018","version":"1.5","firstPublished":"2018-05-22T01:00:00.000+0000","lastPublished":"2018-05-31T20:44:16.123+0000","workflowStatus":null,"id":1,"name":"Cisco Security Advisory","url":"https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20180521-cpusidechannel","severity":"Medium","workarounds":"No","cwe":null,"cve":"CVE-2018-3639,CVE-2018-3640","ciscoBugId":"","status":"Updated","summary":"On May 21, 2018, researchers disclosed two vulnerabilities that take advantage of the implementation of speculative execution of instructions on many modern microprocessor architectures to perform side-channel information disclosure attacks. These vulnerabilities could allow an unprivileged, ","totalCount":6,"relatedResource":[]},{"identifier":"cisco-sa-20180516-firepwr-pb","title":"Cisco Firepower Threat Defense Software Policy Bypass Vulnerability","version":"1.0","firstPublished":"2018-05-16T16:00:00.000+0000","lastPublished":"2018-05-16T16:00:00.000+0000","workflowStatus":null,"id":1,"name":"Cisco Security Advisory","url":"https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20180516-firepwr-pb","severity":"Medium","workarounds":"No","cwe":"CWE-693","cve":"CVE-2018-0297","ciscoBugId":"CSCvg09316","status":"New","summary":"A vulnerability in the detection engine of Cisco Firepower Threat Defense software could allow an unauthenticated, remote attacker to bypass a configured Secure Sockets Layer (SSL) Access Control (AC) policy to block SSL traffic.The vulnerability is due to the incorrect handling ","totalCount":6,"relatedResource":[]}]
I can extract values from this, as such print(jarray.get('identifier')) but I am having a hard time being able to map these values into my own JSON map with keys I define. So the value from the key identifier I got back, needs to map to a key called "node" in my JSON map.
I have tried json.loads, json.load, json.dump, json.dumps. Each time the error is Attribute Type error.
This is the code where I am confused:
def createJson(l):
#try:
jsonarray = l
o_source = "CiscoUpdatePatchChecker"
o_node = (jsonarray.get('identifier')) #this does not work
o_metric_name = ("Critical")
o_type = ("test")
o_resource = ("test_resource")
o_description = jsonarray #this works
o_event_class = ("test event class")
o_additional_info = jsonarray
print ("-" * 50)
print (o_source, o_node, o_metric_name, o_type, o_resource, o_description, o_event_class, o_additional_info)
print ("-" * 50)
data = {"source": o_source, "node": o_node, "metric_name": o_metric_name, "type": o_type, "resource": o_resource, "event_class": o_event_class, "description": o_description, "additional_info": o_additional_info}
return json.dumps(data)
# except:
#pass
Beyond this, the rest of the code just posts the data to ITSM which is working. -
def postjson(data):
# try:
url = posturl
auth = HTTPBasicAuth(username, password)
head = {'Content-type': 'application/json',
'Accept': 'application/json'}
payld = data
ret = requests.post(url, auth=auth , data=payld, headers=head)
# sys.stdout.write(ret.text)
returned_data = ret.json()
print(returned_data)
So my issue is to map data I am getting back to my keys:value pairs in a JSON map, & I will need to loop the code for as many times as the number of patches are retrieved. I am currently planning to loop in my main function for number of JSON maps that need to POST.
For now, I am just take all the data I get and mapping all the data I get to the "description" and "additional_info" field. This works and I can post the data fine.
It will help me tremendously if someone can point me to examples of how to manipulate the data I am getting from my GET request.
json.loads(ciscodata) returns an array of dictionaries.
The statement o_node = (jsonarray.get('identifier')) fails because it is trying to get a dictionary key when jsonarray is a list.
Try o_node = jsonarray[0].get('identifier')
I am not sure why you have parens around jsonarray -- those shouldn't be there.
In general, you can do something like:
for elem in jsonarray:
identifier = elem.get('identifier')
title = elem.get('title')
... etc
do_something(identifier, title, ...)
This makes it easier to debug because you can test the values you get back from the api call.
If you are always getting the same keys in your dictionary, you can skip this assignment and just do
for elem in jsonarray:
do_something(elem.get('key1'), elem.get('key2'), ...)`
Hope that helps

Django model request array

I am new to python and Django. I haven't found anything in documentations so I have to write here.
I have such problem.
I have cars table where you can find it's make, model. year and so on.
Usually i make request by just Cars.objects.filter(make=x, model=y, year=z)
I want to make search and all params are in array. There are many params and is it possible to make something like
Cars.objects.filter(array)
Ok. How i am getting my data. It is regular post form which I send by ajax to my view class. I have list of allowed params which can be found in users request. I have different names for tableview name and input name, but i have everything i need in prepared array. It can take user's sent car-name Acura and make something like {'make':123}. At the end i have an array which is fully compatible with my db {'make': 123, 'model':321}. Can i make a request using this array and not write by hands every param?
if arguments are stored in this format:
args = [('make', 'x'),('model', 'y'),('year', 'z')]
You can try:
arg_dict = dict(args)
Cars.objects.filter(**arg_dict)

Categories