Skip to content

Commit d642205

Browse files
committed
Refactor to use traitlets & classes
Start putting all the prometheus related stuff into one class that we can then configure with Traitlets. This moves us into being able to put all the AWS stuff into one class too, and then that is how we can make this generic enough for cloud providers
1 parent dfe2268 commit d642205

4 files changed

Lines changed: 380 additions & 412 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies = [
1313
"prometheus-client~=0.24",
1414
"requests>=2.32.4",
1515
"yarl>=1.20.1",
16+
"traitlets"
1617
]
1718

1819
[dependency-groups]

src/jupyterhub_cost_monitoring/app.py

Lines changed: 15 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from datetime import timedelta
22

33
import aiohttp
4-
import requests
54
from fastapi import FastAPI, HTTPException, Query
65
from fastapi.responses import Response
76
from prometheus_client import CONTENT_TYPE_LATEST, generate_latest
@@ -10,6 +9,7 @@
109
from .date_utils import get_now_date, parse_from_to_in_query_params
1110
from .logs import get_logger
1211
from .metrics import MetricsMiddleware
12+
from .prometheus import Prometheus
1313
from .query_cost_aws import (
1414
query_hub_names,
1515
query_total_costs,
@@ -18,17 +18,12 @@
1818
query_total_costs_per_hub,
1919
query_total_costs_per_user,
2020
)
21-
from .query_usage import (
22-
query_usage,
23-
query_user_groups,
24-
query_users_with_multiple_groups,
25-
query_users_with_no_groups,
26-
)
2721

2822
app = FastAPI()
2923
app.add_middleware(MetricsMiddleware)
3024
logger = get_logger(__name__)
3125
client_session = aiohttp.ClientSession()
26+
prometheus = Prometheus()
3227

3328

3429
@app.get("/")
@@ -98,7 +93,7 @@ def total_costs(
9893

9994

10095
@app.get("/user-groups")
101-
def user_groups(
96+
async def user_groups(
10297
hub: str | None = Query(None, description="Name of the hub to filter results"),
10398
username: str | None = Query(
10499
None, description="Name of the user to filter results"
@@ -111,19 +106,11 @@ def user_groups(
111106
Endpoint to serve user group memberships. Note that only the most recent date for each user group membership is returned.
112107
"""
113108

114-
try:
115-
return query_user_groups(hub, username, usergroup)
116-
except requests.exceptions.HTTPError as e:
117-
response = e.response
118-
raise HTTPException(
119-
status_code=response.status_code, detail=f"{response.text}"
120-
) from e
121-
except Exception as e:
122-
raise HTTPException(status_code=500, detail=f"{e}")
109+
return await prometheus.query_user_groups(hub, username, usergroup)
123110

124111

125112
@app.get("/users-with-multiple-groups")
126-
def users_with_multiple_groups(
113+
async def users_with_multiple_groups(
127114
hub_name: str | None = Query(None, description="Name of the hub to filter results"),
128115
user_name: str | None = Query(
129116
None, description="Name of the user to filter results"
@@ -141,19 +128,13 @@ def users_with_multiple_groups(
141128
from_date.isoformat(), to_date.isoformat()
142129
)
143130

144-
try:
145-
return query_users_with_multiple_groups(date_range, hub_name, user_name)
146-
except requests.exceptions.HTTPError as e:
147-
response = e.response
148-
raise HTTPException(
149-
status_code=response.status_code, detail=f"{response.text}"
150-
) from e
151-
except Exception as e:
152-
raise HTTPException(status_code=500, detail=f"{e}")
131+
return await prometheus.query_users_with_multiple_groups(
132+
date_range, hub_name, user_name
133+
)
153134

154135

155136
@app.get("/users-with-no-groups")
156-
def users_with_no_groups(
137+
async def users_with_no_groups(
157138
hub_name: str | None = Query(None, description="Name of the hub to filter results"),
158139
user_name: str | None = Query(
159140
None, description="Name of the user to filter results"
@@ -171,19 +152,11 @@ def users_with_no_groups(
171152
from_date.isoformat(), to_date.isoformat()
172153
)
173154

174-
try:
175-
return query_users_with_no_groups(date_range, hub_name, user_name)
176-
except requests.exceptions.HTTPError as e:
177-
response = e.response
178-
raise HTTPException(
179-
status_code=response.status_code, detail=f"{response.text}"
180-
) from e
181-
except Exception as e:
182-
raise HTTPException(status_code=500, detail=f"{e}") from e
155+
return await prometheus.query_users_with_no_groups(date_range, hub_name, user_name)
183156

184157

185158
@app.get("/total-costs-per-hub")
186-
def total_costs_per_hub(
159+
async def total_costs_per_hub(
187160
from_date: str | None = Query(
188161
None, alias="from", description="Start date in YYYY-MM-DDTHH:MMZ format"
189162
),
@@ -204,7 +177,7 @@ def total_costs_per_hub(
204177

205178

206179
@app.get("/total-costs-per-component")
207-
def total_costs_per_component(
180+
async def total_costs_per_component(
208181
from_date: str | None = Query(
209182
None, alias="from", description="Start date in YYYY-MM-DDTHH:MMZ format"
210183
),
@@ -234,7 +207,7 @@ def total_costs_per_component(
234207

235208

236209
@app.get("/total-costs-per-group")
237-
def total_costs_per_group(
210+
async def total_costs_per_group(
238211
from_date: str | None = Query(
239212
None, alias="from", description="Start date in YYYY-MM-DDTHH:MMZ format"
240213
),
@@ -248,13 +221,7 @@ def total_costs_per_group(
248221
# Parse and validate date parameters into DateRange object
249222
date_range = parse_from_to_in_query_params(from_date, to_date)
250223

251-
try:
252-
return query_total_costs_per_group(date_range)
253-
except requests.exceptions.HTTPError as e:
254-
response = e.response
255-
raise HTTPException(status_code=response.status_code, detail=response.text)
256-
except Exception as e:
257-
raise HTTPException(status_code=500, detail=f"{e}")
224+
return query_total_costs_per_group(date_range)
258225

259226

260227
@app.get("/costs-per-user")
@@ -354,13 +321,7 @@ async def total_usage(
354321
if not user or user.lower() == "all":
355322
user = None
356323

357-
try:
358-
return await query_usage(client_session, date_range, hub, component, user)
359-
except requests.exceptions.HTTPError as e:
360-
response = e.response
361-
raise HTTPException(status_code=response.status_code, detail=response.text)
362-
except Exception as e:
363-
raise HTTPException(status_code=500, detail=f"{e}")
324+
return await prometheus.query_usage(date_range, hub, component, user)
364325

365326

366327
@app.get("/metrics")

0 commit comments

Comments
 (0)