-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9706c52
commit 58095ce
Showing
8 changed files
with
224 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
name: Run Behave Tests | ||
name: Behave Tests | ||
|
||
on: | ||
push: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
name: Run Blackboard Session Tests | ||
name: Blackboard Session Tests | ||
|
||
on: | ||
push: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Update-Cumulative-Users | ||
on: | ||
schedule: | ||
- cron: "55 23 * * *" | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.9.x' | ||
|
||
- name: Install backend dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install -r requirements.txt | ||
- name: Run Analytics | ||
env: | ||
CLOUDFLARE_ZONE_TAG: ${{ secrets.CLOUDFLARE_ZONE_TAG }} | ||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | ||
run: | | ||
python analytics.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,3 +15,4 @@ frontend/.DS_Store | |
frontend/.DS_Store | ||
.DS_Store | ||
frontend/.DS_Store | ||
*.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import csv | ||
import os | ||
import requests | ||
import logging | ||
from datetime import datetime | ||
import matplotlib.dates as mdates | ||
from urllib3.util.retry import Retry | ||
from matplotlib import pyplot as plt | ||
from requests.adapters import HTTPAdapter | ||
|
||
# Configure logging | ||
logging.basicConfig(level=logging.INFO, | ||
format='%(asctime)s - %(levelname)s - %(message)s') | ||
|
||
|
||
class Config: | ||
API_TOKEN = os.environ.get('CLOUDFLARE_API_TOKEN') | ||
ZONE_TAG = os.environ.get('CLOUDFLARE_ZONE_TAG') | ||
RETRY_STRATEGY = Retry( | ||
total=3, | ||
status_forcelist=[429, 500, 502, 503, 504], | ||
allowed_methods=["HEAD", "GET", "OPTIONS", "POST"] | ||
) | ||
URL = 'https://api.cloudflare.com/client/v4/graphql/' | ||
|
||
|
||
def fetch_unique_visitors(api_token, zone_tag, date): | ||
""" | ||
Fetch unique visitors from the GraphQL API for a specific date. | ||
""" | ||
session = requests.Session() | ||
session.mount('https://', HTTPAdapter(max_retries=Config.RETRY_STRATEGY)) | ||
headers = { | ||
'Authorization': f'Bearer {api_token}', | ||
'Content-Type': 'application/json' | ||
} | ||
query = { | ||
"query": """ | ||
{ | ||
viewer { | ||
zones(filter: { zoneTag: "%s" }) { | ||
httpRequests1dGroups(limit: 100, filter: { date_geq: "%s" }) { | ||
sum { | ||
bytes | ||
} | ||
uniq { | ||
uniques | ||
} | ||
} | ||
} | ||
} | ||
} | ||
""" % (zone_tag, date) | ||
} | ||
|
||
try: | ||
response = session.post(Config.URL, headers=headers, json=query) | ||
response.raise_for_status() | ||
data = response.json() | ||
return data | ||
except requests.exceptions.HTTPError as errh: | ||
logging.error(f"Http Error: {errh}") | ||
except requests.exceptions.ConnectionError as errc: | ||
logging.error(f"Error Connecting: {errc}") | ||
except requests.exceptions.Timeout as errt: | ||
logging.error(f"Timeout Error: {errt}") | ||
except requests.exceptions.RequestException as err: | ||
logging.error(f"Error: {err}") | ||
|
||
|
||
def get_total_users(): | ||
""" | ||
Get the total number of users from the CSV file. | ||
""" | ||
total_users = 0 | ||
with open('unique_visitors.csv', 'r') as f: | ||
next(f) # Skip the header line | ||
for line in f: | ||
_, value = line.strip().split(',') | ||
total_users += int(value) | ||
return total_users | ||
|
||
|
||
def plot_total_users(): | ||
dates = [] | ||
cumulative_values = [] | ||
total = 0 | ||
|
||
with open('unique_visitors.csv', 'r') as file: | ||
csv_reader = csv.reader(file) | ||
next(csv_reader) # Skip the header | ||
for row in csv_reader: | ||
date = datetime.strptime(row[0], '%d %b %Y') | ||
value = int(row[1]) | ||
total += value # Cumulative sum | ||
dates.append(date) | ||
cumulative_values.append(total) | ||
|
||
plt.figure(figsize=(10, 6)) | ||
plt.plot(dates, cumulative_values, marker='o') | ||
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d %b %Y')) | ||
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=5)) | ||
plt.gcf().autofmt_xdate() # Rotation | ||
plt.xlabel('Date') | ||
plt.ylabel('Cumulative Unique Visitors') | ||
plt.title('Cumulative Unique Visitors Over Time') | ||
plt.grid(True) | ||
|
||
# Remove the existing file if it exists | ||
if os.path.exists('cumulative_unique_visitors.png'): | ||
os.remove('cumulative_unique_visitors.png') | ||
|
||
plt.savefig('cumulative_unique_visitors.png') | ||
|
||
|
||
def update_csv_with_visitors(api_token, zone_tag): | ||
try: | ||
date = datetime.today().strftime('%Y-%m-%d') | ||
visitors_data = fetch_unique_visitors(api_token, zone_tag, date) | ||
if visitors_data: | ||
visitors = visitors_data['data']['viewer']['zones'][0]['httpRequests1dGroups'][0]['uniq']['uniques'] | ||
logging.info(f"Unique visitors for {date}: {visitors}") | ||
|
||
# Adjust the date format to 'DD MMM YYYY' | ||
formatted_date = datetime.today().strftime('%d %b %Y').upper() | ||
|
||
# Check if today's date is already in the CSV | ||
with open('unique_visitors.csv', 'r+') as f: | ||
lines = f.readlines() | ||
last_line = lines[-1] if lines else '' | ||
if formatted_date in last_line: | ||
# Update the existing entry | ||
lines[-1] = f"{formatted_date},{visitors}\n" | ||
f.seek(0) | ||
f.writelines(lines) | ||
else: | ||
# Append the new entry | ||
f.write(f"\n{formatted_date},{visitors}") | ||
else: | ||
logging.error("No data received from API.") | ||
except Exception as e: | ||
logging.error(f"An error occurred: {e}") | ||
|
||
|
||
def main(): | ||
if not all([Config.API_TOKEN, Config.ZONE_TAG]): | ||
logging.error("Environment variables are missing.") | ||
return | ||
|
||
print(get_total_users()) | ||
plot_total_users() | ||
update_csv_with_visitors(Config.API_TOKEN, Config.ZONE_TAG) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
logging | ||
datetime | ||
matplotlib | ||
urllib3 | ||
requests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
timestamp,value | ||
18 DEC 2023,0 | ||
19 DEC 2023,0 | ||
20 DEC 2023,0 | ||
21 DEC 2023,0 | ||
22 DEC 2023,0 | ||
23 DEC 2023,0 | ||
24 DEC 2023,0 | ||
25 DEC 2023,0 | ||
26 DEC 2023,0 | ||
27 DEC 2023,0 | ||
28 DEC 2023,0 | ||
29 DEC 2023,0 | ||
30 DEC 2023,0 | ||
31 DEC 2023,0 | ||
1 JAN 2024,0 | ||
2 JAN 2024,0 | ||
3 JAN 2024,0 | ||
4 JAN 2024,0 | ||
5 JAN 2024,2 | ||
6 JAN 2024,80 | ||
7 JAN 2024,129 | ||
8 JAN 2024,170 | ||
9 JAN 2024,85 | ||
10 JAN 2024,78 | ||
11 JAN 2024,66 | ||
12 JAN 2024,71 | ||
13 JAN 2024,57 | ||
14 JAN 2024,48 | ||
15 JAN 2024,70 | ||
16 JAN 2024,45 | ||
17 JAN 2024,58 |