Skip to content

Commit bfd2a66

Browse files
authored
feat: create new endpoint to retrieve summary of different alerts (#1209)
Closes: #1200
1 parent 58132ba commit bfd2a66

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

src/codegate/api/v1.py

+27
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,33 @@ async def get_workspace_alerts(workspace_name: str) -> List[Optional[v1_models.A
397397
raise HTTPException(status_code=500, detail="Internal server error")
398398

399399

400+
@v1.get(
401+
"/workspaces/{workspace_name}/alerts-summary",
402+
tags=["Workspaces"],
403+
generate_unique_id_function=uniq_name,
404+
)
405+
async def get_workspace_alerts_summary(workspace_name: str) -> v1_models.AlertSummary:
406+
"""Get alert summary for a workspace."""
407+
try:
408+
ws = await wscrud.get_workspace_by_name(workspace_name)
409+
except crud.WorkspaceDoesNotExistError:
410+
raise HTTPException(status_code=404, detail="Workspace does not exist")
411+
except Exception:
412+
logger.exception("Error while getting workspace")
413+
raise HTTPException(status_code=500, detail="Internal server error")
414+
415+
try:
416+
summary = await dbreader.get_alerts_summary_by_workspace(ws.id)
417+
return v1_models.AlertSummary(
418+
malicious_packages=summary["codegate_context_retriever_count"],
419+
pii=summary["codegate_pii_count"],
420+
secrets=summary["codegate_secrets_count"],
421+
)
422+
except Exception:
423+
logger.exception("Error while getting alerts summary")
424+
raise HTTPException(status_code=500, detail="Internal server error")
425+
426+
400427
@v1.get(
401428
"/workspaces/{workspace_name}/messages",
402429
tags=["Workspaces"],

src/codegate/api/v1_models.py

+10
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,16 @@ def from_db_model(db_model: db_models.Alert) -> "Alert":
190190
timestamp: datetime.datetime
191191

192192

193+
class AlertSummary(pydantic.BaseModel):
194+
"""
195+
Represents a set of summary alerts
196+
"""
197+
198+
malicious_packages: int
199+
pii: int
200+
secrets: int
201+
202+
193203
class PartialQuestionAnswer(pydantic.BaseModel):
194204
"""
195205
Represents a partial conversation.

src/codegate/db/connection.py

+32
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,38 @@ async def get_alerts_by_workspace(
746746
)
747747
return prompts
748748

749+
async def get_alerts_summary_by_workspace(self, workspace_id: str) -> dict:
750+
"""Get aggregated alert summary counts for a given workspace_id."""
751+
sql = text(
752+
"""
753+
SELECT
754+
COUNT(*) AS total_alerts,
755+
SUM(CASE WHEN a.trigger_type = 'codegate-secrets' THEN 1 ELSE 0 END)
756+
AS codegate_secrets_count,
757+
SUM(CASE WHEN a.trigger_type = 'codegate-context-retriever' THEN 1 ELSE 0 END)
758+
AS codegate_context_retriever_count,
759+
SUM(CASE WHEN a.trigger_type = 'codegate-pii' THEN 1 ELSE 0 END)
760+
AS codegate_pii_count
761+
FROM alerts a
762+
INNER JOIN prompts p ON p.id = a.prompt_id
763+
WHERE p.workspace_id = :workspace_id
764+
"""
765+
)
766+
conditions = {"workspace_id": workspace_id}
767+
768+
async with self._async_db_engine.begin() as conn:
769+
result = await conn.execute(sql, conditions)
770+
row = result.fetchone()
771+
772+
# Return a dictionary with counts (handling None values safely)
773+
return {
774+
"codegate_secrets_count": row.codegate_secrets_count or 0 if row else 0,
775+
"codegate_context_retriever_count": (
776+
row.codegate_context_retriever_count or 0 if row else 0
777+
),
778+
"codegate_pii_count": row.codegate_pii_count or 0 if row else 0,
779+
}
780+
749781
async def get_workspaces(self) -> List[WorkspaceWithSessionInfo]:
750782
sql = text(
751783
"""

0 commit comments

Comments
 (0)