Skip to content

Commit c1eb2a3

Browse files
committed
Preliminary per-user statistics endpoint
1 parent 402831e commit c1eb2a3

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

api/simqueue/data_models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,8 @@ class Histogram(BaseModel):
452452
status: str
453453
scale: str
454454
max: int
455+
456+
457+
class UserStatistics(BaseModel):
458+
user: str
459+
jobs: int

api/simqueue/resources/statistics.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import asyncio
12
from typing import List
23
from datetime import date, timedelta
3-
from collections import defaultdict
4+
from collections import defaultdict, Counter
45
import logging
56
import numpy as np
67

7-
from fastapi import APIRouter, Query
8+
from fastapi import APIRouter, Depends, Query, HTTPException, status as status_codes
9+
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
810

911
from ..data_models import (
1012
DateRangeCount,
@@ -13,14 +15,17 @@
1315
QueueStatus,
1416
Histogram,
1517
ProjectStatus,
18+
UserStatistics,
1619
)
17-
from .. import db
20+
from .. import db, oauth
21+
1822
from ..globals import STANDARD_QUEUES
1923

2024

2125
logger = logging.getLogger("simqueue")
2226

2327
router = APIRouter()
28+
auth = HTTPBearer()
2429

2530

2631
def normalize_start_end(start: date = None, end: date = None):
@@ -293,3 +298,29 @@ async def resource_usage(start: date = None, end: date = None, interval: int = 7
293298
results.append(new_obj)
294299

295300
return results
301+
302+
303+
@router.get("/statistics/per-user", response_model=List[UserStatistics])
304+
async def resource_usage(
305+
start: date = None, end: date = None, token: HTTPAuthorizationCredentials = Depends(auth)
306+
):
307+
"""
308+
Statistics at the level of individual users (only accessible by platform administrators)
309+
"""
310+
user = await asyncio.create_task(oauth.User.from_token(token.credentials))
311+
if not user.is_admin:
312+
raise HTTPException(
313+
status_code=status_codes.HTTP_403_FORBIDDEN,
314+
detail="Only admins can access per-user statistics",
315+
)
316+
jobs = await db.query_jobs(
317+
status=["finished", "error"],
318+
date_range_start=start,
319+
date_range_end=end,
320+
size=100000,
321+
fields=["user_id"],
322+
)
323+
jobs_per_user = Counter(job["user_id"] for job in jobs)
324+
return [
325+
UserStatistics(user=user_name, jobs=count) for user_name, count in jobs_per_user.items()
326+
]

0 commit comments

Comments
 (0)