Initial commit: Log Analyzer Backend
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
from typing import List, Dict, Any
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from models import LogEntry
|
||||
|
||||
class StatsAnalyzer:
|
||||
@staticmethod
|
||||
async def overview(session: AsyncSession) -> Dict[str, Any]:
|
||||
total = (await session.execute(select(func.count()).select_from(LogEntry))).scalar() or 0
|
||||
fw = (await session.execute(
|
||||
select(func.count()).select_from(LogEntry).where(LogEntry.log_type == "firewall")
|
||||
)).scalar() or 0
|
||||
px = (await session.execute(
|
||||
select(func.count()).select_from(LogEntry).where(LogEntry.log_type == "proxy")
|
||||
)).scalar() or 0
|
||||
return {
|
||||
"total_entries": total,
|
||||
"firewall_entries": fw,
|
||||
"proxy_entries": px,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
async def top_sources(session: AsyncSession, limit: int = 20) -> List[Dict[str, Any]]:
|
||||
stmt = (
|
||||
select(LogEntry.source_ip, func.count().label("cnt"))
|
||||
.where(LogEntry.source_ip.isnot(None))
|
||||
.group_by(LogEntry.source_ip)
|
||||
.order_by(func.count().desc())
|
||||
.limit(limit)
|
||||
)
|
||||
rows = await session.execute(stmt)
|
||||
return [{"source_ip": r[0], "count": r[1]} for r in rows]
|
||||
|
||||
@staticmethod
|
||||
async def top_destinations(session: AsyncSession, limit: int = 20) -> List[Dict[str, Any]]:
|
||||
stmt = (
|
||||
select(LogEntry.destination_ip, func.count().label("cnt"))
|
||||
.where(LogEntry.destination_ip.isnot(None))
|
||||
.group_by(LogEntry.destination_ip)
|
||||
.order_by(func.count().desc())
|
||||
.limit(limit)
|
||||
)
|
||||
rows = await session.execute(stmt)
|
||||
return [{"destination_ip": r[0], "count": r[1]} for r in rows]
|
||||
|
||||
@staticmethod
|
||||
async def top_ports(session: AsyncSession, limit: int = 20) -> List[Dict[str, Any]]:
|
||||
stmt = (
|
||||
select(LogEntry.destination_port, func.count().label("cnt"))
|
||||
.where(LogEntry.destination_port.isnot(None))
|
||||
.group_by(LogEntry.destination_port)
|
||||
.order_by(func.count().desc())
|
||||
.limit(limit)
|
||||
)
|
||||
rows = await session.execute(stmt)
|
||||
return [{"destination_port": r[0], "count": r[1]} for r in rows]
|
||||
|
||||
@staticmethod
|
||||
async def top_urls(session: AsyncSession, limit: int = 20) -> List[Dict[str, Any]]:
|
||||
stmt = (
|
||||
select(LogEntry.url, func.count().label("cnt"))
|
||||
.where(LogEntry.url.isnot(None))
|
||||
.group_by(LogEntry.url)
|
||||
.order_by(func.count().desc())
|
||||
.limit(limit)
|
||||
)
|
||||
rows = await session.execute(stmt)
|
||||
return [{"url": r[0], "count": r[1]} for r in rows]
|
||||
|
||||
@staticmethod
|
||||
async def action_distribution(session: AsyncSession) -> List[Dict[str, Any]]:
|
||||
stmt = (
|
||||
select(LogEntry.action, func.count().label("cnt"))
|
||||
.where(LogEntry.action.isnot(None))
|
||||
.group_by(LogEntry.action)
|
||||
.order_by(func.count().desc())
|
||||
)
|
||||
rows = await session.execute(stmt)
|
||||
return [{"action": r[0], "count": r[1]} for r in rows]
|
||||
|
||||
@staticmethod
|
||||
async def timeline(session: AsyncSession, granularity: str = "hour") -> List[Dict[str, Any]]:
|
||||
if granularity == "hour":
|
||||
fmt = "%Y-%m-%d %H:00"
|
||||
else:
|
||||
fmt = "%Y-%m-%d"
|
||||
# SQLite strftime
|
||||
stmt = (
|
||||
select(func.strftime(fmt, LogEntry.timestamp).label("bucket"), func.count().label("cnt"))
|
||||
.where(LogEntry.timestamp.isnot(None))
|
||||
.group_by("bucket")
|
||||
.order_by("bucket")
|
||||
)
|
||||
rows = await session.execute(stmt)
|
||||
return [{"time_bucket": r[0], "count": r[1]} for r in rows]
|
||||
|
||||
@staticmethod
|
||||
async def unique_counts(session: AsyncSession) -> Dict[str, int]:
|
||||
src = (await session.execute(
|
||||
select(func.count(func.distinct(LogEntry.source_ip)))
|
||||
)).scalar() or 0
|
||||
dst = (await session.execute(
|
||||
select(func.count(func.distinct(LogEntry.destination_ip)))
|
||||
)).scalar() or 0
|
||||
return {"unique_sources": src, "unique_destinations": dst}
|
||||
Reference in New Issue
Block a user