diff --git a/README.md b/README.md index 3ecbb0a..e5a5788 100644 --- a/README.md +++ b/README.md @@ -961,6 +961,59 @@ $ Refer to the Cloudflare Workers API documentation for more information. +## Cloudflare GraphQL + +The GraphQL interface can be accessed via the command line or via Python. + +``` + query=""" + query { + viewer { + zones(filter: {zoneTag: "%s"} ) { + httpRequests1dGroups(limit:40, filter:{date_lt: "%s", date_gt: "%s"}) { + sum { countryMap { bytes, requests, clientCountryName } } + dimensions { date } + } + } + } + } + """ % (zone_id, date_before[0:10], date_after[0:10]) + + r = cf.graphql.post(data={'query':query}) + + httpRequests1dGroups = zone_info = r['data']['viewer']['zones'][0]['httpRequests1dGroups'] +``` + +See the [examples/example_graphql.sh](examples/example_graphql.sh) and [examples/example_graphql.py](examples/example_graphql.py) files for working examples. +Here is the working example of the shell version: + +``` +$ examples/example_graphql.sh example.com +2020-07-14T02:00:00Z 34880 +2020-07-14T03:00:00Z 18953 +2020-07-14T04:00:00Z 28700 +2020-07-14T05:00:00Z 2358 +2020-07-14T06:00:00Z 34905 +2020-07-14T07:00:00Z 779 +2020-07-14T08:00:00Z 35450 +2020-07-14T10:00:00Z 17803 +2020-07-14T11:00:00Z 32678 +2020-07-14T12:00:00Z 19947 +2020-07-14T13:00:00Z 4956 +2020-07-14T14:00:00Z 34585 +2020-07-14T15:00:00Z 3022 +2020-07-14T16:00:00Z 5224 +2020-07-14T18:00:00Z 79482 +2020-07-14T21:00:00Z 10609 +2020-07-14T22:00:00Z 5740 +2020-07-14T23:00:00Z 2545 +2020-07-15T01:00:00Z 10777 +$ +``` + +For more information on how to use GraphQL at Cloudflare, refer to the [Cloudflare GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api). +It contains a full overview of Cloudflare's GraphQL features and keywords. + ## Implemented API calls The **--dump** argument to cli4 will produce a list of all the call implemented within the library. diff --git a/README.rst b/README.rst index 01d7ede..da5ace4 100644 --- a/README.rst +++ b/README.rst @@ -1061,6 +1061,64 @@ state. Refer to the Cloudflare Workers API documentation for more information. +Cloudflare GraphQL +------------------ + +The GraphQL interface can be accessed via the command line or via +Python. + +:: + + query=""" + query { + viewer { + zones(filter: {zoneTag: "%s"} ) { + httpRequests1dGroups(limit:40, filter:{date_lt: "%s", date_gt: "%s"}) { + sum { countryMap { bytes, requests, clientCountryName } } + dimensions { date } + } + } + } + } + """ % (zone_id, date_before[0:10], date_after[0:10]) + + r = cf.graphql.post(data={'query':query}) + + httpRequests1dGroups = zone_info = r['data']['viewer']['zones'][0]['httpRequests1dGroups'] + +See the `examples/example\_graphql.sh `__ +and `examples/example\_graphql.py `__ files +for working examples. Here is the working example of the shell version: + +:: + + $ examples/example_graphql.sh example.com + 2020-07-14T02:00:00Z 34880 + 2020-07-14T03:00:00Z 18953 + 2020-07-14T04:00:00Z 28700 + 2020-07-14T05:00:00Z 2358 + 2020-07-14T06:00:00Z 34905 + 2020-07-14T07:00:00Z 779 + 2020-07-14T08:00:00Z 35450 + 2020-07-14T10:00:00Z 17803 + 2020-07-14T11:00:00Z 32678 + 2020-07-14T12:00:00Z 19947 + 2020-07-14T13:00:00Z 4956 + 2020-07-14T14:00:00Z 34585 + 2020-07-14T15:00:00Z 3022 + 2020-07-14T16:00:00Z 5224 + 2020-07-14T18:00:00Z 79482 + 2020-07-14T21:00:00Z 10609 + 2020-07-14T22:00:00Z 5740 + 2020-07-14T23:00:00Z 2545 + 2020-07-15T01:00:00Z 10777 + $ + +For more information on how to use GraphQL at Cloudflare, refer to the +`Cloudflare GraphQL Analytics +API `__. It +contains a full overview of Cloudflare's GraphQL features and keywords. + Implemented API calls --------------------- diff --git a/examples/example_graphql.py b/examples/example_graphql.py new file mode 100755 index 0000000..fa4bb51 --- /dev/null +++ b/examples/example_graphql.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +"""Cloudflare API code - example""" + +import os +import sys +import time +import datetime +import pytz + +sys.path.insert(0, os.path.abspath('..')) +import CloudFlare + +def now_iso8601_time(h_delta): + """Cloudflare API code - example""" + + t = time.time() - (h_delta * 3600) + r = datetime.datetime.fromtimestamp(int(t), tz=pytz.timezone("UTC")).strftime('%Y-%m-%dT%H:%M:%SZ') + return r + +def main(): + """Cloudflare API code - example""" + + # Grab the zone name + try: + zone_name = sys.argv[1] + params = {'name':zone_name, 'per_page':1} + except IndexError: + exit('usage: example_graphql zone') + + cf = CloudFlare.CloudFlare() + + # grab the zone identifier + try: + zones = cf.zones.get(params=params) + except CloudFlare.exceptions.CloudFlareAPIError as e: + exit('/zones.get %d %s - api call failed' % (e, e)) + except Exception as e: + exit('/zones - %s - api call failed' % (e)) + + date_before = now_iso8601_time(0) # now + date_after = now_iso8601_time(7 * 24) # 7 days worth + + zone_id = zones[0]['id'] + query=""" + query { + viewer { + zones(filter: {zoneTag: "%s"} ) { + httpRequests1dGroups(limit:40, filter:{date_lt: "%s", date_gt: "%s"}) { + sum { countryMap { bytes, requests, clientCountryName } } + dimensions { date } + } + } + } + } + """ % (zone_id, date_before[0:10], date_after[0:10]) # only use yyyy-mm-dd part for httpRequests1dGroups + + # query - always a post + try: + r = cf.graphql.post(data={'query':query}) + except CloudFlare.exceptions.CloudFlareAPIError as e: + exit('/graphql.post %d %s - api call failed' % (e, e)) + + ## only one zone, so use zero'th element! + zone_info = r['data']['viewer']['zones'][0] + + httpRequests1dGroups = zone_info['httpRequests1dGroups'] + + for h in sorted(httpRequests1dGroups, key=lambda v: v['dimensions']['date']): + result_date = h['dimensions']['date'] + result_info = h['sum']['countryMap'] + print(result_date) + for element in sorted(result_info, key=lambda v: -v['bytes']): + print(" %7d %7d %2s" % (element['bytes'], element['requests'], element['clientCountryName'])) + +if __name__ == '__main__': + main() + exit(0) + diff --git a/examples/example_graphql.sh b/examples/example_graphql.sh new file mode 100755 index 0000000..2e52f73 --- /dev/null +++ b/examples/example_graphql.sh @@ -0,0 +1,34 @@ +: + +# +# Show usage of GraphQL - see https://developers.cloudflare.com/analytics/graphql-api for all info +# + +# pass one argument - the zone +ZONEID=`cli4 name="$1" /zones | jq -r '.[].id'` +if [ "${ZONEID}" = "" ] +then + echo "$1: zone not found" 1>&2 + exit 1 +fi + +# Just query the last 24 hours +DATE_BEFORE=`date -u +%Y-%m-%dT%H:%M:%SZ` +DATE_AFTER=`date -u -v -24H +%Y-%m-%dT%H:%M:%SZ` + +# build the GraphQL query - this is just a simple example +QUERY=' + query { + viewer { + zones(filter: {zoneTag: "'${ZONEID}'"} ) { + httpRequests1hGroups(limit:100, orderBy:[datetime_ASC], filter:{datetime_gt:"'${DATE_AFTER}'", datetime_lt:"'${DATE_BEFORE}'"}) { + dimensions { datetime } + sum { bytes } + } + } + } + } +' + +# this not only does the query; but also drills down into the results to print the final data +cli4 --post query="${QUERY}" /graphql | jq -cr '.data.viewer.zones[]|.httpRequests1hGroups[]|.dimensions.datetime,.sum.bytes' | paste - -