Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
adding newrelic query runner, only count supported in this commit
  • Loading branch information
mudasirmirza committed Feb 16, 2022
commit b6caffed5abf9ebda9b8f66a2854467dceeca864
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,9 @@ redis-cli:

bash:
docker-compose run --rm server bash

rebuild:
docker-compose build server
docker-compose build worker
docker-compose restart server
docker-compose restart worker
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"url": "git+https://github.com/getredash/redash.git"
},
"engines": {
"node": "^14.16.1",
"node": "^17.3.1",
"yarn": "^1.22.10"
},
"author": "Redash Contributors",
Expand Down
120 changes: 120 additions & 0 deletions redash/query_runner/newrelic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import json
import logging
from collections import OrderedDict
from urllib.parse import quote_from_bytes

from redash.query_runner import *
from redash.utils import json_dumps, json_loads


logger = logging.getLogger(__name__)

# TODO: make this more general and move into __init__.py
class ResultSet(object):
def __init__(self):
self.columns = OrderedDict()
self.rows = []

def add_row(self, row):
for key in row.keys():
self.add_column(key)

self.rows.append(row)

def add_column(self, column, column_type=TYPE_STRING):
if column not in self.columns:
self.columns[column] = {
"name": column,
"type": column_type,
"friendly_name": column,
}

def to_json(self):
return json_dumps({"rows": self.rows, "columns": list(self.columns.values())})

def merge(self, set):
self.rows = self.rows + set.rows


def parse_count(data):
nested_data = data.get("data").get("actor").get("account").get("nrql").get("results")[0]
logger.info(f"Data details, data: {data} -- data type: {type(data)}")
logger.info(f"Nested dictionay data: {nested_data} -- Nested Data Type: {type(nested_data)}")
key_name = list(nested_data.keys())[0]
data_count = list(nested_data.values())[0]
results = ResultSet()
results.add_row({key_name: data_count})
return results


class NewRelicGQL(BaseHTTPQueryRunner):
should_annotate_query = False
response_error = "NewRelic returned unexpected status code"


@classmethod
def configuration_schema(cls):
return {
"type": "object",
"properties": {
"nr_account_id": {"type": "string", "title": "NewRelic Account ID"},
"url": {"type": "string", "title": "API URL"},
"token": {"type": "string", "title": "Security Token"},
},
"required": ["nr_account_id", "url", "token"],
"secret": ["token"],
"order": [
"nr_account_id",
"url",
"token",
]
}


@classmethod
def name(cls):
return "NewRelic (GraphQL)"


def test_connection(self):
nr_account_id = str("{}".format(self.configuration["nr_account_id"]))
qraphql_test_query = '{actor {account(id: ' + nr_account_id +') {nrql(query: "SELECT 1") {results}}}}'
testQuery = {"queryType": "count", "query": qraphql_test_query}
try:
response = self.run_query(query=json.dumps(testQuery), user="test")
except Exception as err:
logger.info(f"Raised Exception: {err}")
if response is None:
raise Exception("Failed describing objects.")
pass

def run_query(self, query, user):
nr_url = "{}".format(self.configuration["url"])
nr_token = "{}".format(self.configuration["token"])
nr_account_id = "{}".format(self.configuration["nr_account_id"])
headers = {
"Content-Type": "application/json",
"API-Key": "{}".format(nr_token),
}

query = json_loads(query)
query_type = query.pop("queryType", "count")
nrql_query = query.pop("nrql", None)
if not nrql_query or not nr_account_id:
return None, None

qraphql_query = '{actor {account(id: ' + nr_account_id +') {nrql(query: "' + nrql_query + '") {results}}}}'
payload = {"query":qraphql_query}
response, error = self.get_response(nr_url, http_method="post", data=json.dumps(payload), headers=headers)

if error is not None:
return None, error
data = response.json()

if query_type == "count":
results = parse_count(data)

return results.to_json(), None


register(NewRelicGQL)
1 change: 1 addition & 0 deletions redash/settings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ def email_server_is_configured():
"redash.query_runner.mssql_odbc",
"redash.query_runner.memsql_ds",
"redash.query_runner.mapd",
"redash.query_runner.newrelic",
"redash.query_runner.jql",
"redash.query_runner.google_analytics",
"redash.query_runner.axibase_tsd",
Expand Down