diff --git a/playbooks/openedx_native.yml b/playbooks/openedx_native.yml index bf6740bcee9..fd00627c26b 100644 --- a/playbooks/openedx_native.yml +++ b/playbooks/openedx_native.yml @@ -39,6 +39,7 @@ ECOMMERCE_ENABLE_COMPREHENSIVE_THEMING: false EDXAPP_ENABLE_MEMCACHE: true EDXAPP_ENABLE_ELASTIC_SEARCH: true + ENABLE_UPTIME_REPORT: true roles: - role: swapfile SWAPFILE_SIZE: 4GB @@ -107,3 +108,5 @@ - role: user_retirement_pipeline when: COMMON_RETIREMENT_SERVICE_SETUP - role: mfe_deployer + - role: uptime_report + when: ENABLE_UPTIME_REPORT diff --git a/playbooks/roles/uptime_report/defaults/main.yml b/playbooks/roles/uptime_report/defaults/main.yml new file mode 100644 index 00000000000..8d1d65049d5 --- /dev/null +++ b/playbooks/roles/uptime_report/defaults/main.yml @@ -0,0 +1,24 @@ +# +# Open edX Retirement Pipeline Configuration +# +# github: https://github.com/edx/configuration +# wiki: https://openedx.atlassian.net/wiki/display/OpenOPS +# code style: https://openedx.atlassian.net/wiki/display/OpenOPS/Ansible+Code+Conventions +# license: https://github.com/edx/configuration/blob/master/LICENSE.TXT +# +# +# Deploy uptime_report +# +# See documentation in README.rst + +# +# This file contains the variables you'll need to pass to the role, and some +# example values. + +uptime_report_script: "/edx/var/upload_uptime_report.py" +uptime_report_cron_job_days: 6 +uptime_report_cron_job_minutes: 0 +newrelic_query_key: "" +newrelic_query_api_url: "" +uptime_report_s3_bucket: "" +uptime_report_s3_bucket_folder: "" diff --git a/playbooks/roles/uptime_report/tasks/main.yml b/playbooks/roles/uptime_report/tasks/main.yml new file mode 100644 index 00000000000..06e31791fd2 --- /dev/null +++ b/playbooks/roles/uptime_report/tasks/main.yml @@ -0,0 +1,36 @@ +--- +# +# edX Configuration +# +# github: https://github.com/edx/configuration +# wiki: https://openedx.atlassian.net/wiki/display/OpenOPS +# code style: https://openedx.atlassian.net/wiki/display/OpenOPS/Ansible+Code+Conventions +# license: https://github.com/edx/configuration/blob/master/LICENSE.TXT +# +# +# +# Tasks for role uptime_report +# +# Overview: +# This role will be used to set up automatic querying of daily uptime reports +# and upload it onto an S3 bucket +# +# Example play: +# +# + +- name: Create python script to upload query and upload uptime reports + template: + dest: "{{ uptime_report_script }}" + src: "uptime_report_script.j2" + mode: 0755 + owner: root + group: root + +- name: Install cron job for automatically running the uptime report script + cron: + name: "Run uptime report script" + job: "{{ uptime_report_script }}" + hour: "{{ uptime_report_cron_job_days }}" + minute: "{{ uptime_report_cron_job_minutes }}" + day: "*" diff --git a/playbooks/roles/uptime_report/templates/uptime_report_script.j2 b/playbooks/roles/uptime_report/templates/uptime_report_script.j2 new file mode 100644 index 00000000000..716ff0abbf8 --- /dev/null +++ b/playbooks/roles/uptime_report/templates/uptime_report_script.j2 @@ -0,0 +1,59 @@ +#!/usr/bin/python + +import boto3 +import json +import datetime +from six.moves import urllib + +newrelic_query_key = '{{ newrelic_query_key }}' +newrelic_query_api_url = '{{ newrelic_query_api_url }}' +uptime_report_s3_bucket = '{{ uptime_report_s3_bucket }}' +uptime_report_s3_bucket_folder = '{{ uptime_report_s3_bucket_folder }}' +newrelic_monitor_name = 'https://{{ EDXAPP_SITE_NAME }}/' +aws_access_key_id = '{{ AWS_S3_LOGS_ACCESS_KEY_ID }}' +aws_secret_access_key = '{{ AWS_S3_LOGS_SECRET_KEY }}' + +nr_query = ("SELECT percentage(count(*), WHERE result = 'SUCCESS') as 'UPTIME' " + "FROM SyntheticCheck WHERE monitorName = '{0}' " + "FACET dateOf(timestamp), hourOf(timestamp) " + "SINCE '{1} 00:00:00' UNTIL '{2} 00:00:00' " + "LIMIT MAX") + +def get_uptime_data(date): + from_time = (date+datetime.timedelta(days=-1)).strftime("%Y-%m-%d") + to_time = date.strftime("%Y-%m-%d") + data = urllib.parse.urlencode({ + 'nrql': nr_query.format(newrelic_monitor_name, from_time, to_time) + }) + headers = {'X-Query-Key': newrelic_query_key, 'Accept': 'application/json'} + request = urllib.request.Request(newrelic_query_api_url+'?'+data, headers=headers) + + response = urllib.request.urlopen(request) + data = json.loads(response.read().decode('utf-8')) + response.close() + times = [] + + for facet in data['facets']: + date, time = facet['name'][0], facet['name'][1] + times.append({ + 'time': datetime.datetime.strptime('{0} {1}'.format(date, time), '%B %d, %Y %H:%M').strftime("%Y-%m-%d %H:%M"), + 'uptime_percentage': float(facet['results'][0]['result']), + }) + times = sorted(times, key=lambda x: x['time']) + return times + +def upload_to_s3(uptime_data, date): + filepath = 'uptime/' + if uptime_report_s3_bucket_folder: + filepath = '{0}{1}/'.format(filepath, uptime_report_s3_bucket_folder) + + filename = '{0}uptime-{1}.json'.format(filepath, (date+datetime.timedelta(days=-1)).strftime("%Y-%m-%d")) + uptime_data = json.dumps(uptime_data) + + s3_client = boto3.client('s3',aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key) + s3_client.put_object(Body=uptime_data, Bucket=uptime_report_s3_bucket, Key=filename) + +if __name__ == "__main__": + today = datetime.datetime.now() + uptime_data = get_uptime_data(today) + upload_to_s3(uptime_data, today)