2025-09-15 23:25:11 +02:00
"""
Stats resource for the OpenEventDatabase .
"""
import subprocess
import falcon
import psycopg2 . extras
from oedb . utils . db import db_connect
from oedb . utils . serialization import dumps
from oedb . utils . logging import logger
class StatsResource :
"""
Resource for retrieving database statistics .
Handles the / stats endpoint .
"""
def on_get ( self , req , resp ) :
"""
Handle GET requests to the / stats endpoint .
Args :
req : The request object .
resp : The response object .
"""
logger . info ( " Processing GET request to /stats " )
db = db_connect ( )
cur = db . cursor ( cursor_factory = psycopg2 . extras . DictCursor )
try :
# Estimated row count, way faster than count(*)
cur . execute ( " SELECT reltuples::bigint FROM pg_class r WHERE relname = ' events ' ; " )
count = cur . fetchone ( ) [ 0 ]
logger . debug ( f " Estimated event count: { count } " )
2025-09-18 22:30:25 +02:00
# If the estimated count is negative, fall back to an actual count
if count < 0 :
logger . warning ( f " Estimated event count is negative ( { count } ), falling back to COUNT(*) " )
cur . execute ( " SELECT COUNT(*) FROM events; " )
count = cur . fetchone ( ) [ 0 ]
logger . debug ( f " Actual event count: { count } " )
2025-09-15 23:25:11 +02:00
# Global info
cur . execute ( " SELECT max(lastupdate) as last_updated, current_timestamp-pg_postmaster_start_time() from events; " )
pg_stats = cur . fetchone ( )
last = pg_stats [ 0 ]
pg_uptime = pg_stats [ 1 ]
uptime = subprocess . check_output ( [ " uptime " , " -p " ] ) . decode ( ' utf-8 ' ) [ 0 : - 1 ]
# Summary about last 10000 events (what, last, count, sources)
cur . execute ( " SELECT row_to_json(stat) from (SELECT events_what as what, left(max(upper(events_when))::text,19) as last, count(*) as count, array_agg(distinct(regexp_replace(regexp_replace(events_tags ->> ' source ' , ' ^(http://|https://) ' , ' ' ), ' /.* ' , ' ' ))) as source from (select * from events order by lastupdate desc limit 10000) as last group by 1 order by 2 desc) as stat; " )
recent = cur . fetchall ( )
2025-09-15 23:54:04 +02:00
resp . text = dumps ( dict ( events_count = count , last_updated = last , uptime = uptime , db_uptime = pg_uptime , recent = recent ) )
2025-09-15 23:25:11 +02:00
resp . status = falcon . HTTP_200
logger . success ( " Successfully processed GET request to /stats " )
except Exception as e :
logger . error ( f " Error processing GET request to /stats: { e } " )
resp . status = falcon . HTTP_500
2025-09-15 23:54:04 +02:00
resp . text = dumps ( { " error " : str ( e ) } )
2025-09-15 23:25:11 +02:00
finally :
cur . close ( )
db . close ( )