From 0e543f41877d2b00d8c26cf6d39acc7e3ca8ef1a Mon Sep 17 00:00:00 2001 From: peterdudfield Date: Tue, 28 Nov 2023 15:25:30 +0000 Subject: [PATCH] add user api page --- src/main.py | 2 + src/plots/users.py | 41 +++++++++++++++++++++ src/users.py | 77 +++++++++++++++++++++++++++++++++++++++ tests/plots/test_users.py | 13 +++++++ 4 files changed, 133 insertions(+) create mode 100644 src/plots/users.py create mode 100644 src/users.py create mode 100644 tests/plots/test_users.py diff --git a/src/main.py b/src/main.py index 6bf1891..9b00a36 100644 --- a/src/main.py +++ b/src/main.py @@ -28,6 +28,7 @@ from status import status_page from tables.raw import make_raw_table from tables.summary import make_recent_summary_stats, make_forecast_horizon_table +from users import user_page st.get_option("theme.primaryColor") st.set_page_config(layout="centered", page_title="OCF Dashboard") @@ -266,6 +267,7 @@ def metric_page(): "Forecast": forecast_page, "PV Site Forecast": pvsite_forecast_page, "Sites Toolbox": sites_toolbox_page, + "API Users": user_page, } demo_name = st.sidebar.selectbox("Choose a page", page_names_to_funcs.keys()) diff --git a/src/plots/users.py b/src/plots/users.py new file mode 100644 index 0000000..ff2f6b2 --- /dev/null +++ b/src/plots/users.py @@ -0,0 +1,41 @@ +import pandas as pd +from plotly import graph_objects as go + +from datetime import datetime + + +def make_api_requests_plot( + api_requests: pd.DataFrame, email_selected: str, end_time: datetime, start_time: datetime +): + """ + Make plot of API requests + + Parameters + ---------- + api_requests : pd.DataFrame, need to have columns "created_utc" and "url" + email_selected : str, email of user + end_time : datetime, end time of plot + start_time : datetime, start time of plot + + """ + + fig = go.Figure( + layout=go.Layout( + title=go.layout.Title( + text=f"Api requests for {email_selected} between {start_time} and {end_time}" + ), + xaxis=go.layout.XAxis(title=go.layout.xaxis.Title(text="Date")), + yaxis=go.layout.YAxis(title=go.layout.yaxis.Title(text="API request")), + legend=go.layout.Legend(title=go.layout.legend.Title(text="Chart Legend")), + ) + ) + fig.add_trace( + go.Scatter( + x=api_requests["created_utc"], + y=api_requests["url"], + mode="markers", + name="API requests", + ) + ) + fig.update_yaxes(visible=False) + return fig diff --git a/src/users.py b/src/users.py new file mode 100644 index 0000000..5d2262f --- /dev/null +++ b/src/users.py @@ -0,0 +1,77 @@ +import pandas as pd +import streamlit as st +from datetime import datetime, timedelta +import os +from nowcasting_datamodel.connection import DatabaseConnection +from nowcasting_datamodel.models.api import UserSQL, APIRequestSQL + +from plots.users import make_api_requests_plot + + +def user_page(): + + st.markdown( + f'

{"API Users Page"}

', + unsafe_allow_html=True, + ) + + st.text("See which users have been using the API") + + start_time = st.sidebar.date_input( + "Start Date", + min_value=datetime.today() - timedelta(days=365), + max_value=datetime.today(), + value=datetime.today() - timedelta(days=31), + ) + end_time = st.sidebar.date_input( + "End Date", min_value=datetime.today() - timedelta(days=365), max_value=datetime.today() + ) + + # get last call from the database + url = os.environ["DB_URL"] + connection = DatabaseConnection(url=url, echo=True) + with connection.get_session() as session: + + last_requests_sql = ( + session.query(APIRequestSQL) + .distinct(APIRequestSQL.user_uuid) + .join(UserSQL) + .order_by(APIRequestSQL.user_uuid, APIRequestSQL.created_utc.desc()) + .all() + ) + + last_request = [ + (last_request_sql.user.email, last_request_sql.created_utc) + for last_request_sql in last_requests_sql + ] + + last_request = pd.DataFrame(last_request, columns=["email", "last API reuqest"]) + last_request = last_request.sort_values(by="last API reuqest", ascending=False) + last_request.set_index("email", inplace=True) + + st.write(last_request) + + # add selectbox for users + email_selected = st.sidebar.selectbox("Select", last_request.index.tolist(), index=0) + + # get all calls for selected user + with connection.get_session() as session: + api_requests_sql = ( + session.query(APIRequestSQL) + .join(UserSQL) + .where(UserSQL.email == email_selected) + .where(APIRequestSQL.created_utc >= start_time) + .where(APIRequestSQL.created_utc <= end_time) + .all() + ) + + api_requests = [ + (api_request_sql.created_utc, api_request_sql.url) + for api_request_sql in api_requests_sql + ] + api_requests = pd.DataFrame(api_requests, columns=["created_utc", "url"]) + + fig = make_api_requests_plot(api_requests, email_selected, end_time, start_time) + st.plotly_chart(fig, theme="streamlit") + + diff --git a/tests/plots/test_users.py b/tests/plots/test_users.py new file mode 100644 index 0000000..687df1c --- /dev/null +++ b/tests/plots/test_users.py @@ -0,0 +1,13 @@ +from plots.users import make_api_requests_plot +import pandas as pd + +def test_make_api_requests_plot(): + + # create fake data + api_requests = pd.DataFrame( + { + "created_utc": ["2021-01-01", "2021-01-02", "2021-01-03"], + "url": ["https://api.solarforecastarbiter.org/", "https://api.solarforecastarbiter.org/", "https://api.solarforecastarbiter.org/"], + } + ) + _ = make_api_requests_plot(api_requests, "", "", "") \ No newline at end of file