add baseline and sqlite
This commit is contained in:
@@ -74,7 +74,10 @@ def _rate_per_minute(events: list[LogEvent]) -> tuple[float | None, float]:
|
||||
return len(timestamps) * 60 / max(1.0, duration_seconds), duration_seconds
|
||||
|
||||
|
||||
def detect_source_anomalies(events: list[LogEvent], *, limit: int = 20) -> list[AnomalyFinding]:
|
||||
def detect_source_anomalies(
|
||||
events: list[LogEvent], *, limit: int = 20, baselines: dict[str, dict[str, float | int]] | None = None
|
||||
) -> list[AnomalyFinding]:
|
||||
baselines = baselines or {}
|
||||
by_src: dict[str, list[LogEvent]] = defaultdict(list)
|
||||
for event in events:
|
||||
if event.src_ip:
|
||||
@@ -137,6 +140,12 @@ def detect_source_anomalies(events: list[LogEvent], *, limit: int = 20) -> list[
|
||||
points = min(25, 10 + int(rate_z * 5))
|
||||
score += points
|
||||
reasons.append(f"unusually high log rate ({event_rate:.1f} events/min, z={rate_z:.1f})")
|
||||
baseline = baselines.get(src_ip)
|
||||
if baseline:
|
||||
historical_z = (event_rate - float(baseline["event_rate_mean"])) / float(baseline["event_rate_stddev"])
|
||||
if historical_z >= 3:
|
||||
score += min(25, 10 + int(historical_z * 3))
|
||||
reasons.append(f"log rate exceeds its {baseline['samples']}-window baseline (z={historical_z:.1f})")
|
||||
|
||||
dst_z = (distinct_dst - avg_dst) / std_dst
|
||||
if distinct_dst >= 10 and dst_z >= 2:
|
||||
@@ -155,6 +164,13 @@ def detect_source_anomalies(events: list[LogEvent], *, limit: int = 20) -> list[
|
||||
points = min(15, 5 + int(hitcount_z * 3))
|
||||
score += points
|
||||
reasons.append(f"unusually high policy hitcount ({total_hitcount}, max event value {max_hitcount})")
|
||||
if event_rate is not None and observed_duration > 0 and src_ip in baselines:
|
||||
hit_rate = total_hitcount * 60 / max(1.0, observed_duration)
|
||||
baseline = baselines[src_ip]
|
||||
historical_z = (hit_rate - float(baseline["hitcount_rate_mean"])) / float(baseline["hitcount_rate_stddev"])
|
||||
if total_hitcount >= 10 and historical_z >= 3:
|
||||
score += min(15, 5 + int(historical_z * 2))
|
||||
reasons.append(f"hitcount rate exceeds its historical baseline (z={historical_z:.1f})")
|
||||
|
||||
if event_count >= 5:
|
||||
deny_rate = deny_count / event_count
|
||||
|
||||
Reference in New Issue
Block a user