Skip to content
Snippets Groups Projects

Resolve "Endpoint for developer statistics"

Merged Daniel Göbel requested to merge feature/62-endpoint-for-developer-statistics into development
17 files
+ 739
103
Compare changes
  • Side-by-side
  • Inline
Files
17
from datetime import date
from typing import Annotated, Any, Awaitable, Callable, List, Optional, Set
from uuid import UUID
@@ -12,6 +13,7 @@ from app.crud import CRUDWorkflow, CRUDWorkflowVersion
from app.crud.crud_workflow_mode import CRUDWorkflowMode
from app.git_repository import GitHubRepository, build_repository
from app.schemas.workflow import WorkflowIn, WorkflowOut, WorkflowStatistic, WorkflowUpdate
from app.schemas.workflow_execution import AnonymizedWorkflowExecution
from app.schemas.workflow_version import WorkflowVersion as WorkflowVersionSchema
from app.scm import SCM, Provider
from app.utils.otlp import start_as_current_span_async
@@ -71,11 +73,11 @@ async def list_workflows(
Workflows in the system
"""
current_span = trace.get_current_span()
if developer_id is not None:
if developer_id is not None: # pragma: no cover
current_span.set_attribute("developer_id", developer_id)
if name_substring is not None: # pragma: no cover
current_span.set_attribute("name_substring", name_substring)
if version_status is not None and len(version_status) > 0:
if version_status is not None and len(version_status) > 0: # pragma: no cover
current_span.set_attribute("version_status", [stat.name for stat in version_status])
rbac_operation = "list"
if developer_id is not None and current_user.uid != developer_id:
@@ -189,6 +191,70 @@ async def create_workflow(
return WorkflowOut.from_db_workflow(await CRUDWorkflow.get(db, workflow_db.workflow_id))
@router.get("/developer_statistics", status_code=status.HTTP_200_OK, summary="Get anonymized workflow execution")
@start_as_current_span_async("api_workflow_get_developer_statistics", tracer=tracer)
async def get_developer_workflow_statistics(
db: DBSession,
authorization: Authorization,
response: Response,
current_user: CurrentUser,
developer_id: Optional[str] = Query(
None,
description="Filter by the developer of the workflows",
examples=["28c5353b8bb34984a8bd4169ba94c606"],
min_length=3,
max_length=64,
),
workflow_ids: Optional[List[UUID]] = Query(None, description="Filter by workflow IDs", alias="workflow_id"),
start: Optional[date] = Query(None, description="Filter by workflow executions after this date"),
end: Optional[date] = Query(None, description="Filter by workflow executions before this date"),
) -> List[AnonymizedWorkflowExecution]:
"""
Get the workflow executions with meta information and anonymized user IDs.\n
Permission "workflow:read_statistics" required if the `developer_id` is the same as the uid of the current user,
other "workflow:read_statistics_any".
\f
Parameters
----------
db : sqlalchemy.ext.asyncio.AsyncSession.
Async database session to perform query on. Dependency Injection.
authorization : Callable[[str], Awaitable[Any]]
Async function to ask the auth service for authorization. Dependency Injection.
response : fastapi.Response
Temporary Response object. Dependency Injection.
current_user : clowmdb.models.User
Current user. Dependency Injection.
developer_id : str | None, default None
Filter for workflows developed by a specific user. Query Parameter.
workflow_ids: List[uuid.UUID] | None, default None
Filter by workflow IDs. Query Parameter.
start : datetime.date | None, default None
Filter by executions that started after the specified date. Query Parameter.
end : datetime.date | None, default None
Filter by executions that started before the specified date. Query Parameter.
Returns
-------
statistics : List[app.schema.workflow.AnonymizedWorkflowExecution]
List of raw datapoints for analysis.
"""
span = trace.get_current_span()
if developer_id: # pragma: no cover
span.set_attribute("developer_id", developer_id)
if workflow_ids: # pragma: no cover
span.set_attribute("workflow_ids", [str(wid) for wid in workflow_ids])
if start: # pragma: no cover
span.set_attribute("start_day", start.isoformat())
if end: # pragma: no cover
span.set_attribute("end_day", end.isoformat())
await authorization("read_statistics" if current_user.uid == developer_id else "read_statistics_any")
# Instruct client to cache response for 1 hour
response.headers["Cache-Control"] = "max-age=3600"
return await CRUDWorkflow.developer_statistics(
db, developer_id=developer_id, workflow_ids=workflow_ids, start=start, end=end
)
@router.get("/{wid}", status_code=status.HTTP_200_OK, summary="Get a workflow")
@start_as_current_span_async("api_workflow_get", tracer=tracer)
async def get_workflow(
@@ -203,7 +269,7 @@ async def get_workflow(
) -> WorkflowOut:
"""
Get a specific workflow.\n
Permission "workflow: read" required.
Permission "workflow:read" required.
\f
Parameters
----------
@@ -225,7 +291,7 @@ async def get_workflow(
"""
current_span = trace.get_current_span()
current_span.set_attribute("workflow_id", str(workflow.workflow_id))
if version_status is not None and len(version_status) > 0:
if version_status is not None and len(version_status) > 0: # pragma: no cover
current_span.set_attribute("version_status", [stat.name for stat in version_status])
rbac_operation = "read_any" if workflow.developer_id != current_user.uid and version_status is not None else "read"
await authorization(rbac_operation)
@@ -244,7 +310,8 @@ async def get_workflow_statistics(
workflow: CurrentWorkflow, db: DBSession, authorization: Authorization, response: Response
) -> List[WorkflowStatistic]:
"""
Get the number of started workflow per day.
Get the number of started workflow per day.\n
Permission "workflow:read" required.
\f
Parameters
----------
@@ -255,16 +322,17 @@ async def get_workflow_statistics(
authorization : Callable[[str], Awaitable[Any]]
Async function to ask the auth service for authorization. Dependency Injection.
response : fastapi.Response
Temporal Response object. Dependency Injection.
Temporary Response object. Dependency Injection.
Returns
-------
statistics : List[app.schema.Workflow.WorkflowStatistic]
statistics : List[app.schema.workflow.WorkflowStatistic]
List of datapoints aggregated by day.
"""
trace.get_current_span().set_attribute("workflow_id", str(workflow.workflow_id))
await authorization("read")
# Instruct client to cache response for 1 hour
response.headers["Cache-Control"] = "max-age=3600"
# Instruct client to cache response for 24 hour
response.headers["Cache-Control"] = "max-age=86400"
return await CRUDWorkflow.statistics(db, workflow.workflow_id)
Loading