File size: 8,672 Bytes
45ab2bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
"""
Database models for alerts, incidents, and analyses
"""
from sqlalchemy import Column, String, Integer, Float, DateTime, Boolean, Enum, ForeignKey, JSON, Text
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID
import uuid
from datetime import datetime
import enum

from src.database import Base


class AlertSeverity(str, enum.Enum):
    """Alert severity levels"""
    CRITICAL = "CRITICAL"
    HIGH = "HIGH"
    MEDIUM = "MEDIUM"
    LOW = "LOW"
    INFO = "INFO"


class AlertStatus(str, enum.Enum):
    """Alert status"""
    NEW = "NEW"
    ACKNOWLEDGED = "ACKNOWLEDGED"
    RESOLVED = "RESOLVED"
    SUPPRESSED = "SUPPRESSED"


class IncidentSeverity(str, enum.Enum):
    """Incident severity levels"""
    CRITICAL = "CRITICAL"
    HIGH = "HIGH"
    MEDIUM = "MEDIUM"
    LOW = "LOW"


class IncidentStatus(str, enum.Enum):
    """Incident status"""
    OPEN = "OPEN"
    IN_PROGRESS = "IN_PROGRESS"
    RESOLVED = "RESOLVED"
    CLOSED = "CLOSED"


class IncidentEventType(str, enum.Enum):
    """Types of incident events"""
    CREATED = "CREATED"
    UPDATED = "UPDATED"
    ANALYZED = "ANALYZED"
    RECOMMENDED = "RECOMMENDED"
    ACKNOWLEDGED = "ACKNOWLEDGED"
    RESOLVED = "RESOLVED"
    ESCALATED = "ESCALATED"
    COMMENTED = "COMMENTED"


class AnalysisType(str, enum.Enum):
    """Types of LLM analysis"""
    CLASSIFICATION = "CLASSIFICATION"
    ROOT_CAUSE = "ROOT_CAUSE"
    RECOMMENDATION = "RECOMMENDATION"


class Alert(Base):
    """Alert model"""
    __tablename__ = "alerts"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    source = Column(String(100), nullable=False, index=True)
    source_id = Column(String(255), nullable=False)
    title = Column(String(255), nullable=False)
    description = Column(Text)
    severity = Column(Enum(AlertSeverity), nullable=False, index=True)
    status = Column(Enum(AlertStatus), default=AlertStatus.NEW, nullable=False, index=True)
    
    # Categorization
    category = Column(String(100))
    affected_service = Column(JSON)  # List of services
    affected_component = Column(String(255))
    tags = Column(JSON, default=[])
    
    # Fingerprint for deduplication
    fingerprint = Column(String(255), nullable=False, unique=True, index=True)
    
    # Metrics and metadata
    metrics = Column(JSON)
    metadata = Column(JSON)
    remediation_hints = Column(JSON)
    
    # Relationships
    incident_id = Column(UUID(as_uuid=True), ForeignKey("incidents.id"))
    incident = relationship("Incident", back_populates="alerts")
    
    # Timestamps
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    resolved_at = Column(DateTime)

    def __repr__(self):
        return f"<Alert {self.id}: {self.title}>"


class Incident(Base):
    """Incident model"""
    __tablename__ = "incidents"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    title = Column(String(255), nullable=False)
    description = Column(Text)
    
    # Classification
    severity = Column(Enum(IncidentSeverity), nullable=False, index=True)
    status = Column(Enum(IncidentStatus), default=IncidentStatus.OPEN, nullable=False, index=True)
    category = Column(String(100))
    
    # Impact
    impact_summary = Column(Text)
    affected_services = Column(JSON, default=[])
    estimated_users_impacted = Column(Integer)
    business_impact = Column(String(50))  # High, Medium, Low
    
    # Root cause and analysis
    root_cause = Column(Text)
    root_cause_confidence = Column(Float)
    
    # Resolution
    assigned_to = Column(String(255))
    resolved_at = Column(DateTime)
    resolution_time_minutes = Column(Integer)
    
    # Relationships
    alerts = relationship("Alert", back_populates="incident")
    events = relationship("IncidentEvent", back_populates="incident", cascade="all, delete-orphan")
    analyses = relationship("IncidentAnalysis", back_populates="incident", cascade="all, delete-orphan")
    recommendations = relationship("IncidentRecommendation", back_populates="incident", cascade="all, delete-orphan")
    
    # Timestamps
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    def __repr__(self):
        return f"<Incident {self.id}: {self.title}>"


class IncidentEvent(Base):
    """Timeline event for an incident"""
    __tablename__ = "incident_events"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    incident_id = Column(UUID(as_uuid=True), ForeignKey("incidents.id"), nullable=False)
    incident = relationship("Incident", back_populates="events")
    
    event_type = Column(Enum(IncidentEventType), nullable=False, index=True)
    message = Column(Text, nullable=False)
    actor = Column(String(255))  # SYSTEM or user email
    details = Column(JSON)
    
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)

    def __repr__(self):
        return f"<IncidentEvent {self.id}: {self.event_type}>"


class IncidentAnalysis(Base):
    """LLM analysis results for an incident"""
    __tablename__ = "llm_analyses"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    incident_id = Column(UUID(as_uuid=True), ForeignKey("incidents.id"), nullable=False)
    incident = relationship("Incident", back_populates="analyses")
    
    analysis_type = Column(Enum(AnalysisType), nullable=False, index=True)
    model_used = Column(String(100), nullable=False)
    
    # Prompt and response
    prompt = Column(Text)
    response = Column(Text)
    response_json = Column(JSON)
    
    # Confidence
    confidence_score = Column(Float)
    
    # Metadata
    tokens_used = Column(Integer)
    latency_ms = Column(Integer)
    
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)

    def __repr__(self):
        return f"<IncidentAnalysis {self.id}: {self.analysis_type}>"


class IncidentRecommendation(Base):
    """Recommended actions for an incident"""
    __tablename__ = "incident_recommendations"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    incident_id = Column(UUID(as_uuid=True), ForeignKey("incidents.id"), nullable=False)
    incident = relationship("Incident", back_populates="recommendations")
    
    priority = Column(String(50))  # CRITICAL, HIGH, MEDIUM, LOW
    phase = Column(String(50))  # immediate, investigation, remediation, prevention
    
    recommendation = Column(String(255), nullable=False)
    description = Column(Text)
    
    estimated_time = Column(String(100))
    risk_level = Column(String(50))  # Critical, High, Medium, Low
    success_criteria = Column(Text)
    
    # Status
    status = Column(String(50), default="PENDING")  # PENDING, IN_PROGRESS, COMPLETED, SKIPPED
    executed_at = Column(DateTime)
    executed_by = Column(String(255))
    
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    def __repr__(self):
        return f"<IncidentRecommendation {self.id}: {self.recommendation}>"


class NotificationLog(Base):
    """Log of sent notifications"""
    __tablename__ = "notification_logs"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    incident_id = Column(UUID(as_uuid=True), ForeignKey("incidents.id"))
    
    channel = Column(String(50), nullable=False)  # email, slack, webhook, etc
    recipient = Column(String(255), nullable=False)
    subject = Column(String(255))
    body = Column(Text)
    
    status = Column(String(50), default="SENT")  # SENT, FAILED, BOUNCED
    error_message = Column(Text)
    
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)

    def __repr__(self):
        return f"<NotificationLog {self.id}: {self.channel} to {self.recipient}>"


class AuditLog(Base):
    """Audit log for user actions"""
    __tablename__ = "audit_logs"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    
    user = Column(String(255), nullable=False)
    action = Column(String(255), nullable=False)
    resource_type = Column(String(100))
    resource_id = Column(String(255))
    
    changes = Column(JSON)
    
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)

    def __repr__(self):
        return f"<AuditLog {self.id}: {self.action}>"