File size: 3,552 Bytes
a28cff7 ce17628 a28cff7 ce17628 a28cff7 58debbc a28cff7 58debbc a28cff7 58debbc a28cff7 4819352 a28cff7 58debbc a28cff7 37fcd19 a28cff7 58debbc a28cff7 69812a2 58debbc 69812a2 a28cff7 58debbc a28cff7 58debbc a28cff7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | from __future__ import annotations
"""
Behavioral ์ด๋ฒคํธ ๊ณต์ ์ ์ฅ์ (์๋๋ฆฌ์ค ๋ฌด๊ด).
์ธ์
๋ณ ํ๋ ์ด๋ฒคํธ๋ฅผ ๋์ ํ๊ณ 5๋ถ window๋ก ์กฐํํ๋ค.
Pattern Feature ์ฐ์ถ(์๋๋ฆฌ์ค๋ณ ์ง๊ณ)์ ๊ฐ ์์ง(cs/bundle/worker)์ด ๋ด๋น.
"""
from datetime import datetime, timedelta
from typing import Any
def _now() -> datetime:
"""ํ์ฌ UTC ์๊ฐ์ ๋ฐํํ๋ค (์ด๋ฒคํธ ํ์์คํฌํยทwindow ์ปท์คํ ๊ธฐ์ค).
Returns:
ํ์ฌ UTC datetime.
"""
return datetime.utcnow()
class BehavioralPatternExtractor:
"""์ธ์
๋ณ ํ๋ ์ด๋ฒคํธ๋ฅผ ๋์ ํ๊ณ window ๋จ์๋ก ์กฐํํ๋ค.
WebSocket ์ธ์
๋จ์๋ก ์ธ์คํด์ค๋ฅผ ๋ณด์กดํ๋ฉฐ, ๋งค ํ๋๋ง๋ค add_event()๋ฅผ ํธ์ถํ๋ค.
Pattern Feature ์ฐ์ถ์ ๊ฐ ์๋๋ฆฌ์ค ์์ง์ด ๋ด๋นํ๋ค.
"""
def __init__(self) -> None:
self._events_by_session: dict[str, list[dict[str, Any]]] = {}
def add_event(
self,
session_id: str,
event_type: str,
entity: str,
occurred_at: datetime | None = None,
) -> None:
"""์ธ์
์ ํ๋ ์ด๋ฒคํธ 1๊ฑด์ ๋์ ํ๋ค.
Args:
session_id: ์ด๋ฒคํธ๋ฅผ ๋์ ํ ์ธ์
ID.
event_type: ์ด๋ฒคํธ ์ข
๋ฅ.
entity: ์ด๋ฒคํธ ๋์ ์ํฐํฐ.
occurred_at: ์ด๋ฒคํธ ๋ฐ์ ์๊ฐ. ๋ฏธ์ง์ ์ ํ์ฌ UTC.
"""
ts = occurred_at or _now()
self._events_by_session.setdefault(session_id, []).append({
"event_type": event_type,
"entity": entity,
"occurred_at": ts,
})
def events_within(
self,
session_id: str,
window_seconds: int = 300,
) -> list[dict[str, Any]]:
"""์ธ์
์ ์ต๊ทผ window ๋ด ์ด๋ฒคํธ๋ฅผ ์กฐํํ๋ค.
์์ง๋ณ Pattern ๊ณ์ฐ ์
๋ ฅ์ผ๋ก ์ฌ์ฉ๋๋ค.
Args:
session_id: ์กฐํํ ์ธ์
ID.
window_seconds: ์ปท์คํ window ๊ธธ์ด(์ด).
Returns:
์ปท์คํ ์ดํ ๋ฐ์ํ ์ด๋ฒคํธ ๋ฆฌ์คํธ.
"""
events = self._events_by_session.get(session_id, [])
cutoff = _now() - timedelta(seconds=window_seconds)
return [e for e in events if e["occurred_at"] >= cutoff]
def recent_events(self, session_id: str, n: int) -> list[dict[str, Any]]:
"""์ธ์
์ ์ต๊ทผ n๊ฐ ์ด๋ฒคํธ๋ฅผ ์กฐํํ๋ค (ํด๋ฆญ ๊ธฐ๋ฐ ์๋์ฐ).
Args:
session_id: ์กฐํํ ์ธ์
ID.
n: ์กฐํํ ์ต๊ทผ ์ด๋ฒคํธ ๊ฐ์. 0 ์ดํ์ด๋ฉด ์ ์ฒด.
Returns:
์ต๊ทผ n๊ฐ ์ด๋ฒคํธ ๋ฆฌ์คํธ.
"""
events = self._events_by_session.get(session_id, [])
return events[-n:] if n and n > 0 else list(events)
def reset(self, session_id: str) -> None:
"""์ธ์
์ ๋์ ์ด๋ฒคํธ๋ฅผ ์ ๊ฑฐํ๋ค.
Args:
session_id: ์ด๊ธฐํํ ์ธ์
ID.
"""
self._events_by_session.pop(session_id, None)
# โโ ์ฑ๊ธํค ์ธ์คํด์ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
_extractor: BehavioralPatternExtractor | None = None
def get_extractor() -> BehavioralPatternExtractor:
"""๊ณต์ ์ด๋ฒคํธ ์ ์ฅ์ ์ฑ๊ธํค์ ๋ฐํํ๋ค.
Returns:
ํ๋ก์ธ์ค ์ ์ญ BehavioralPatternExtractor ์ธ์คํด์ค.
"""
global _extractor
if _extractor is None:
_extractor = BehavioralPatternExtractor()
return _extractor
|