Skip to content

Instantly share code, notes, and snippets.

@gregbuehler
Created November 16, 2019 01:29
Show Gist options
  • Save gregbuehler/06231646a38a1864c257b692eaa48b98 to your computer and use it in GitHub Desktop.
Save gregbuehler/06231646a38a1864c257b692eaa48b98 to your computer and use it in GitHub Desktop.
Slack New Relic NRQL Slash Command Endpoint
#!/usr/bin/env python
import os
import requests
import json
from datetime import datetime
from flask import Flask, jsonify, request
app = Flask(__name__)
def is_request_valid(request):
token = request.form.get('token', None)
team_id = request.form.get('team_id', None)
is_token_valid = (token != None) and (token == os.environ['SLACK_VERIFICATION_TOKEN'])
is_team_id_valid = (team_id != None) and (team_id == os.environ['SLACK_TEAM_ID'])
return is_token_valid and is_team_id_valid
def is_nrql_valid(nrql):
if nrql is None: return False
if "SELECT" not in nrql.upper(): return False
if "FROM" not in nrql.upper(): return False
return True
def guess_result_type(nrql):
if 'TIMESERIES' in nrql.upper(): return 'LINE'
return 'TABLE'
@app.route('/nrqlizer/slash-nrql', methods=['POST'])
def get_message():
if not is_request_valid(request):
return jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems with that.'
), 401
url = os.environ.get('NEWRELIC_GRAPHQL_ENDPOINT', 'https://api.newrelic.com/graphql')
account_id = request.form.get('newrelic_account', os.environ.get('NEWRELIC_ACCOUNT'))
api_key = request.form.get('newrelic_graphql_key', os.environ.get('NEWRELIC_GRAPHQL_KEY'))
nrql = request.form.get('text')
if not is_nrql_valid(nrql):
return jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems with that NRQL.'
), 400
result_type = guess_result_type(nrql)
try:
headers = {
'Content-Type': 'application/json',
'API-Key': api_key
}
query = f'''
{{
actor {{
account(id: {account_id}) {{
nrql(query: "{nrql}") {{
nrql
metadata {{
timeWindow {{
begin
end
}}
}}
staticChartUrl(chartType: {result_type}, format: PNG)
}}
}}
}}
}}
'''
r = requests.post(url, headers=headers, json={'query': query})
r.raise_for_status()
try:
data = r.json()
exec_nrql = data['data']['actor']['account']['nrql']['nrql']
chart_url = data['data']['actor']['account']['nrql']['staticChartUrl']
since = data['data']['actor']['account']['nrql']['metadata']['timeWindow']['begin'] / 1000
until = data['data']['actor']['account']['nrql']['metadata']['timeWindow']['end'] / 1000
since_utc = datetime.utcfromtimestamp(since)
until_utc = datetime.utcfromtimestamp(until)
return jsonify(
response_type='in_channel',
text=f'<{chart_url}|"{exec_nrql}", {since_utc}-{until_utc}>'
)
except Exception as e:
return jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems with that. {e}'
), r.status_code
jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems with that.'
), 400
except requests.HTTPError as e:
data = r.json()
errors = data.get('errors', [])
if len(errors) > 0:
return jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems with that. New Relic said "{e}"'
), r.status_code
return jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems with that.'
), r.status_code
except requests.Timeout as e:
return jsonify(
response_type='in_channel',
text=f'Sorry, but that query timed out.'
), 503
except requests.ConnectionError as e:
return jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems communicating with New Relic.'
), 503
except Exception as e:
return jsonify(
response_type='in_channel',
text=f'Sorry, but we had problems with that. {e}'
), 503
return jsonify(
response_type='in_channel',
text=f'<{chart_url}|{nrql}>'
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment