From d948a1cc770539e7f3726245f3976f07b515bc6c Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Tue, 26 Nov 2024 11:48:08 +0200 Subject: [PATCH] feat: better stats --- lnbits/core/crud/audit.py | 64 ++++---------------------- lnbits/core/migrations.py | 3 +- lnbits/core/models/audit.py | 3 ++ lnbits/core/templates/audit/index.html | 7 ++- lnbits/core/views/audit_api.py | 10 ++-- 5 files changed, 24 insertions(+), 63 deletions(-) diff --git a/lnbits/core/crud/audit.py b/lnbits/core/crud/audit.py index 9c40d2673..65003157a 100644 --- a/lnbits/core/crud/audit.py +++ b/lnbits/core/crud/audit.py @@ -29,11 +29,6 @@ async def get_audit_entries( async def delete_expired_audit_entries( conn: Optional[Connection] = None, ): - q = f""" - DELETE from audit - WHERE delete_at < {db.timestamp_now} - """ - print("### q", q) await (conn or db).execute( f""" DELETE from audit @@ -42,70 +37,29 @@ async def delete_expired_audit_entries( ) -async def get_request_method_stats( +async def get_count_stats( + field: str, filters: Optional[Filters[AuditFilters]] = None, conn: Optional[Connection] = None, ) -> list[AuditCountStat]: + if field not in ["request_method", "component", "response_code"]: + return [] if not filters: filters = Filters() clause = filters.where() - request_methods = await (conn or db).fetchall( + data = await (conn or db).fetchall( query=f""" - SELECT request_method as field, count(request_method) as total + SELECT {field} as field, count({field}) as total FROM audit {clause} - GROUP BY request_method - ORDER BY request_method + GROUP BY {field} + ORDER BY {field} """, values=filters.values(), model=AuditCountStat, ) - return request_methods - - -async def get_component_stats( - filters: Optional[Filters[AuditFilters]] = None, - conn: Optional[Connection] = None, -) -> list[AuditCountStat]: - if not filters: - filters = Filters() - clause = filters.where() - components = await (conn or db).fetchall( - query=f""" - SELECT component as field, count(component) as total - FROM audit - {clause} - GROUP BY component - ORDER BY component - """, - values=filters.values(), - model=AuditCountStat, - ) - - return components - - -async def get_response_codes_stats( - filters: Optional[Filters[AuditFilters]] = None, - conn: Optional[Connection] = None, -) -> list[AuditCountStat]: - if not filters: - filters = Filters() - clause = filters.where() - request_methods = await (conn or db).fetchall( - query=f""" - SELECT response_code as field, count(response_code) as total - FROM audit - {clause} - GROUP BY response_code - ORDER BY response_code - """, - values=filters.values(), - model=AuditCountStat, - ) - - return request_methods + return data async def get_long_duration_stats( diff --git a/lnbits/core/migrations.py b/lnbits/core/migrations.py index 95249c47a..c185861a2 100644 --- a/lnbits/core/migrations.py +++ b/lnbits/core/migrations.py @@ -681,7 +681,8 @@ async def m029_create_audit_table(db): response_code TEXT, duration REAL NOT NULL, delete_at TIMESTAMP, - created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now} + created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, + created_at_minute INT NOT NULL ); """ ) diff --git a/lnbits/core/models/audit.py b/lnbits/core/models/audit.py index 3fdb890ce..a28273b74 100644 --- a/lnbits/core/models/audit.py +++ b/lnbits/core/models/audit.py @@ -22,6 +22,9 @@ class AuditEntry(BaseModel): duration: float delete_at: Optional[datetime] = None created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) + created_at_minute: int = Field( + default_factory=lambda: int(datetime.now(timezone.utc).timestamp() / 60) + ) def __init__(self, **data): super().__init__(**data) diff --git a/lnbits/core/templates/audit/index.html b/lnbits/core/templates/audit/index.html index 542186f38..c2cf2c1c2 100644 --- a/lnbits/core/templates/audit/index.html +++ b/lnbits/core/templates/audit/index.html @@ -124,7 +124,12 @@ - + diff --git a/lnbits/core/views/audit_api.py b/lnbits/core/views/audit_api.py index 9ac35b148..1e38726c4 100644 --- a/lnbits/core/views/audit_api.py +++ b/lnbits/core/views/audit_api.py @@ -2,10 +2,8 @@ from fastapi import APIRouter, Depends from lnbits.core.crud.audit import ( get_audit_entries, - get_component_stats, + get_count_stats, get_long_duration_stats, - get_request_method_stats, - get_response_codes_stats, ) from lnbits.core.models import AuditEntry, AuditFilters from lnbits.core.models.audit import AuditStats @@ -39,9 +37,9 @@ async def api_get_audit( async def api_get_audit_stats( filters: Filters = Depends(parse_filters(AuditFilters)), ) -> AuditStats: - request_mothod_stats = await get_request_method_stats(filters) - response_code_stats = await get_response_codes_stats(filters) - components_stats = await get_component_stats(filters) + request_mothod_stats = await get_count_stats("request_method", filters) + response_code_stats = await get_count_stats("response_code", filters) + components_stats = await get_count_stats("component", filters) long_duration_stats = await get_long_duration_stats(filters) return AuditStats( request_method=request_mothod_stats,